import { describe, it, expect } from 'vitest';
import { makeFakeInference, AI_GOLDEN } from '@insignia/iios-testkit';
import type { AiJobType } from '@insignia/iios-contracts';

const run = (jobType: AiJobType, text: string) =>
  makeFakeInference().infer({ jobType, text, purpose: `ai_${jobType.toLowerCase()}`, scopeId: 'scope1', interactionId: 'int1' });

describe('FakeInference — deterministic golden provider (P7)', () => {
  it('is replayable: every golden case yields byte-identical output twice', async () => {
    for (const c of AI_GOLDEN) {
      const a = await run(c.jobType, c.text);
      const b = await run(c.jobType, c.text);
      expect(JSON.stringify(a)).toEqual(JSON.stringify(b));
    }
  });

  it('matches golden expectations (artifact type, claims, abstention)', async () => {
    for (const c of AI_GOLDEN) {
      const r = await run(c.jobType, c.text);
      expect(r.artifactType).toBe(c.expect.artifactType);
      expect(r.claims.map((x) => x.claimType).sort()).toEqual([...c.expect.claimTypes].sort());
      expect(!!r.abstentionReason).toBe(c.expect.abstained);
    }
  });

  it('never asserts an event beyond DISCUSSION certainty (Scenario 7)', async () => {
    for (const c of AI_GOLDEN.filter((g) => g.expect.maxCertainty)) {
      const r = await run(c.jobType, c.text);
      const event = r.claims.find((x) => x.claimType === 'EVENT');
      expect(event?.claimJson.certainty).toBe('DISCUSSION');
    }
  });

  it('abstain control forces no claims + a reason', async () => {
    const r = await makeFakeInference().abstain().infer({ jobType: 'EXTRACT', text: 'party at 9 pm', purpose: 'x', scopeId: 's' });
    expect(r.claims).toHaveLength(0);
    expect(r.abstentionReason).toBeTruthy();
  });

  it('emits a positive integer cost (budget governor input)', async () => {
    const r = await run('SUMMARIZE', 'hello world this is a message');
    expect(Number.isInteger(r.modelRun.costUnits)).toBe(true);
    expect(r.modelRun.costUnits).toBeGreaterThan(0);
  });
});
