import { GRADE_THRESHOLDS } from "@/lib/config";
import type { Grade } from "@/lib/types";

/**
 * ◎○△× の判定
 *
 * ★必ず丸める前の生値を渡すこと★
 *   完了率 89.5% は、表示は「90%」だが判定は ○。
 *   丸めてから判定すると ★無いはずの ◎ が生まれる★（CLAUDE.md 4.3 / D-020）。
 *   ★D-139 で境界が「以上」になり、事故の向きが逆になった★ —
 *   旧規則では「90.4 を丸めると ◎ が消える」側だった。★どちらにせよ丸めた値で判定しない★。
 *
 * ★★境界はすべて「上のランクに入る」★★（ユーザー指示 2026-09-16 /
 *   ★D-139★。「◯、×は90%以上のように境はふくめてください」）。
 *   ★D-020b（境界はすべて下のランクに落ちる）は破棄★ — 90.0 は ◎、70.0 は ○。
 *   ★× の境界だけは変わらない★（「10％未満を×としてください」でユーザー確定）。
 *
 * | 判定 | 条件 |
 * |---|---|
 * | ◎ | 完了率 90%以上 |
 * | ○ | 完了率 70%以上 |
 * | △ | 完了率 10%以上 70%未満 |
 * | × | 完了率 10%未満、または未実施 |
 *
 * 閾値は `lib/config` から読む（ハードコード禁止）。
 *
 * @param rate 清掃完了率(%)。未実施は null
 */
export function judgeGrade(rate: number | null): Grade {
  if (rate === null) return "×";
  if (rate >= GRADE_THRESHOLDS.excellent) return "◎";
  if (rate >= GRADE_THRESHOLDS.good) return "○";
  if (rate < GRADE_THRESHOLDS.poor) return "×";
  return "△";
}

/**
 * 表示用の丸め
 *
 * 小数第1位を四捨五入して整数にする（例: 91.4 → 91、89.5 → 90）。
 * ★この値で judgeGrade を呼ばないこと★
 */
export function displayRate(rate: number | null): string {
  if (rate === null) return "-";
  return `${Math.round(rate)}%`;
}

/**
 * 「問題あり」= 判定が △ または ×（★出発の有無を見ない版★）
 *
 * ★閾値を直書きしない★ — 判定は `judgeGrade()` が済ませているので、
 *   ここは「どの判定を問題とみなすか」だけを持つ。
 *
 * ★★`isProblemCompletion()`（`lib/db/clean-log-mapping.ts`）との関係★★ —
 *   あちらは ★完了率（生値）★ を入力に取り `rate === null || rate < GRADE_THRESHOLDS.good`
 *   で判定する。★判定結果は本関数と常に一致する★
 *   （`judgeGrade()` の「○ = 70%以上」より、△× ⟺ `null` または 70 未満。★D-139★）。
 *   ★入力が違うだけの同じ規則★なので、片方の閾値だけを動かさないこと。
 *   ★★本関数は「grade を既に持っている呼び出し側」用★★
 *   （`buildAreaCompletions()` は行ごとに `judgeGrade()` を通したあとの `grade` を持っている。
 *   そこから完了率に戻して `isProblemCompletion()` を呼ぶと、同じ値を2回別の関数で
 *   判定することになる）。★`isProblemCompletion()` は連続日数の算出が使っており、
 *   あちらは grade を作らないまま完了率だけを見ている★。
 */
export function isProblemGrade(grade: Grade): boolean {
  return grade === "△" || grade === "×";
}

/** 「問題あり」= △以下、または出発失敗 */
export function isProblem(input: {
  departed: boolean;
  completionRate: number | null;
}): boolean {
  if (!input.departed) return true;
  return isProblemGrade(judgeGrade(input.completionRate));
}
