import { describe, expect, it } from 'vitest';
import { CONTENT_PACK, getContentPack } from '../content/pack';
import { buildChecklist } from './checklist';
import { classify } from './classify';
import { conformityDeclaration, procurementSpec } from './extraDocs';
import { deriveObligations } from './obligations';
import type { AISystem, AssessmentAnswers, CompanyProfile } from './types';

const base: AssessmentAnswers = {
  isAISystem: true,
  role: 'deployer',
  isGPAIModel: false,
  prohibitedPractices: [],
  annexIIICategories: [],
  art63Exception: false,
  involvesProfiling: false,
  isAnnexISafetyComponent: false,
  transparencyTriggers: [],
};

const profile: CompanyProfile = {
  name: 'Muster GmbH',
  street: 'Musterstraße 1',
  zipCity: '60311 Frankfurt',
  contactPerson: '',
  email: '',
  phone: '',
  website: '',
  logoDataUrl: '',
  countries: ['DE', 'IT'],
};

function makeSystem(answers: AssessmentAnswers, locale: 'de' | 'en' = 'de'): AISystem {
  return {
    id: 'sys-1',
    name: 'HR-Screening',
    purpose: 'Bewerbervorauswahl',
    vendor: 'Beispiel GmbH',
    owner: 'Jane Doe',
    createdAt: '2026-07-01T00:00:00.000Z',
    updatedAt: '2026-07-01T00:00:00.000Z',
    answers,
    classification: classify(answers, getContentPack(locale), locale),
    obligationStatus: {},
  };
}

describe('mehrsprachiger Content-Pack', () => {
  it('liefert identische IDs und Strukturen in DE und EN', () => {
    const de = getContentPack('de');
    const en = getContentPack('en');
    expect(en.obligations.map((o) => o.id)).toEqual(de.obligations.map((o) => o.id));
    expect(en.national.map((n) => n.code)).toEqual(de.national.map((n) => n.code));
    expect(en.prohibitedPractices).toHaveLength(de.prohibitedPractices.length);
  });

  it('übersetzt Inhalte tatsächlich (kein deutscher Text im EN-Pack)', () => {
    const en = getContentPack('en');
    const literacy = en.obligations.find((o) => o.id === 'ob-ai-literacy');
    expect(literacy?.title).toBe('Ensure AI literacy of staff');
    expect(en.national.find((n) => n.code === 'DE')?.country).toBe('Germany');
  });

  it('klassifiziert mit englischen Begründungen', () => {
    const result = classify(
      { ...base, annexIIICategories: ['a3-employment'] },
      getContentPack('en'),
      'en',
    );
    expect(result.riskClass).toBe('high');
    expect(result.reasons[0]).toContain('Annex III area');
  });

  it('liefert für FR/IT/ES vollständig übersetzte Rechtstexte', () => {
    const en = getContentPack('en');
    for (const locale of ['fr', 'it', 'es', 'pl', 'cs', 'sk', 'ro'] as const) {
      const pack = getContentPack(locale);
      expect(pack.obligations.map((o) => o.id)).toEqual(en.obligations.map((o) => o.id));
      // Tatsächlich übersetzt, nicht EN-Fallback:
      expect(pack.obligations[0]?.title).not.toBe(en.obligations[0]?.title);
      expect(pack.deadlines[0]?.description).not.toBe(en.deadlines[0]?.description);
      const result = classify({ ...base, annexIIICategories: ['a3-employment'] }, pack, locale);
      expect(result.riskClass).toBe('high');
      expect(result.reasons[0]).not.toContain('Annex III area'); // nicht mehr EN
    }
  });
});

describe('UI-Wörterbücher FR/IT/ES', () => {
  it('sind vollständig (gleiche Schlüssel wie Deutsch)', async () => {
    const { uiStrings } = await import('../i18n/ui');
    const deKeys = Object.keys(uiStrings('de')).sort();
    for (const locale of ['fr', 'it', 'es', 'pl', 'cs', 'sk', 'ro'] as const) {
      const dict = uiStrings(locale) as Record<string, string>;
      expect(Object.keys(dict).sort()).toEqual(deKeys);
      // Stichprobe: tatsächlich übersetzt, nicht kopiert
      expect(dict['btnSave']).not.toBe(uiStrings('de').btnSave);
    }
  });
});

