import { describe, expect, it } from "vitest";
import {
  calculatePeriodWorkAbilityAssessment,
  calculateReportScore,
  getEntryTime,
  getScoreBand,
  normalizeNegativeScale,
  normalizePositiveScale
} from "./scoring";
import type { Report } from "./types";

const baseReport: 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: 3,
  energy_level: 3,
  mental_clarity: 3,
  symptom_burden: 3,
  effort_strain: 3,
  status: "kan_fortsette",
  physical_energy: 3,
  mental_energy: 3,
  task_types: [],
  main_limitations: [],
  helpful_accommodations: []
};

describe("scoring", () => {
  it("normaliserer positive og negative 1-5-skalaer til 0-100", () => {
    expect(normalizePositiveScale(1)).toBe(0);
    expect(normalizePositiveScale(4)).toBe(75);
    expect(normalizePositiveScale(5)).toBe(100);
    expect(normalizeNegativeScale(1)).toBe(100);
    expect(normalizeNegativeScale(2)).toBe(75);
    expect(normalizeNegativeScale(3)).toBe(50);
    expect(normalizeNegativeScale(4)).toBe(25);
    expect(normalizeNegativeScale(5)).toBe(0);
  });

  it("ignorerer manglende valgfrie felt i totalscore", () => {
    const withoutOptional = calculateReportScore(baseReport);
    const explicitEmpty = calculateReportScore({
      ...baseReport,
      perceived_productivity: undefined,
      task_completion: undefined,
      main_limitations: [],
      helpful_accommodations: []
    });

    expect(explicitEmpty).toBe(withoutOptional);
  });

  it("ignorerer fritekst og arbeidstype i totalscore", () => {
    const baseline = calculateReportScore(baseReport);
    const withExcludedFields = calculateReportScore({
      ...baseReport,
      note: "Dette skal ikke påvirke score.",
      task_types: ["lifting", "noise", "time_pressure"]
    });

    expect(withExcludedFields).toBe(baseline);
  });

  it("lar ikke bare Annet under begrensninger telle positivt", () => {
    expect(calculateReportScore({ ...baseReport, main_limitations: ["other"] })).toBe(calculateReportScore(baseReport));
  });

  it("bruker energidetaljer når de finnes, og samlet energi som fallback", () => {
    const fallback = calculateReportScore({ ...baseReport, energy_level: 5, physical_energy: 5, mental_energy: 5 });
    const details = calculateReportScore({
      ...baseReport,
      energy_level: 5,
      physical_energy_detail: 1,
      mental_energy_detail: 1,
      physical_energy: 1,
      mental_energy: 1
    });
    const oneMissing = calculateReportScore({
      ...baseReport,
      energy_level: 5,
      physical_energy_detail: 1,
      physical_energy: 1,
      mental_energy: 5
    });

    expect(details).toBeLessThan(fallback ?? 0);
    expect(oneMissing).toBeGreaterThan(details ?? 0);
    expect(oneMissing).toBeLessThan(fallback ?? 100);
  });

  it("bruker faktisk timestamp for tidsverdier", () => {
    const early = getEntryTime({ ...baseReport, id: "a", created_at: "2026-05-27T08:00:00.000Z" });
    const late = getEntryTime({ ...baseReport, id: "b", created_at: "2026-05-29T08:00:00.000Z" });

    expect(late - early).toBe(48 * 60 * 60 * 1000);
  });

  it("velger riktig scoreband ved grenseverdier", () => {
    expect(getScoreBand(100)?.label).toBe("Særdeles høyt funksjonsnivå");
    expect(getScoreBand(90)?.label).toBe("Særdeles høyt funksjonsnivå");
    expect(getScoreBand(89)?.label).toBe("Forventet funksjonsnivå");
    expect(getScoreBand(75)?.label).toBe("Forventet funksjonsnivå");
    expect(getScoreBand(70)?.label).toBe("Forventet funksjonsnivå");
    expect(getScoreBand(69)?.label).toBe("Moderat redusert funksjon");
    expect(getScoreBand(50)?.label).toBe("Moderat redusert funksjon");
    expect(getScoreBand(49)?.label).toBe("Betydelig redusert funksjon");
    expect(getScoreBand(30)?.label).toBe("Betydelig redusert funksjon");
    expect(getScoreBand(29)?.label).toBe("Svært lav funksjon");
    expect(getScoreBand(0)?.label).toBe("Svært lav funksjon");
  });

  it("tolker 4 av 5 og invertert 2 av 5 som forventet funksjonsnivå", () => {
    expect(getScoreBand(normalizePositiveScale(4))?.label).toBe("Forventet funksjonsnivå");
    expect(getScoreBand(normalizeNegativeScale(2))?.label).toBe("Forventet funksjonsnivå");
  });

  it("beregner periodens arbeidsevnevurdering fra rapportenes totalscore", () => {
    const assessment = calculatePeriodWorkAbilityAssessment([
      { ...baseReport, id: "a", total_score_percent: 40 },
      { ...baseReport, id: "b", total_score_percent: 68 }
    ]);

    expect(assessment.score_percent).toBe(54);
    expect(assessment.score_band?.label).toBe("Moderat redusert funksjon");
    expect(assessment.report_count).toBe(2);
  });

  it("håndterer tom periode uten score", () => {
    const assessment = calculatePeriodWorkAbilityAssessment([]);

    expect(assessment.score_percent).toBeNull();
    expect(assessment.score_band).toBeNull();
    expect(assessment.report_count).toBe(0);
  });

  it("bruker nye scoreband for periodens arbeidsevnevurdering", () => {
    const assessment = calculatePeriodWorkAbilityAssessment([
      { ...baseReport, id: "a", total_score_percent: 75 },
      { ...baseReport, id: "b", total_score_percent: 75 }
    ]);

    expect(assessment.score_percent).toBe(75);
    expect(assessment.score_band?.label).toBe("Forventet funksjonsnivå");
  });
});
