import { describe, expect, it } from 'vitest';
import { deriveChildState } from '../index.js';
const ROOT_TENANT = 'tnt_root';
describe('InvocationState', () => {
    describe('deriveChildState', () => {
        it('seeds parentChain from a root seed when no parent state exists', () => {
            const childState = deriveChildState({ tenantId: ROOT_TENANT }, 'agent-123');
            expect(childState.parentChain).toEqual(['agent-123']);
            expect(childState.tenantId).toBe(ROOT_TENANT);
            expect(childState.metadata).toBeUndefined();
            expect(childState.services).toBeUndefined();
        });
        it('seeds parentChain when parent has no parentChain', () => {
            const parent = {
                tenantId: 'tnt_abc',
                metadata: { userId: 'user-123' },
            };
            const childState = deriveChildState(parent, 'agent-456');
            expect(childState.parentChain).toEqual(['agent-456']);
            expect(childState.tenantId).toBe(parent.tenantId);
            expect(childState.metadata).toBe(parent.metadata);
        });
        it('extends parentChain with current agent', () => {
            const parent = {
                parentChain: ['supervisor', 'router'],
                tenantId: 'tnt_xyz',
            };
            const childState = deriveChildState(parent, 'worker-agent');
            expect(childState.parentChain).toEqual(['supervisor', 'router', 'worker-agent']);
        });
        it('preserves tenantId through derivation', () => {
            const tenantId = 'tnt_tenant123';
            const parent = {
                tenantId,
                parentChain: ['agent-1'],
            };
            const childState = deriveChildState(parent, 'agent-2');
            expect(childState.tenantId).toBe(tenantId);
        });
        it('preserves metadata through derivation', () => {
            const metadata = {
                userId: 'user-456',
                sessionId: 'ses_789',
                correlationId: 'corr_abc',
            };
            const parent = {
                tenantId: ROOT_TENANT,
                metadata,
                parentChain: ['agent-1'],
            };
            const childState = deriveChildState(parent, 'agent-2');
            expect(childState.metadata).toBe(metadata);
            expect(childState.metadata?.userId).toBe('user-456');
        });
        it('preserves services through derivation', () => {
            const services = {
                db: { pool: 'mock-pool' },
                cache: { client: 'mock-redis' },
            };
            const parent = {
                tenantId: ROOT_TENANT,
                services,
                parentChain: ['agent-1'],
            };
            const childState = deriveChildState(parent, 'agent-2');
            expect(childState.services).toBe(services);
        });
        it('preserves all fields through multi-level derivation', () => {
            const tenantId = 'tnt_multi';
            const metadata = { userId: 'user-multi' };
            const services = { db: 'postgres' };
            const level1 = deriveChildState({ tenantId }, 'supervisor');
            expect(level1.parentChain).toEqual(['supervisor']);
            const parent = {
                tenantId,
                metadata,
                services,
                parentChain: level1.parentChain,
            };
            const level2 = deriveChildState(parent, 'router');
            expect(level2.parentChain).toEqual(['supervisor', 'router']);
            expect(level2.tenantId).toBe(tenantId);
            expect(level2.metadata).toBe(metadata);
            expect(level2.services).toBe(services);
            const level3 = deriveChildState(level2, 'worker');
            expect(level3.parentChain).toEqual(['supervisor', 'router', 'worker']);
            expect(level3.tenantId).toBe(tenantId);
            expect(level3.metadata).toBe(metadata);
            expect(level3.services).toBe(services);
        });
        it('creates immutable parentChain', () => {
            const parent = {
                tenantId: ROOT_TENANT,
                parentChain: ['agent-1'],
            };
            const childState = deriveChildState(parent, 'agent-2');
            // Ensure the parentChain is a new array, not mutated
            expect(parent.parentChain).toEqual(['agent-1']);
            expect(childState.parentChain).toEqual(['agent-1', 'agent-2']);
        });
        it('handles empty parentChain in parent', () => {
            const parent = {
                tenantId: ROOT_TENANT,
                parentChain: [],
            };
            const childState = deriveChildState(parent, 'agent-first');
            expect(childState.parentChain).toEqual(['agent-first']);
        });
        it('allows complex agent IDs in parentChain', () => {
            const agentIds = ['supervisor-agent-123', 'router-multi-path', 'worker-task-handler'];
            let state = { tenantId: ROOT_TENANT };
            for (const agentId of agentIds) {
                state = deriveChildState(state, agentId);
            }
            expect(state.parentChain).toEqual(agentIds);
        });
        it('does not mutate parent state', () => {
            const parent = {
                parentChain: ['original'],
                tenantId: 'tnt_orig',
                metadata: { key: 'value' },
            };
            const originalParentChain = [...(parent.parentChain ?? [])];
            deriveChildState(parent, 'child');
            // Parent state should remain unchanged
            expect(parent.parentChain).toEqual(originalParentChain);
            expect(parent.parentChain).toEqual(['original']);
        });
    });
    describe('InvocationState immutability', () => {
        it('has readonly fields', () => {
            const state = {
                tenantId: 'tnt_test',
                metadata: { key: 'value' },
                services: { db: 'postgres' },
                parentChain: ['agent-1'],
            };
            // Type system enforces immutability, so these assertions verify the type definitions
            expect(state.tenantId).toBe('tnt_test');
            expect(state.metadata).toBeDefined();
            expect(state.services).toBeDefined();
            expect(state.parentChain).toBeDefined();
        });
        it('supports undefined optional fields (tenantId still required)', () => {
            const minimalState = {
                tenantId: ROOT_TENANT,
                parentChain: ['agent-1'],
            };
            expect(minimalState.tenantId).toBe(ROOT_TENANT);
            expect(minimalState.metadata).toBeUndefined();
            expect(minimalState.services).toBeUndefined();
            expect(minimalState.parentChain).toEqual(['agent-1']);
        });
        it('handles metadata with various types', () => {
            const metadata = {
                userId: 'user-123',
                count: 42,
                enabled: true,
                nested: { key: 'value' },
                array: [1, 2, 3],
            };
            const state = {
                tenantId: ROOT_TENANT,
                metadata,
            };
            expect(state.metadata?.userId).toBe('user-123');
            expect(state.metadata?.count).toBe(42);
            expect(state.metadata?.enabled).toBe(true);
            expect(state.metadata?.nested).toEqual({ key: 'value' });
            expect(state.metadata?.array).toEqual([1, 2, 3]);
        });
    });
});
//# sourceMappingURL=state.test.js.map