import { describe, expect, it } from "vitest";
import { attachIntegrity, buildCanonicalReportPayload, canonicalizeReportForIntegrity, createExportIntegrity, verifyEntryIntegrity } from "./integrity";
import { demoEntries } from "./demoData";
import type { Report } from "./types";

const report: Report = {
  id: "rapport-1",
  report_time: "08:00:00",
  report_date: "2026-05-27",
  created_at: "2026-05-27T06:00:00.000Z",
  type: "work_report",
  work_ability: 4,
  energy_level: 3,
  mental_clarity: 4,
  symptom_burden: 2,
  effort_strain: 3,
  status: "kan_fortsette",
  physical_energy: 3,
  mental_energy: 3,
  task_types: [],
  main_limitations: [],
  helpful_accommodations: []
};

describe("integritetskontroll", () => {
  it("legger til og validerer integritetsmetadata", () => {
    const signed = attachIntegrity(report);
    const verified = verifyEntryIntegrity(signed);

    expect(signed.integrity?.payload_hash_sha256).toBeTruthy();
    expect(signed.integrity?.payload_hash_sha256).toHaveLength(64);
    expect(signed.integrity?.algorithm).toBe("sha256");
    expect(verified.integrity?.verification_status).toBe("valid");
  });

  it("markerer endret rapport som mulig endret", () => {
    const signed = attachIntegrity(report);
    const tampered = { ...signed, energy_level: 1 as const };
    const verified = verifyEntryIntegrity(tampered);

    expect(verified.integrity?.verification_status).toBe("modified");
  });

  it("validerer uendret eksport og import uten falsk modified", () => {
    const signed = attachIntegrity({ ...report, total_score_percent: 72 });
    const exported = JSON.stringify({ reports: [signed] });
    const imported = JSON.parse(exported).reports[0] as Report;
    const verified = verifyEntryIntegrity(imported);

    expect(verified.integrity?.verification_status).toBe("valid");
  });

  it("påvirkes ikke av nøkkelrekkefølge eller appgenerert verifiseringsstatus", () => {
    const signed = attachIntegrity(report);
    const reordered = {
      type: signed.type,
      created_at: signed.created_at,
      id: signed.id,
      report_date: signed.report_date,
      report_time: signed.report_time,
      status: signed.status,
      effort_strain: signed.effort_strain,
      symptom_burden: signed.symptom_burden,
      mental_clarity: signed.mental_clarity,
      energy_level: signed.energy_level,
      work_ability: signed.work_ability,
      physical_energy: signed.physical_energy,
      mental_energy: signed.mental_energy,
      helpful_accommodations: signed.helpful_accommodations,
      main_limitations: signed.main_limitations,
      task_types: signed.task_types,
      integrity: { ...signed.integrity!, verification_status: "modified" as const }
    };

    expect(canonicalizeReportForIntegrity(reordered)).toBe(canonicalizeReportForIntegrity(signed));
    expect(verifyEntryIntegrity(reordered).integrity?.verification_status).toBe("valid");
  });

  it("fjerner hele integrity-objektet fra canonical payload", () => {
    const signed = attachIntegrity(report);
    const withChangedIntegrity = {
      ...signed,
      integrity: {
        ...signed.integrity!,
        verification_status: "modified" as const,
        verification_reason: "Endret lokal forklaring",
        signed_at: "2099-01-01T00:00:00.000Z"
      }
    };

    expect(buildCanonicalReportPayload(withChangedIntegrity)).toBe(buildCanonicalReportPayload(report));
    expect(verifyEntryIntegrity(withChangedIntegrity).integrity?.verification_status).toBe("valid");
  });

  it("ignorerer rekalkulert totalscore og veiledernotater i integritetskontrollen", () => {
    const signed = attachIntegrity(report);
    const withLocalFields = {
      ...signed,
      total_score_percent: 12,
      evaluator_notes: [{ id: "note-1", text: "Lokalt notat" }],
      report_review_note: "Lokalt notat",
      normalized_period_score: 55
    } as Report;

    expect(verifyEntryIntegrity(withLocalFields).integrity?.verification_status).toBe("valid");
  });

  it("lar demodataflagg være metadata uten å endre rapportintegritet", () => {
    const signed = attachIntegrity(report);

    expect(verifyEntryIntegrity({ ...signed, demo: true }).integrity?.verification_status).toBe("valid");
  });

  it("validerer innebygde demorapporter mot medfølgende integritetsdata", () => {
    expect(demoEntries.map((entry) => verifyEntryIntegrity(entry).integrity?.verification_status)).toEqual(
      demoEntries.map(() => "valid")
    );
  });

  it("validerer rapport med arbeidssted og legacy energidetaljer uten false modified", () => {
    const raw = {
      id: "aac87f66-2d39-4a6f-8169-7d39aa5fc0e6",
      created_at: "2026-05-27T18:36:17.482Z",
      report_date: "2026-05-27",
      report_time: "20:36:17",
      type: "work_report",
      workplace: "Hjemme",
      work_start_time: "12:30",
      work_end_time: "20:00",
      work_ability: 4,
      energy_level: 3,
      mental_clarity: 4,
      symptom_burden: 1,
      effort_strain: 2,
      status: "kan_fortsette",
      physical_energy: 3,
      mental_energy: 4,
      physical_energy_detail: 3,
      mental_energy_detail: 4,
      perceived_productivity: 4,
      task_completion: "som_forventet",
      task_types: ["sitting", "computer_work", "concentration"],
      main_limitations: ["stress_anxiety"],
      helpful_accommodations: [],
      total_score_percent: 81
    } as Report;

    const signed = attachIntegrity(raw);
    const imported = JSON.parse(JSON.stringify(signed)) as Report;

    expect(buildCanonicalReportPayload(imported)).not.toContain("physical_energy_detail");
    expect(buildCanonicalReportPayload(imported)).not.toContain("mental_energy_detail");
    expect(verifyEntryIntegrity(imported).integrity?.verification_status).toBe("valid");
  });

  it("bruker legacy energidetaljer som fallback når foretrukket felt mangler", () => {
    const preferred = attachIntegrity({ ...report, physical_energy: 2, mental_energy: 4 });
    const aliasOnly = {
      ...report,
      physical_energy: undefined,
      mental_energy: undefined,
      physical_energy_detail: 2,
      mental_energy_detail: 4
    } as unknown as Report;

    expect(buildCanonicalReportPayload(aliasOnly)).toBe(buildCanonicalReportPayload(preferred));
    expect(verifyEntryIntegrity({ ...aliasOnly, integrity: preferred.integrity }).integrity?.verification_status).toBe("valid");
  });

  it("oppdager faktisk endring av rapporterte felt", () => {
    const signed = attachIntegrity({ ...report, note: "Opprinnelig kommentar" });

    expect(verifyEntryIntegrity({ ...signed, work_ability: 1 }).integrity?.verification_status).toBe("modified");
    expect(verifyEntryIntegrity({ ...signed, energy_level: 1 }).integrity?.verification_status).toBe("modified");
    expect(verifyEntryIntegrity({ ...signed, symptom_burden: 5 }).integrity?.verification_status).toBe("modified");
    expect(verifyEntryIntegrity({ ...signed, workplace: "Annet sted" }).integrity?.verification_status).toBe("modified");
    expect(verifyEntryIntegrity({ ...signed, note: "Endret kommentar" }).integrity?.verification_status).toBe("modified");
  });

  it("markerer eldre local-fnv1a-64 metadata som unsupported, ikke modified", () => {
    const legacy = {
      ...report,
      integrity: {
        report_id: report.id,
        canonicalization: "stable-json-v2" as const,
        algorithm: "local-fnv1a-64" as const,
        payload_hash_sha256: "1234",
        signed_at: "2026-05-27T06:00:00.000Z"
      }
    } as Report;

    expect(verifyEntryIntegrity(legacy).integrity?.verification_status).toBe("unsupported");
  });

  it("markerer rapport uten metadata som ikke verifisert", () => {
    const verified = verifyEntryIntegrity(report);

    expect(verified.integrity?.verification_status).toBe("missing");
  });

  it("lager eksportintegritet for manifest", () => {
    const signed = attachIntegrity(report);
    const integrity = createExportIntegrity([signed]);

    expect(integrity.schema).toBe("arbeidsevne-export-integrity-v1");
    expect(integrity.manifest_hash_sha256).toBeTruthy();
  });
});
