import type {
  ContractClassThreshold,
  CorpusMeasurementInput,
  MutationRoundSummary,
} from "./types.js";

function selectThreshold(measuredScore: number): number {
  return measuredScore;
}

function thresholdRationale(
  contractClass: string,
  measuredScore: number,
  killedMutants: number,
  totalMutants: number,
): string {
  return `Fixture corpus for ${contractClass} killed ${String(killedMutants)}/${String(totalMutants)} semantic mutants (${(measuredScore * 100).toFixed(0)}%). Threshold equals measured score because no lower observed score exists in the Phase 5 fixture corpus.`;
}

export function measureFixtureCorpusThresholds(
  corpus: readonly CorpusMeasurementInput[],
): ContractClassThreshold[] {
  if (corpus.length === 0) {
    throw new Error("corpus must not be empty");
  }

  return corpus.map((entry) => {
    const { round, contractClass } = entry;
    validateRound(round, contractClass);
    const measuredScore = round.score;
    const threshold = selectThreshold(measuredScore);

    return {
      contractClass,
      measuredScore,
      killedMutants: round.killedMutants,
      totalMutants: round.totalMutants,
      threshold,
      rationale: thresholdRationale(
        contractClass,
        measuredScore,
        round.killedMutants,
        round.totalMutants,
      ),
    };
  });
}

function validateRound(round: MutationRoundSummary, contractClass: string): void {
  if (round.totalMutants <= 0) {
    throw new Error(`corpus entry ${contractClass} has no mutants`);
  }
  if (round.killedMutants < 0 || round.killedMutants > round.totalMutants) {
    throw new Error(`corpus entry ${contractClass} has invalid kill count`);
  }
}

export const MEASURED_MUTATION_THRESHOLDS: ContractClassThreshold[] = [
  {
    contractClass: "journey.order",
    measuredScore: 1,
    killedMutants: 6,
    totalMutants: 6,
    threshold: 1,
    rationale:
      "Fixture corpus for journey.order killed 6/6 semantic mutants (100%). Threshold equals measured score because no lower observed score exists in the Phase 5 fixture corpus.",
  },
  {
    contractClass: "journey.transfer",
    measuredScore: 1,
    killedMutants: 3,
    totalMutants: 3,
    threshold: 1,
    rationale:
      "Fixture corpus for journey.transfer killed 3/3 semantic mutants (100%). Threshold equals measured score because no lower observed score exists in the Phase 5 fixture corpus.",
  },
];