describe('nationale Module', () => {
  const answers: AssessmentAnswers = { ...base, annexIIICategories: ['a3-employment'] };

  it('ergänzt deutsche und italienische Pflichten bei aktivierten Modulen', () => {
    const classification = classify(answers, CONTENT_PACK);
    const ids = deriveObligations(classification, answers, CONTENT_PACK, ['DE', 'IT']).map((o) => o.id);
    expect(ids).toContain('de-betrvg');
    expect(ids).toContain('it-l132-workers');
    expect(ids).not.toContain('es-aesia');
  });

  it('liefert ohne Länderauswahl nur EU-Pflichten', () => {
    const classification = classify(answers, CONTENT_PACK);
    const ids = deriveObligations(classification, answers, CONTENT_PACK).map((o) => o.id);
    expect(ids.some((id) => id.startsWith('de-') || id.startsWith('it-'))).toBe(false);
  });

  it('respektiert Rolle und Risikoklasse auch bei nationalen Pflichten', () => {
    const providerAnswers: AssessmentAnswers = { ...answers, role: 'provider' };
    const classification = classify(providerAnswers, CONTENT_PACK);
    const ids = deriveObligations(classification, providerAnswers, CONTENT_PACK, ['DE']).map((o) => o.id);
    expect(ids).not.toContain('de-betrvg'); // nur Betreiber
    expect(ids).toContain('de-kimig-authority');
  });

  it('enthält neue EU-Pflichten (Art. 72/73) für Hochrisiko-Anbieter', () => {
    const providerAnswers: AssessmentAnswers = { ...answers, role: 'provider' };
    const classification = classify(providerAnswers, CONTENT_PACK);
    const ids = deriveObligations(classification, providerAnswers, CONTENT_PACK).map((o) => o.id);
    expect(ids).toContain('ob-postmarket');
    expect(ids).toContain('ob-incident');
    expect(ids).toContain('ob-corrective');
  });
});

describe('buildChecklist', () => {
  it('gruppiert nach fällig / anstehend / erledigt und zählt Fortschritt', () => {
    const system = makeSystem({ ...base, annexIIICategories: ['a3-employment'] });
    const withStatus: AISystem = {
      ...system,
      obligationStatus: { 'ob-ai-literacy': 'done' },
    };
    const checklist = buildChecklist([withStatus], CONTENT_PACK, ['DE'], '2026-07-04');

    expect(checklist.total).toBeGreaterThan(5);
    expect(checklist.resolvedCount).toBe(1);
    // KI-Kompetenz (2025) ist erledigt; BetrVG (2025) ist fällig
    expect(checklist.dueNow.some((e) => e.obligation.id === 'de-betrvg')).toBe(true);
    // Art.-26-Pflichten (2027) stehen an
    expect(checklist.upcoming.some((e) => e.obligation.id === 'ob-deployer-oversight')).toBe(true);
    expect(checklist.resolved[0]?.obligation.id).toBe('ob-ai-literacy');
  });

  it('ist leer ohne Systeme', () => {
    const checklist = buildChecklist([], CONTENT_PACK, [], '2026-07-04');
    expect(checklist.total).toBe(0);
  });
});

describe('Zusatzdokumente', () => {
  it('Lastenheft enthält MUSS-Anforderungen und Hochrisiko-Punkte', () => {
    const system = makeSystem({ ...base, annexIIICategories: ['a3-employment'] });
    const md = procurementSpec(system, CONTENT_PACK, '2026-07-04', profile);
    expect(md).toContain('Lastenheft');
    expect(md).toContain('REQ-01');
    expect(md).toContain('MUSS');
    expect(md).toContain('keine Rechtsberatung');
  });

  it('Lastenheft lässt Hochrisiko-Anforderungen bei limited weg', () => {
    const system = makeSystem({ ...base, transparencyTriggers: ['tr-chatbot'] });
    const md = procurementSpec(system, CONTENT_PACK, '2026-07-04', profile);
    expect(md).not.toContain('REQ-01'); // CE-Kennzeichnung nur Hochrisiko
    expect(md).toContain('REQ-03'); // Betriebsanleitung immer
  });

  it('Konformitätserklärung füllt Anbieter aus dem Profil vor (EN)', () => {
    const system = makeSystem({ ...base, role: 'provider', annexIIICategories: ['a3-employment'] }, 'en');
    const md = conformityDeclaration(system, getContentPack('en'), '2026-07-04', profile, 'en');
    expect(md).toContain('EU declaration of conformity');
    expect(md).toContain('Muster GmbH, Musterstraße 1, 60311 Frankfurt');
    expect(md).toContain('not legal advice');
  });
});
