/**
 * @module sync saga context helpers
 */
import { extractErrorMsg, getTimestamp } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
import { Factory_V1 } from '@ibgib/ts-gib/dist/V1/factory.mjs';
import { getIbGibAddr } from '@ibgib/ts-gib/dist/helper.mjs';
import { validateIbGibIntrinsically } from '@ibgib/ts-gib/dist/V1/validate-helper.mjs';
import { GLOBAL_LOG_A_LOT } from '../../core-constants.mjs';
import { SYNC_SAGA_CONTEXT_ATOM } from './sync-saga-context-constants.mjs';
import { SYNC_SAGA_PAYLOAD_ADDRS_DOMAIN } from '../sync-constants.mjs';
import { putInSpace, registerNewIbGib } from '../../witness/space/space-helper.mjs';
import { validateSyncSagaFrame } from '../sync-helpers.mjs';
const logalot = GLOBAL_LOG_A_LOT;
/**
 * Constructs the standard 'ib' string for a Sync Saga Context stone.
 */
export async function getSyncSagaContextIb({ data, }) {
    const lc = `[${getSyncSagaContextIb.name}]`;
    try {
        if (!data) {
            throw new Error(`data required (E: 839d82138c234b3e89582855594191fe)`);
        }
        const payloadCount = data['@payloadAddrsDomain'] ? data['@payloadAddrsDomain'].length : 0;
        const ib = [
            SYNC_SAGA_CONTEXT_ATOM,
            data.sagaN,
            payloadCount,
        ].join(' ');
        return ib;
    }
    catch (error) {
        console.error(`${lc} ${extractErrorMsg(error)}`);
        throw error;
    }
}
/**
 * Parses a standard Sync Saga Context 'ib' string.
 */
export async function parseSyncSagaContextIb({ ib, }) {
    const lc = `[${parseSyncSagaContextIb.name}]`;
    try {
        const parts = ib.split(' ');
        if (parts.length !== 2) {
            throw new Error(`Invalid sync saga context ib. Expected at least 2 parts [atom, payloadCount]. Got ${parts.length}. (E: 8b06c88820c74f5fb9f21f148459422a)`);
        }
        const [atom, sagaNStr, payloadCountStr,] = parts;
        if (atom !== SYNC_SAGA_CONTEXT_ATOM) {
            throw new Error(`Atom mismatch. Expected ${SYNC_SAGA_CONTEXT_ATOM}. Got ${atom}. (E: 67d71fc0f8d04840b178652309f471f5)`);
        }
        if (!sagaNStr) {
            throw new Error(`invalid ib. second piece should be sagaN but is falsy (E: 081ed475aeb8fe25a66f60466b2e5826)`);
        }
        const sagaN = parseInt(sagaNStr);
        if (isNaN(sagaN)) {
            throw new Error(`sagaNStr is not a number. (E: 3d6b580d5a48c5e03ecec288896e2826)`);
        }
        if (!payloadCountStr) {
            throw new Error(`invalid ib. second piece should be payloadCount but is falsy (E: 0bb7580793d800ca02227828a7294826)`);
        }
        const payloadCount = parseInt(payloadCountStr);
        if (isNaN(payloadCount)) {
            throw new Error(`payloadCountStr is not a number. (E: 49457814282a44069871630987588722)`);
        }
        return { atom, sagaN, payloadCount };
    }
    catch (error) {
        console.error(`${lc} ${extractErrorMsg(error)}`);
        throw error;
    }
}
/**
 * Creates new SyncSagaContext stone. Puts/registers in {@link localSpace}
 * immediately after creation.
 *
 * @returns The context ibGib.
 *
 * ## notes
 *
 * the other ibgibs that are related to this context stone should already be
 * put/registered in {@link localSpace}.
 */
