import { describe, it, expect } from 'vitest';
import { _ASSET_AUDIT_INTERNALS } from './data-builder';
import { fieldNameToTraitKey } from './persistence';
import { buildAssetAuditUserPayload, _PROMPT_INTERNALS } from './prompt';
import { AssetAuditResponse } from '@/lib/types/analyzer';

describe('fillCount', () => {
  const { fillCount } = _ASSET_AUDIT_INTERNALS;

  it('counts populated trait keys', () => {
    expect(fillCount({ a: 'x', b: 'y' })).toBe(2);
  });

  it('drops empty strings, empty arrays, null, undefined', () => {
    expect(
      fillCount({
        a: '',
        b: '   ',
        c: null,
        d: undefined,
        e: [],
        f: 'real',
      })
    ).toBe(1);
  });

  it('counts non-empty objects/arrays', () => {
    expect(fillCount({ a: { values: [1] }, b: [1, 2] })).toBe(2);
  });

  it('returns 0 for null/undefined input', () => {
    expect(fillCount(null)).toBe(0);
    expect(fillCount(undefined)).toBe(0);
  });
});

describe('fieldNameToTraitKey', () => {
  it('matches IT Glue trait-key convention', () => {
    expect(fieldNameToTraitKey('Name')).toBe('name');
    expect(fieldNameToTraitKey('Wulf Application Champion(s)')).toBe(
      'wulf-application-champion-s'
    );
    expect(fieldNameToTraitKey('Application on Device(s)')).toBe(
      'application-on-device-s'
    );
    expect(fieldNameToTraitKey('Client/Server Software Installation Media Location'))
      .toBe('client-server-software-installation-media-location');
  });

  it('strips leading/trailing/repeated hyphens', () => {
    expect(fieldNameToTraitKey('  --Foo--  ')).toBe('foo');
    expect(fieldNameToTraitKey('A & B')).toBe('a-b');
  });
});

describe('AssetAuditResponse Zod schema', () => {
  it('accepts a well-formed response', () => {
    const ok = AssetAuditResponse.safeParse({
      field_gaps: [
        {
          field_name: 'Wulf Application Champion(s)',
          why_missing_matters: 'Jake Hammel is the SME but not recorded.',
          suggested_value: 'Jake Hammel',
          evidence_ticket_numbers: ['T20260502.0033'],
          confidence: 'high',
        },
      ],
      notes_promotions: [
        {
          quoted_note_text: 'Per Jake if down send to Steve Cianflone',
          target_field: 'Vendor Maintenance/Support',
          suggested_value: 'Steve Cianflone (Kastech)',
          confidence: 'medium',
        },
      ],
      contradictions: [
        {
          description: 'Notes say 2-3 VMs, Application-on-Device-s lists 1',
          evidence: 'Notes field; application-on-device-s.values',
        },
      ],
      overall_score: 0.55,
    });
    expect(ok.success).toBe(true);
  });

  it('allows null suggested_value', () => {
    const ok = AssetAuditResponse.safeParse({
      field_gaps: [
        {
          field_name: 'URL',
          why_missing_matters: 'Vendor admin console URL not recorded.',
          suggested_value: null,
          evidence_ticket_numbers: [],
          confidence: 'low',
        },
      ],
      notes_promotions: [],
      contradictions: [],
      overall_score: 0.7,
    });
    expect(ok.success).toBe(true);
  });

  it('rejects out-of-range overall_score', () => {
    const bad = AssetAuditResponse.safeParse({
      field_gaps: [],
      notes_promotions: [],
      contradictions: [],
      overall_score: 1.5,
    });
    expect(bad.success).toBe(false);
  });

  it('rejects bogus confidence values', () => {
    const bad = AssetAuditResponse.safeParse({
      field_gaps: [
        {
          field_name: 'X',
          why_missing_matters: 'y',
          suggested_value: null,
          evidence_ticket_numbers: [],
          confidence: 'sky-high',
        },
      ],
      notes_promotions: [],
      contradictions: [],
      overall_score: 0.5,
    });
    expect(bad.success).toBe(false);
  });
});

describe('buildAssetAuditUserPayload', () => {
  function makeCtx(overrides: Record<string, unknown> = {}) {
    return {
      asset_type: 'flexible_asset',
      asset: {
        id: '1',
        organization_id: '100',
        organization_name: 'Acme',
        type_id: '3790',
        type_name: 'Applications',
        name: 'MISYS',
        traits: { name: 'MISYS', version: '6.3' },
      },
      type_id: 3790,
      type_name: 'Applications',
      fields: [
        { id: '1', name: 'Name', kind: 'Text', hint: null, required: true },
      ],
      peer_same_client: [],
      peer_global: [],
      fill_rate_client: [{ field_name: 'Name', fill_rate: 1.0 }],
      fill_rate_global: [{ field_name: 'Name', fill_rate: 0.95 }],
      ticket_evidence: [],
      ticket_scope: null,
      ...overrides,
    };
  }

  it('renders all sections (flexible asset)', () => {
    const ctx = makeCtx();
    const { payload, trimmed } = buildAssetAuditUserPayload(ctx as never);
    expect(payload).toContain('=== FLEXIBLE ASSET UNDER AUDIT ===');
    expect(payload).toContain('=== FIELD SCHEMA');
    expect(payload).toContain('=== FILL-RATE STATS ===');
    expect(payload).toContain('=== PEER EXEMPLARS — SAME CLIENT ===');
    expect(payload).toContain('=== PEER EXEMPLARS — BEST-IN-CLASS');
    expect(payload).toContain('=== TICKET EVIDENCE');
    expect(trimmed.peer_global_dropped).toBe(0);
    expect(trimmed.tickets_dropped).toBe(0);
  });

  it('renders configuration header when assetType is configuration', () => {
    const ctx = makeCtx({ asset_type: 'configuration' });
    const { payload } = buildAssetAuditUserPayload(ctx as never);
    expect(payload).toContain('=== CONFIGURATION UNDER AUDIT ===');
  });

  it('renders ticket-scoped header when ticket_scope is set', () => {
    const ctx = makeCtx({
      ticket_scope: { analysis_id: 'a', ticket_number: 'T20260502.0033' },
    });
    const { payload } = buildAssetAuditUserPayload(ctx as never);
    expect(payload).toContain('single ticket');
    expect(payload).toContain('T20260502.0033');
  });

  it('trims peer_global before tickets when over the cap', () => {
    const bigPeer = {
      id: 'x',
      organization_id: '99',
      organization_name: 'Other',
      type_id: '3790',
      type_name: 'Applications',
      name: 'BigPeer',
      traits: { huge: 'x'.repeat(_PROMPT_INTERNALS.PAYLOAD_CHAR_CAP) },
    };
    const ctx = makeCtx({ peer_global: [bigPeer, bigPeer] });
    const { trimmed } = buildAssetAuditUserPayload(ctx as never);
    expect(trimmed.peer_global_dropped).toBeGreaterThan(0);
  });
});
