/**
 * GET /clean-logs/export のCSV組み立て。
 *
 * ルート（`app/api/clean-logs/export/route.ts`）から切り出してある。
 * 理由は★テストを書くため★で、ルートの `route.ts` は Next.js の App Router が
 * HTTPメソッド以外の export を想定していないため、ここに置いてから import する。
 * ★行の組み立て（`buildCleanLogCsv()`）も同じ理由でここに置く★ —
 * 「全列が `csvCell()` を通っているか」はセル単体のテストでは確かめられない。
 */
import { csvDocument, csvRate } from "@/lib/csv";
import {
  CLEAN_LOG_UNSCHEDULED_LABEL,
  CLEAN_RESULT_PENDING_LABEL,
  cleanLogRowView,
} from "@/lib/format/clean-result";
import { formatHm, formatYmdSlash } from "@/lib/format/date";
import type { CleanLogItem } from "@/lib/types";

/**
 * ★`csvCell()` の本体は `lib/csv.ts` へ移した★（D-163。レポートの施設別パフォーマンス CSV と共有するため）。
 * 既存の import 先（`@/lib/clean-logs/csv`）を壊さないよう、ここから再エクスポートする。
 */
export { csvCell } from "@/lib/csv";

/** ヘッダ行の見出し（モックの列順に合わせる） */
export const CLEAN_LOG_CSV_HEADER = [
  "施設名",
  "機種",
  "シリアル",
  "日付",
  "予定時刻",
  // ★事前チェックは「1回目 / 2回目」と「何分前か」の4列★（D-178。ユーザー判断 2026-10-16）—
  //   列は分数ではなく順番で割り当てる（早い方が1回目）ので、見出しに分数を書かず、分数は隣の列に数値で出す。
  //   ★旧: 「1h前ST」「30分前ST」★（設定で分数が変わると見出しと中身が食い違うため改めた）
  "事前チェック1回目",
  "1回目（分前）",
  "事前チェック2回目",
  "2回目（分前）",
  "出発",
  // ★画面（CleanLogTable）と同じ位置★ — `出発`（✓/✗）も `清掃結果` も出所は同じ
  // `clean_task_reports`（行の有無と `status`。指示書AQ §1-1 / §1-2）なので、
  // 隣に並べてその場で読めるようにする。★中身は `status` の日本語の表示名（例 `清掃正常終了`）★
  // （第10回 N-2。D-155 項2）。★表に無い値（6 など）は数字のまま★。★CSV は言語を受け取らないので
  // 見出しと同じく日本語固定★（指示書AS D11）。
  // 列順を画面と変えると、突き合わせる人が毎回並べ替えることになる（指示書AO 段階3）。
  "清掃結果",
  "完了率",
  "判定",
] as const;

/**
 * 清掃詳細ログのCSV本体を組み立てる（UTF-8 BOM付き・CRLF区切り）。
 *
 * ★全列を例外なく `csvCell()` に通す★
 *   「この列は固定文言だから安全」という判断を列ごとにすると、後から列を足した人が
 *   同じ判断を迫られて漏れる。実際 `displayRate()` は未実施（`completion_rate: null`）で
 *   ★`-` を返す★（`lib/judge/grade.ts`）ので、安全に見える列が
 *   数式インジェクションの入口になっていた。関門を1つにしておけば、
 *   列の追加は「生の文字列を並べる」だけで済む。
 *   ★`csvCell()` を通すのは `csvDocument()`（`lib/csv.ts`）の中★（D-163。ここでは包まない）。
 *
 * ★完了率は `csvRate()`（null は空欄）★（ユーザー指示 2026-10-06「値がないとこは空欄で」。D-164）。
 *   `displayRate()` の `-` を出すと関門が `'-` にして、Excel で `'-` と見えていた。
 *   ★清掃結果列（`task_status` が null）は値の欠けではなく表示名なので、ここでは変えない★。
 */
export function buildCleanLogCsv(rows: CleanLogItem[]): string {
  return csvDocument(
    CLEAN_LOG_CSV_HEADER,
    rows.map((r) => {
      // ★結果待ち（D-173）★ — 見え方は画面と同じ `cleanLogRowView()` で決める（ユーザー判断 2026-10-07）。
      //   結果待ちは 出発・清掃結果が「結果待ち」、★完了率・判定は空のセル★（「-」を入れない。D-164）
      const view = cleanLogRowView(r);
      return [
        r.facility_name,
        // ★null（清掃エリアに有効なロボットがいない。指示書BB U2・D-182）は空のセル★（`'-` にしない。D-164 と同じ理由）
        r.model_name ?? "",
        r.serial_number ?? "",
        // ★日付は年つき `YYYY/MM/DD`（指示書BB A4・D-182。旧: `M/D`。画面の `formatMd()` は変えない）★
        // ★予定外タスクの行（指示書BG §2-1）★ — 日付は `scheduled_at`（＝ `started_at`）の日付、予定時刻は「予定外」。
        //   事前チェックの4列は null なので下で空のセルになる
        formatYmdSlash(r.scheduled_at),
        r.unscheduled ? CLEAN_LOG_UNSCHEDULED_LABEL : formatHm(r.scheduled_at),
        // ★null（事前チェックの予定が無い）は空のセル★（ユーザー指示 2026-10-07。D-171）。
        //   ★画面の「-」を入れないこと★ — `csvCell()` の数式対策で `'-` になる（D-164 と同じ理由）
        r.status_1h ?? "",
        // ★分数は数値のまま（例 60）。null（その回の予定が無い）は空のセル★（D-178）
        r.status_1h_minutes === null ? "" : String(r.status_1h_minutes),
        r.status_30m ?? "",
        r.status_30m_minutes === null ? "" : String(r.status_30m_minutes),
        view.departed === "pending"
          ? CLEAN_RESULT_PENDING_LABEL
          : view.departed === "ok"
            ? "出発"
            : "未出発",
        view.resultLabel,
        csvRate(view.completionRate),
        view.gradeShown ? r.grade : "",
      ];
    })
  );
}
