/**
 * @module conflict-optimistic
 *
 * Implements the Optimistic Conflict Resolution Strategy.
 *
 * Logic:
 * 1. findLCA: Traverses `past` to find common ancestor.
 * 2. mergeDivergentTimelines: Replays DNA to create a merged tip.
 */
import { getIbGibAddr } from '@ibgib/ts-gib/dist/helper.mjs';
import { getFromSpace } from '../../witness/space/space-helper.mjs';
const lc = `[conflict-optimistic]`;
/**
 * Finds the Last Common Ancestor (LCA) between two divergent timelines.
 *
 * Note: simplistic implementation assuming simple linear divergence.
 * Complex DAGs might require more robust graph traversal.
 */
export async function findLCA({ tipA, tipB, space, }) {
    // 1. Load history for both
    // Optimization: Just load 'past' array if available.
    // Ideally we assume 'past' is full history for V1.
    // Check if one is ancestor of another first?
    const pastA = tipA.rel8ns?.past || [];
    const pastB = tipB.rel8ns?.past || [];
    const addrA = getIbGibAddr({ ibGib: tipA });
    const addrB = getIbGibAddr({ ibGib: tipB });
    // Is B in A's past?
    if (pastA.includes(addrB)) {
        return { lcaAddr: addrB, branchA: [], branchB: [] };
    } // Not a divergence, just an update.
    // Is A in B's past?
    if (pastB.includes(addrA)) {
        return { lcaAddr: addrA, branchA: [], branchB: [] };
    }
    // Find intersection
    let lcaAddr;
    // Iterate backwards through A's past
    // The *latest* entry in A's past that is also in B's past (or is B itself, but we checked that)
    // Actually, 'past' is usually ordered? V1 convention is accretive, so order matches evolution.
    // But 'past' array order isn't strictly guaranteed by schema to be chronological, but robust implementations do so.
    // Let's assume Set intersection.
    const setPastB = new Set(pastB);
    // Find the *latest* item in pastA that is in setPastB.
    // We assume pastA is ordered [older -> newer].
    for (let i = pastA.length - 1; i >= 0; i--) {
        const candidate = pastA[i];
        if (setPastB.has(candidate)) {
            lcaAddr = candidate;
            break;
        }
    }
    if (!lcaAddr) {
        // Fallback: check if they share the SAME TJP (they should if they are same timeline).
        // If they share TJP but no common past, the TJP itself is the LCA.
        const tjpA = tipA.rel8ns?.tjp?.[0];
        const tjpB = tipB.rel8ns?.tjp?.[0];
        if (tjpA && tjpA === tjpB) {
            lcaAddr = tjpA;
        }
        else {
            throw new Error(`No LCA found for divergences. Are they the same timeline? (E: 81aa17f0e34b4138ad1743a60a76f27b)`);
        }
    }
    // 2. Reconstruct Branches
    // We need the actual ibGib objects from LCA to Tips to inspect DNA.
    // This requires fetching from Space.
    // Helper to get path from LCA to Tip
    const getPath = async (tip, past, lca) => {
        const pathAddrs = [];
        let foundLca = false;
        for (const addr of past) {
            if (foundLca) {
                pathAddrs.push(addr);
            }
            else if (addr === lca) {
                foundLca = true;
            }
        }
        pathAddrs.push(getIbGibAddr({ ibGib: tip }));
        // Fetch all
        const res = await getFromSpace({ space, addrs: pathAddrs });
        if (!res.success || !res.ibGibs) {
            throw new Error(`Failed to fetch history branch. (E: 7904097405be4a27b871c5031631553c)`);
        }
        return res.ibGibs;
    };
    const branchA = await getPath(tipA, pastA, lcaAddr);
    const branchB = await getPath(tipB, pastB, lcaAddr);
    return { lcaAddr, branchA, branchB };
}
import { graftTimelines } from '../graft-info/graft-info-helpers.mjs';
/**
 * Optimistically grafts two divergent timelines by inspecting DNA and replaying transforms.
 */
export async function mergeDivergentTimelines({ tipA, tipB, space, metaspace, }) {
    const lc = `[${mergeDivergentTimelines.name}]`;
    // 1. Find LCA & Branches
    const { lcaAddr, branchA, branchB } = await findLCA({ tipA, tipB, space });
    // 2. Delegate to Graft Engine
    // The graft engine handles timestamp verification, DNA fetching, replay, and Stone creation.
    const result = await graftTimelines({
        tipA,
        branchA,
        tipB,
        branchB,
        space,
        metaspace,
    });
    return result;
}
//# sourceMappingURL=conflict-optimistic.mjs.map