import { expect, test } from "bun:test";
import { SCORING_MODEL } from "./scoring-model";
import { calculateScoringResult, deriveTrafficLight, type LlmScoringAssessment } from "./scoring";

function assessmentWithColor(farbe: "gruen" | "gelb" | "rot" | "unbewertbar"): LlmScoringAssessment {
  return {
    ausschlussgruende: [],
    dimensionen: SCORING_MODEL.map((dimension) => ({
      id: dimension.id,
      subcriteria: dimension.subcriteria.map((subcriterion) => ({
        id: subcriterion.id,
        farbe,
        evidence: farbe === "unbewertbar" ? "" : "Test evidence",
        begruendung: "Test begruendung",
        confidence: 0.9,
        missingReason: farbe === "unbewertbar" ? "Keine belastbaren Angaben" : "",
      })),
    })),
  };
}

test("calculates a green weighted score when all criteria are green", () => {
  const scoring = calculateScoringResult(SCORING_MODEL, assessmentWithColor("gruen"));

  expect(scoring.gesamtScore).toBe(100);
  expect(scoring.farbe).toBe("gruen");
  expect(scoring.unbewertbareKriterien).toBe(0);
});

test("scores against the maximum achievable by assessable dimensions", () => {
  const assessment = assessmentWithColor("gruen");
  for (const subcriterion of assessment.dimensionen[4]!.subcriteria) {
    subcriterion.farbe = "unbewertbar";
    subcriterion.evidence = "";
    subcriterion.missingReason = "Keine belastbaren Angaben";
  }

  const scoring = calculateScoringResult(SCORING_MODEL, assessment);

  expect(scoring.gesamtScore).toBe(100);
  expect(scoring.farbe).toBe("gruen");
  expect(scoring.dimensionen[4]!.score).toBe(0);
  expect(scoring.dimensionen[4]!.scorableWeight).toBe(0);
  expect(scoring.unbewertbareKriterien).toBeGreaterThan(0);
});

test("normalizes a partially assessable dimension by answered criterion weight", () => {
  const assessment = assessmentWithColor("gruen");
  const innovation = assessment.dimensionen.find((dimension) => dimension.id === "innovation")!;
  for (const subcriterion of innovation.subcriteria) {
    if (subcriterion.id === "innovation_output") {
      subcriterion.farbe = "unbewertbar";
      subcriterion.evidence = "";
      subcriterion.missingReason = "Keine belastbaren Angaben";
    }
  }

  const scoring = calculateScoringResult(SCORING_MODEL, assessment);
  const innovationScore = scoring.dimensionen.find((dimension) => dimension.id === "innovation")!;

  expect(innovationScore.scorableWeight).toBe(75);
  expect(innovationScore.score).toBe(100);
  expect(scoring.gesamtScore).toBe(100);
  expect(scoring.farbe).toBe("gruen");
});

test("derives red when automatic exclusion reasons are present", () => {
  const scoring = calculateScoringResult(SCORING_MODEL, assessmentWithColor("gruen"));

  expect(deriveTrafficLight(scoring, ["Stiftung als Bewerber"])).toBe("rot");
});

test("keeps low-scoring non-excluded applications yellow rather than discarded", () => {
  const scoring = calculateScoringResult(SCORING_MODEL, assessmentWithColor("rot"));

  expect(scoring.gesamtScore).toBe(0);
  expect(scoring.farbe).toBe("gelb");
  expect(deriveTrafficLight(scoring, [])).toBe("gelb");
});
