import { extractErrorMsg } from "@ibgib/helper-gib/dist/helpers/utils-helper.mjs";
import { GLOBAL_LOG_A_LOT } from "../core-constants.mjs";
import { SYNC_ATOM, SYNC_MSG_REL8N_NAME } from "./sync-constants.mjs";
import { getFromSpace } from "../witness/space/space-helper.mjs";
const logalot = GLOBAL_LOG_A_LOT;
/**
 * Constructs the standard 'ib' string for a Sync frame.
 */
/**
 * Constructs the standard 'ib' string for a Sync frame.
 */
export async function getSyncIb({ data, }) {
    const lc = `[${getSyncIb.name}]`;
    try {
        // sync uuid
        // e.g. "sync 1234-5678" (stage removed from ib)
        const ib = [
            SYNC_ATOM,
            data.uuid
        ].join(' ');
        return ib;
    }
    catch (error) {
        console.error(`${lc} ${extractErrorMsg(error)}`);
        throw error;
    }
}
/**
 * Parses a standard Sync 'ib' string.
 */
export async function parseSyncIb({ ib, }) {
    const lc = `[${parseSyncIb.name}]`;
    try {
        const parts = ib.split(' ');
        if (parts.length !== 2) {
            throw new Error(`Invalid sync ib. Expected 2 parts [atom uuid]. Got ${parts.length}. (E: 7db603e0dcf8c35af826cce89a125825)`);
        }
        const [atom, uuid] = parts;
        if (atom !== SYNC_ATOM) {
            throw new Error(`Atom mismatch. Expected ${SYNC_ATOM}. Got ${atom}.`);
        }
        return { atom, uuid };
    }
    catch (error) {
        console.error(`${lc} ${extractErrorMsg(error)}`);
        throw error;
    }
}
/**
 * Checks if an address (`olderAddr`) is in the past frames of another (`newerAddr`).
 *
 * Efficiently uses `inMemoryGraph` if provided to avoid Space I/O.
 * Otherwise falls back to traversing using `space`.
 */
export async function isPastFrame({ olderAddr, newerAddr, space, inMemoryGraph, }) {
    if (olderAddr === newerAddr)
        return true;
    // Quick check if optimization allowed
    if (inMemoryGraph) {
        // Optimization: Iterate the graph values (or keys) and see if olderAddr is in any 'past'
        // Actually we need to traverse from newerAddr back to olderAddr using the graph.
        const queue = [newerAddr];
        const visited = new Set();
        while (queue.length > 0) {
            const currentAddr = queue.shift();
            if (visited.has(currentAddr))
                continue;
            visited.add(currentAddr);
            if (currentAddr === olderAddr)
                return true;
            const node = inMemoryGraph[currentAddr];
            // If node not in memory graph, we can't traverse further in memory.
            // If we have space, we could fallback, but usually mixed mode is tricky.
            // For now, if provided inMemoryGraph, assume it contains the relevant segment.
            if (!node && space) {
                // optional fallback to space if allowed?
                // User requirement: "at most we are looking... in dependency graph". 
                // So let's fallback if space provided.
                const res = await getFromSpace({ space, addr: currentAddr });
                if (res.success && res.ibGibs?.length) {
                    const spaceNode = res.ibGibs[0];
                    if (spaceNode.rel8ns && spaceNode.rel8ns.past) {
                        for (const pastAddr of spaceNode.rel8ns.past) {
                            if (!visited.has(pastAddr))
                                queue.push(pastAddr);
                        }
                    }
                }
                continue;
            }
            else if (!node) {
                continue; // Dead end in memory
            }
            if (node.rel8ns && node.rel8ns.past) {
                for (const pastAddr of node.rel8ns.past) {
                    if (!visited.has(pastAddr))
                        queue.push(pastAddr);
                }
            }
        }
        return false;
    }
    // Fallback to purely space-based traversal if no memory graph
    if (!space) {
        throw new Error(`Must provide either space or inMemoryGraph for ancestry check.`);
    }
    const queue = [newerAddr];
    const visited = new Set();
    while (queue.length > 0) {
        const currentAddr = queue.shift();
        if (visited.has(currentAddr))
            continue;
        visited.add(currentAddr);
        if (currentAddr === olderAddr)
            return true;
        const res = await getFromSpace({ space, addr: currentAddr });
        if (!res.success || !res.ibGibs || res.ibGibs.length === 0)
            continue;
        const node = res.ibGibs[0];
        if (node.rel8ns && node.rel8ns.past) {
            for (const pastAddr of node.rel8ns.past) {
                if (!visited.has(pastAddr))
                    queue.push(pastAddr);
            }
        }
    }
    return false;
}
/**
 * Gets a shallow dependency graph for a Sync Saga Frame.
 *
 * DOES NOT GET THE ENTIRE DEPENDENCY FRAME (INCLUDING PAST).
 *
 * Unlike standard `getDependencyGraph`, this does NOT traverse `ancestor` (history) or `past`.
 * It only retrieves the *content* of the current frame:
 * 1. The Frame itself.
 * 2. The Message Stone(s) (`rel8ns.msg`).
 * 3. The Identity (`rel8ns.identity`).
 *
 * This is used for efficient transmission of the "Current Step" without re-sending the entire history.
 */
export async function getSyncSagaDependencyGraph({ ibGib, space, }) {
    const lc = `[${getSyncSagaDependencyGraph.name}]`;
    const result = [ibGib];
    // Helper to fetch and push
    const fetchAndPush = async (addrs) => {
        const res = await getFromSpace({ space, addrs });
        if (res.success && res.ibGibs?.length === addrs.length) {
            res.ibGibs.forEach(x => result.push(x));
        }
        else {
            const resIbGib = res.rawResultIbGib;
            if (!resIbGib.data) {
                throw new Error(`(UNEXPECTED) res.rawResultIbGib.data falsy? (E: c26c681d2f831fc537ba6f48fee36d26)`);
            }
            throw new Error(`(UNEXPECTED) couldn't find addrs? addrsNotFound: ${resIbGib.data.addrsNotFound}? (E: 43b7b5a6ad982715c8f3eed69bfa0d26)`);
        }
    };
    if (ibGib.rel8ns) {
        // 1. Message Stones (Payload of the frame)
        if (ibGib.rel8ns[SYNC_MSG_REL8N_NAME] && ibGib.rel8ns[SYNC_MSG_REL8N_NAME].length > 0) {
            await fetchAndPush(ibGib.rel8ns[SYNC_MSG_REL8N_NAME]);
        }
        // 2. Identity (Signer)
        if (ibGib.rel8ns.identity && ibGib.rel8ns.identity.length > 0) {
            await fetchAndPush(ibGib.rel8ns.identity);
        }
    }
    return result;
}
//# sourceMappingURL=sync-helpers.mjs.map