export async function createSyncSagaContext({ sagaFrame, sessionKeystones, payloadIbGibsDomain, localSpace, }) {
    const lc = `[${createSyncSagaContext.name}]`;
    try {
        if (logalot) {
            console.log(`${lc} starting... (I: 6b87bee313e811d1d2fc90e87fbec826)`);
        }
        if (!sagaFrame.data) {
            throw new Error(`(UNEXPECTED) sagaFrame.data falsy? (E: 04c49b4cccba6842a8b52e4c6f570726)`);
        }
        if (!sagaFrame.data.n && sagaFrame.data.n !== 0) {
            throw new Error(`(UNEXPECTED) sagaFrame.data.n falsy and not 0? (E: 45b508da64a8b28428b11765d684b826)`);
        }
        const date = new Date();
        const timestamp = getTimestamp(date);
        const timestampMs = date.getMilliseconds();
        const data = {
            timestamp,
            timestampMs,
            sagaN: sagaFrame.data.n,
        };
        // Domain Payloads
        const payloadAddrsDomain = payloadIbGibsDomain ?
            payloadIbGibsDomain?.map(x => getIbGibAddr({ ibGib: x })) :
            undefined;
        if (payloadAddrsDomain && payloadAddrsDomain.length > 0) {
            data[SYNC_SAGA_PAYLOAD_ADDRS_DOMAIN] = payloadAddrsDomain;
        }
        // rel8ns should always have saga frame, sometimes have keystone
        const rel8ns = {
            sagaFrame: [getIbGibAddr({ ibGib: sagaFrame })],
        };
        if (sessionKeystones && sessionKeystones.length > 0) {
            rel8ns.sessionKeystone = sessionKeystones.map(x => getIbGibAddr({ ibGib: x }));
        }
        // Generate standard ib
        const ib = await getSyncSagaContextIb({ data });
        const contextIbGib = await Factory_V1.stone({
            parentPrimitiveIb: SYNC_SAGA_CONTEXT_ATOM,
            ib,
            data,
            rel8ns,
        });
        // put/register immediately. Note that contextIbGib at this point is
        // pure DTO, i.e., only ib, gib, data, rel8ns props.
        await putInSpace({ ibGib: contextIbGib, space: localSpace, });
        await registerNewIbGib({
            ibGib: contextIbGib,
            space: localSpace,
            fnBroadcast: undefined,
        });
        // Attach actual ibgibs for transport (not pure DTO now)
        contextIbGib.sagaFrame = sagaFrame;
        if (payloadIbGibsDomain && payloadIbGibsDomain.length > 0) {
            contextIbGib.payloadIbGibsDomain = payloadIbGibsDomain;
        }
        return contextIbGib;
    }
    catch (error) {
        console.error(`${lc} ${extractErrorMsg(error)}`);
        throw error;
    }
    finally {
        if (logalot) {
            console.log(`${lc} complete.`);
        }
    }
}
/**
 * Validates ONLY the {@link context} ibgib itself and saga frame/msg stone(s)
 * ({@link SyncSagaContextIbGib_V1.sagaFrame}).
 *
 * Does NOT...
 * * validate keystones (authn or authz)
 * * validate domain payload ibgibs...
 *   * intrinsically
 *   * in relation to this context (addrs match up)
 *
 * @returns empty array if valid, else validation errors
 */
