/**
 * Unit tests for the reflection.v1 schema + self-report boundary.
 *
 * The runtime source of truth is the zod schema set in `reflection.ts`. The
 * class-validator `ReflectionSelfReportDto` is the NestJS-side boundary type
 * (exercised under the gateway app's reflect-metadata runtime, mirroring how
 * `chat.dto.ts` is tested in apps/gateway); here we validate the self-report
 * input with its zod counterpart, which is what the Stop hook actually uses.
 *
 * Coverage:
 *  - REVIEW_SURFACES canonical ordering (the enum both zod + JSON Schema mirror)
 *  - ReflectionV1Schema accepts a fully-populated record
 *  - ReflectionV1Schema accepts a degraded record (self-report fields null)
 *  - ReflectionV1Schema rejects bad schema literal / out-of-range confidence / bad surface
 *  - ReflectionSelfReportSchema accepts valid + empty, rejects bad input
 */

import { describe, expect, it } from 'vitest';

import {
  REVIEW_SURFACES,
  ReflectionV1Schema,
  ReflectionSelfReportSchema,
  type ReflectionV1,
} from '../index.js';

const baseMechanical = {
  schema: 'reflection.v1' as const,
  task_ref: 'stack#544',
  agent: 'claude',
  session_id: 'sess-abc',
  timestamp: '2026-06-16T00:00:00.000Z',
  repo: 'stack',
  risk: {
    needs_review: true,
    score: 1.0,
    surface: 'auth' as const,
    reason: 'auth surface (weight 1) in: src/auth.ts',
  },
  files_changed: ['src/auth.ts'],
  provenance: {
    source: 'stop-hook' as const,
    reflection_attempt: 1,
    degraded: false,
    reflection_mode: 'solo' as const,
  },
};

describe('REVIEW_SURFACES', () => {
  it('keeps the canonical most→least-sensitive ordering', () => {
    expect(REVIEW_SURFACES).toEqual([
      'auth',
      'data',
      'infra',
      'build',
      'ui',
      'test',
      'docs',
      'none',
    ]);
  });
});

describe('ReflectionV1Schema', () => {
  it('accepts a fully-populated record', () => {
    const rec: ReflectionV1 = {
      ...baseMechanical,
      confidence: 0.7,
      most_likely_wrong: { surface: 'auth', description: 'token refresh untested' },
      known_not_in_diff: 'manual QA only on the happy path',
    };
    expect(() => ReflectionV1Schema.parse(rec)).not.toThrow();
  });

  it('accepts a degraded record with null self-report fields', () => {
    const rec: ReflectionV1 = {
      ...baseMechanical,
      confidence: null,
      most_likely_wrong: null,
      known_not_in_diff: null,
      provenance: { ...baseMechanical.provenance, degraded: true },
    };
    expect(() => ReflectionV1Schema.parse(rec)).not.toThrow();
  });

  it('rejects a wrong schema literal', () => {
    const bad = {
      ...baseMechanical,
      schema: 'reflection.v2',
      confidence: null,
      most_likely_wrong: null,
      known_not_in_diff: null,
    };
    expect(() => ReflectionV1Schema.parse(bad)).toThrow();
  });

  it('rejects out-of-range confidence', () => {
    const bad = {
      ...baseMechanical,
      confidence: 1.5,
      most_likely_wrong: null,
      known_not_in_diff: null,
    };
    expect(() => ReflectionV1Schema.parse(bad)).toThrow();
  });

  it('rejects an unknown surface', () => {
    const bad = {
      ...baseMechanical,
      risk: { ...baseMechanical.risk, surface: 'network' },
      confidence: null,
      most_likely_wrong: null,
      known_not_in_diff: null,
    };
    expect(() => ReflectionV1Schema.parse(bad)).toThrow();
  });
});

describe('ReflectionSelfReportSchema', () => {
  it('accepts a valid self-report', () => {
    const ok = ReflectionSelfReportSchema.safeParse({
      confidence: 0.8,
      most_likely_wrong: {
        surface: 'data',
        description: 'migration not run against prod-sized data',
      },
      known_not_in_diff: 'rollback path untested',
    });
    expect(ok.success).toBe(true);
  });

  it('accepts an empty self-report (all optional)', () => {
    expect(ReflectionSelfReportSchema.safeParse({}).success).toBe(true);
  });

  it('rejects confidence above 1', () => {
    expect(ReflectionSelfReportSchema.safeParse({ confidence: 2 }).success).toBe(false);
  });

  it('rejects an unknown most_likely_wrong.surface', () => {
    const res = ReflectionSelfReportSchema.safeParse({
      most_likely_wrong: { surface: 'network', description: 'x' },
    });
    expect(res.success).toBe(false);
  });
});
