import { respecfully, iReckon, ifWe } from '@ibgib/helper-gib/dist/respec-gib/respec-gib.mjs';
import { KeystoneService_V1 } from './keystone-service-v1.mjs';
import { createStandardPoolConfig } from './keystone-config-builder.mjs';
import { POOL_ID_DEFAULT, KEYSTONE_CHECKPOINT_FREQUENCY } from './keystone-constants.mjs';
const sir = `[${import.meta.url}]`;
class MockMetaspace {
    storage = new Map();
    async get(args) {
        const ibGib = this.storage.get(args.addr);
        return { success: !!ibGib, ibGibs: ibGib ? [ibGib] : [] };
    }
    async put(args) {
        this.storage.set(`${args.ibGib.ib}^${args.ibGib.gib}`, args.ibGib);
    }
    async registerNewIbGib(args) {
        await this.put(args);
    }
    async getLocalUserSpace() { return new MockSpace(); }
}
class MockSpace {
    async put() { }
    async witness() { return { data: { success: true } }; }
}
await respecfully(sir, 'Keystone State Aggregation', async () => {
    const service = new KeystoneService_V1();
    const metaspace = new MockMetaspace();
    const space = new MockSpace();
    const masterSecret = "AliceSecret";
    const config = createStandardPoolConfig({ id: POOL_ID_DEFAULT, salt: POOL_ID_DEFAULT, size: 1000 });
    await ifWe(sir, 'aggregates frameDetails correctly across multiple evolutions', async () => {
        // 1. Genesis with some details
        const genesis = await service.genesis({
            masterSecret,
            configs: [config],
            metaspace,
            space,
            frameDetails: { profile: { name: 'Alice' } }
        });
        // 2. Evolve with more details
        const claim = { target: "comment 1^gib", verb: "post" };
        const frame2 = await service.sign({
            latestKeystone: genesis,
            masterSecret,
            claim,
            metaspace,
            space,
            frameDetails: { profile: { email: 'alice@example.com' }, lastLogin: '2026-05-01' }
        });
        // 3. Evolve again (no new details)
        const frame3 = await service.sign({
            latestKeystone: frame2,
            masterSecret,
            claim: { ...claim, target: "comment 2^gib" },
            metaspace,
            space
        });
        // 4. Verify aggregation
        const aggregated = await service.getAggregateDetails({
            latestKeystone: frame3,
            metaspace,
            space
        });
        iReckon(sir, aggregated.profile.name).willEqual('Alice');
        iReckon(sir, aggregated.profile.email).willEqual('alice@example.com');
        iReckon(sir, aggregated.lastLogin).willEqual('2026-05-01');
    });
    await ifWe(sir, 'generates a checkpoint and uses it for aggregation', async () => {
        // We will force a checkpoint by evolving KEYSTONE_CHECKPOINT_FREQUENCY times.
        // For testing, we might want to lower the frequency, but let's stick to the constant
        // and just do a loop if it's not too large. 50 is fine for a test.
        let current = await service.genesis({
            masterSecret,
            configs: [config],
            metaspace,
            space,
            frameDetails: { initial: true }
        });
        const totalEvolutions = KEYSTONE_CHECKPOINT_FREQUENCY;
        console.log(`[test] Performing ${totalEvolutions} evolutions to trigger checkpoint...`);
        for (let i = 1; i <= totalEvolutions; i++) {
            current = await service.sign({
                latestKeystone: current,
                masterSecret,
                claim: { target: `item_${i}^gib`, verb: "update" },
                metaspace,
                space,
                frameDetails: { [`step_${i}`]: true }
            });
        }
        // The latest frame should now have a checkpointDetails
        iReckon(sir, current.data.checkpointDetails).asTo('checkpoint exists').isGonnaBeTruthy();
        iReckon(sir, current.data.n).willEqual(totalEvolutions);
        // Aggregation should work and be fast (it stops at the checkpoint)
        // We can verify it has all the steps
        const aggregated = await service.getAggregateDetails({
            latestKeystone: current,
            metaspace,
            space
        });
        iReckon(sir, aggregated.initial).isGonnaBeTrue();
        iReckon(sir, aggregated[`step_${totalEvolutions}`]).isGonnaBeTrue();
        iReckon(sir, aggregated[`step_1`]).isGonnaBeTrue();
        // Verify that it actually used the checkpoint (white-box-ish)
        // If we clear the previous frames from storage, getAggregateDetails should still work
        // if it only goes back to the checkpoint.
        // Wait, current IS the checkpoint. So it should stop immediately.
        metaspace.storage.clear();
        // Re-put ONLY the latest (which has the checkpoint)
        await metaspace.put({ ibGib: current });
        const aggregatedFromCheckpoint = await service.getAggregateDetails({
            latestKeystone: current,
            metaspace,
            space
        });
        iReckon(sir, aggregatedFromCheckpoint.initial).isGonnaBeTrue();
    });
});
//# sourceMappingURL=aggregate-details.respec.mjs.map