/**
 * @module SyncPeer_V1 witness class
 */
import { extractErrorMsg } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
import { getIbGibAddr } from '@ibgib/ts-gib/dist/helper.mjs';
import { GLOBAL_LOG_A_LOT } from '../../core-constants.mjs';
import { SYNC_MSG_REL8N_NAME, SYNC_SAGA_PAYLOAD_ADDRS_DOMAIN } from '../sync-constants.mjs';
import { LightWitnessBase_V1 } from '../../witness/light-witness-base-v1.mjs';
const logalot = GLOBAL_LOG_A_LOT || true;
const logalotControlDomain = true;
const lcControlDomain = '[ControlDomain]';
/**
 * Abstract witness for talking to a Sync Peer (e.g. Remote Node or Local Simulator).
 *
 * Takes a SyncSagaContext (Request) and returns a SyncSagaContext (Response).
 *
 * Implements the core "Sync Protocol Transport" logic:
 * 1. Push Context & Dependencies (Sender -> Receiver)
 * 2. Send Request (RPC)
 * 3. Pull Response & Dependencies (Receiver -> Sender)
 */
export class SyncPeer_V1 extends LightWitnessBase_V1 {
    lc = `[${SyncPeer_V1.name}]`;
    get classname() {
        if (!this.data) {
            throw new Error(`(UNEXPECTED) this.data falsy? (E: 1ab1841e9338b54f3aa615fa37024826)`);
        }
        if (!this.data.classname) {
            throw new Error(`invalid peer. this.data.classname is falsy (E: b0ee28a0abb84a06588d9de7afcef826)`);
        }
        return this.data.classname;
    }
    constructor(initialData, initialRel8ns) {
        super(initialData, initialRel8ns);
    }
    /**
     * Witness the synchronization context (Send/Receive).
     *
     * @param arg The OUTGOING context (Request).
     * @returns The INCOMING context (Response), or undefined if failed/empty.
     */
    async witness(arg) {
        const lc = `${this.lc}[${this.witness.name}]`;
        try {
            if (logalot) {
                console.log(`${lc} starting...`);
            }
            if (logalot) {
                console.log(`${lc} starting...`);
            }
            // 1. PUSH: Ensure Request Data is available on Receiver
            await this.pushContextGraph({ context: arg });
            // 2. EXECUTE: Trigger Remote Processing
            const response = await this.sendContextRequest(arg);
            if (!response) {
                if (logalot) {
                    console.log(`${lc} No response from peer.`);
                }
                return undefined;
            }
            // 3. PULL: Ensure Response Data is available on Sender (Local)
            await this.pullContextGraph({ context: response });
            return response;
        }
        catch (error) {
            console.error(`${lc} ${extractErrorMsg(error)}`);
            throw error;
        }
        finally {
            if (logalot) {
                console.log(`${lc} complete.`);
            }
        }
    }
    /**
     * Helper to orchestrate the PUSH of a Context's dependency graph.
     */
    async pushContextGraph({ context }) {
        const lc = `[${SyncPeer_V1.name}][pushContextGraph]`;
        // A. Push Context Envelope
        const contextAddr = getIbGibAddr({ ibGib: context });
        if (logalotControlDomain) {
            console.log(`${lc}${lcControlDomain} PUSH Context Envelope -> ${contextAddr} (I: 3f4e5a6b7c8d9e0f)`);
        }
        await this.push([contextAddr]);
        // B. Push Saga Frame & Immediate Deps (Msg, Identity)
        const frameAddr = context.rel8ns?.sagaFrame?.[0];
        if (frameAddr) {
            if (logalotControlDomain) {
                console.log(`${lc}${lcControlDomain} PUSH CONTROL: Saga Frame -> ${frameAddr} (I: 4a5b6c7d8e9f0a1b)`);
            }
            await this.push([frameAddr]);
            // We inspect the local frame to find its immediate deps
            const frame = await this.getLocalIbGib(frameAddr);
            if (frame) {
                // Msg Stone
                const msgAddrs = frame.rel8ns?.[SYNC_MSG_REL8N_NAME];
                if (msgAddrs) {
                    for (const addr of msgAddrs) {
                        if (logalotControlDomain) {
                            console.log(`${lc}${lcControlDomain} PUSH CONTROL: Msg Stone -> ${addr} (I: 5b6c7d8e9f0a1b2c)`);
                        }
                        await this.push([addr]);
                    }
                }
                // Identity
                const idAddrs = frame.rel8ns?.identity;
                if (idAddrs) {
                    for (const addr of idAddrs) {
                        if (logalotControlDomain) {
                            console.log(`${lc}${lcControlDomain} PUSH CONTROL: Identity -> ${addr} (I: 6c7d8e9f0a1b2c3d)`);
                        }
                        await this.push([addr]);
                    }
                }
            }
        }
        // C. Push Session Identity
        const sessionKeystoneAddr = context.rel8ns?.sessionKeystone?.[0];
        if (sessionKeystoneAddr) {
            if (logalotControlDomain) {
                console.log(`${lc}${lcControlDomain} PUSH CONTROL: Session Keystone -> ${sessionKeystoneAddr} (I: 7d8e9f0a1b2c3d4e)`);
            }
            await this.push([sessionKeystoneAddr]);
        }
        // D. Push Payloads (Deep/Soft)
        // For payloads, the Peer is just a transport. It doesn't know the structure.
        // It relies on "push" handling the "deep" transfer if needed, or we explicitly iterate if we had a graph.
        // But since we are "Witnessing", we usually assume "push(addr)" acts like "copy(addr, recursive=true)"?
        // Or do we need to be explicit?
        // User said: "payloads should be flat... sync coordinator is the one doing the heavy lifting".
        // So we just push the addrs listed.
        // 1. Control Payloads
        // const controlAddrs = context.data?.[SYNC_SAGA_PAYLOAD_ADDRS_CONTROL];
        // if (controlAddrs && controlAddrs.length > 0) {
        //     if (logalotControlDomain) { console.log(`${lc}${lcControlDomain} PUSH CONTROL PAYLOADS (${controlAddrs.length}): ${controlAddrs.join(', ')} (I: 8e9f0a1b2c3d4e5f)`); }
        //     for (const addr of controlAddrs) {
        //         await this.push(addr);
        //     }
        // }
        // 2. Domain Payloads
        const domainAddrs = context.data?.[SYNC_SAGA_PAYLOAD_ADDRS_DOMAIN];
        if (domainAddrs && domainAddrs.length > 0) {
            if (logalotControlDomain) {
                console.log(`${lc}${lcControlDomain} PUSH DOMAIN PAYLOADS (${domainAddrs.length}): ${domainAddrs.join(', ')} (I: 9f0a1b2c3d4e5f6a)`);
            }
            for (const addr of domainAddrs) {
                await this.push([addr]);
            }
        }
        if (logalotControlDomain) {
            console.log(`${lc}${lcControlDomain} PUSH COMPLETE for context ${contextAddr} (I: a0b1c2d3e4f5a6b7)`);
        }
    }
    /**
     * Helper to orchestrate the PULL of a Context's dependency graph.
     */
    async pullContextGraph({ context }) {
        const lc = `[${SyncPeer_V1.name}][pullContextGraph]`;
        // A. Pull Context Envelope
        const contextAddr = getIbGibAddr({ ibGib: context });
        if (logalotControlDomain) {
            console.log(`${lc}${lcControlDomain} PULL Context Envelope <- ${contextAddr} (I: b1c2d3e4f5a6b7c8)`);
        }
        await this.pull([contextAddr]);
        // B. Pull Saga Frame & Immediate Deps
        const frameAddr = context.rel8ns?.sagaFrame?.[0];
        if (frameAddr) {
            if (logalotControlDomain) {
                console.log(`${lc}${lcControlDomain} PULL CONTROL: Saga Frame <- ${frameAddr} (I: c2d3e4f5a6b7c8d9)`);
            }
            await this.pull([frameAddr]);
            // Inspect REMOTE frame? We need to have pulled it first.
            const frame = await this.getLocalIbGib(frameAddr); // Should be local now
            if (frame) {
                const msgAddrs = frame.rel8ns?.[SYNC_MSG_REL8N_NAME];
                if (msgAddrs) {
                    for (const addr of msgAddrs) {
                        if (logalotControlDomain) {
                            console.log(`${lc}${lcControlDomain} PULL CONTROL: Msg Stone <- ${addr} (I: d3e4f5a6b7c8d9e0)`);
                        }
                        await this.pull([addr]);
                    }
                }
                const idAddrs = frame.rel8ns?.identity;
                if (idAddrs) {
                    for (const addr of idAddrs) {
                        if (logalotControlDomain) {
                            console.log(`${lc}${lcControlDomain} PULL CONTROL: Identity <- ${addr} (I: e4f5a6b7c8d9e0f1)`);
                        }
                        await this.pull([addr]);
                    }
                }
            }
        }
        // C. Pull Session Identity
        const sessionKeystoneAddr = context.rel8ns?.sessionKeystone?.[0];
        if (sessionKeystoneAddr) {
            if (logalotControlDomain) {
                console.log(`${lc}${lcControlDomain} PULL CONTROL: Session Keystone <- ${sessionKeystoneAddr} (I: f5a6b7c8d9e0f1a2)`);
            }
            await this.pull([sessionKeystoneAddr]);
        }
        // D. Pull Payloads
        // const controlAddrs = context.data?.[SYNC_SAGA_PAYLOAD_ADDRS_CONTROL];
        // if (controlAddrs && controlAddrs.length > 0) {
        //     if (logalotControlDomain) { console.log(`${lc}${lcControlDomain} PULL CONTROL PAYLOADS (${controlAddrs.length}): ${controlAddrs.join(', ')} (I: a6b7c8d9e0f1a2b3)`); }
        //     for (const addr of controlAddrs) {
        //         await this.pull(addr);
        //     }
        // }
        const domainAddrs = context.data?.[SYNC_SAGA_PAYLOAD_ADDRS_DOMAIN];
        if (domainAddrs && domainAddrs.length > 0) {
            if (logalotControlDomain) {
                console.log(`${lc}${lcControlDomain} PULL DOMAIN PAYLOADS (${domainAddrs.length}): ${domainAddrs.join(', ')} (I: b7c8d9e0f1a2b3c4)`);
            }
            for (const addr of domainAddrs) {
                await this.pull([addr]);
            }
        }
        if (logalotControlDomain) {
            console.log(`${lc}${lcControlDomain} PULL COMPLETE for context ${contextAddr} (I: c8d9e0f1a2b3c4d5)`);
        }
    }
}
//# sourceMappingURL=sync-peer-v1.mjs.map