export async function validateContextAndSagaFrame({ context }) {
    const lc = `[${validateContextAndSagaFrame.name}]`;
    try {
        if (logalot) {
            console.log(`${lc} starting... (I: 7797f8294bd8f7e5089cb722ad468226)`);
        }
        const errors = [];
        // validate just the context first. if this fails we return early.
        const intrinsicErrors = await validateIbGibIntrinsically({ ibGib: context });
        if (intrinsicErrors && intrinsicErrors.length > 0) {
            intrinsicErrors.forEach(x => errors.push(x));
            return errors; /* <<<< returns early */
        }
        if (context.sagaFrame) {
            const sagaFrameErrors = await validateSyncSagaFrame({ sagaIbGib: context.sagaFrame });
            sagaFrameErrors.forEach(x => errors.push(x));
        }
        else {
            errors.push(`context.sagaFrame is falsy. (E: b4edd88f4963f493789f83b29ba2df26)`);
        }
        // if this is already invalid, we could have intrinsic validation errors, which are a non-starter.
        if (errors.length > 0) {
            return errors; /* <<<< returns early */
        }
        // validate the entire context graph intrinsically, including saga frame, stones, identity(s) (if applicable but not authentication, that will be done in a separate step)
        // ~~ensure the non-dto properties on the context object (i.e. props
        // that are not ib, gib, data, or rel8ns) match the data in the
        // context object~~ NO. THIS WILL BE IN A SEPARATE FUNCTION.
        // See `validateContextDomainPayloadIbGibs`
        // throw new Error(`not implemented (E: cb639658e1183fa6c8a4ebca023ba926)`);
        console.error(`${lc} NAG ERROR MSG (NOT THROWN): not fully implemented yet (E: d574d85cb578637648ed403857f7a826)`);
        return [];
    }
    catch (error) {
        console.error(`${lc} ${extractErrorMsg(error)}`);
        throw error;
    }
    finally {
        if (logalot) {
            console.log(`${lc} complete.`);
        }
    }
}
/**
 * validates {@link SyncSagaContextIbGib_V1.payloadIbGibsDomain} intrinsically,
 * and ensures that these payloadIbGibs also match the expected addrs in
 * {@link SyncSagaContextData_V1}[{@link SYNC_SAGA_PAYLOAD_ADDRS_DOMAIN}].
 *
 * @returns empty array if valid, else validation errors
 */
export async function validateContextDomainPayloadIbGibs({ context }) {
    const lc = `[${validateContextDomainPayloadIbGibs.name}]`;
    try {
        if (logalot) {
            console.log(`${lc} starting... (I: 9f9fe835bcc80c75aa7fd6d887fc0826)`);
        }
        console.error(`${lc} NAG MESSAGE (NOT THROWN). not implemented (E: bfe02ab36a227291a8f17ffc08f2ef26)`);
        return [];
    }
    catch (error) {
        console.error(`${lc} ${extractErrorMsg(error)}`);
        throw error;
    }
    finally {
        if (logalot) {
            console.log(`${lc} complete.`);
        }
    }
}
/**
 * move to sync-peer-helpers.mts as a pure function?
 */
export async function authenticateContext({ context }) {
    const lc = `[${authenticateContext.name}]`;
    try {
        if (logalot) {
            console.log(`${lc} starting... (I: 2677a482dfa873dcd1aa04a3031ff826)`);
        }
        console.error(`${lc} NAG ERROR (NOT THROWN): not implemented. // todo: authenticate  (v1 must have this after we get merge logic workflow going) (E: bc3a78f2dab18ab64c36d055a4b50526)`);
        return [];
    }
    catch (error) {
        console.error(`${lc} ${extractErrorMsg(error)}`);
        throw error;
    }
    finally {
        if (logalot) {
            console.log(`${lc} complete.`);
        }
    }
}
/**
 * move to sync-peer-helpers.mts as a pure function?
 */
export async function authorizeContext({ context }) {
    const lc = `[${authorizeContext.name}]`;
    try {
        if (logalot) {
            console.log(`${lc} starting... (I: 48c918b41ceec0cd489ca3b8819e6826)`);
        }
        console.error(`${lc} NAG ERROR (NOT THROWN): not implemented. authorize business logic (v1 must have this, but later when we are working on admin vs. student)(E: bc3a78f2dab18ab64c36d055a4b50526)`);
        return [];
    }
    catch (error) {
        console.error(`${lc} ${extractErrorMsg(error)}`);
        throw error;
    }
    finally {
        if (logalot) {
            console.log(`${lc} complete.`);
        }
    }
}
//# sourceMappingURL=sync-saga-context-helpers.mjs.map