/**
 * GET /prechecks — アラート（事前チェック）一覧+サマリ
 *
 * ★返すのは事前チェック異常の行だけ★（ユーザー判断 2026-10-29。出発失敗は清掃詳細ログ・ダッシュボードで見る）。
 * summary・meta.total も事前チェック異常の行だけを数える（`db.prechecks()` が出発失敗の行を作らないため、ここは変えていない）。
 *
 * 形は `app/api/clean-logs/route.ts`（動く見本）に合わせている。
 * 仕様の正は `d-watch-api.yaml` の /prechecks、status=open の意味は docs/decisions.md D-054。
 *
 * ★対応状況の更新（PATCH /prechecks/{id}/status）は `app/api/prechecks/[id]/status/route.ts`★（指示書AT）
 */
import { NextResponse } from "next/server";
import { db } from "@/lib/db";
import { resolveFacilityIdsByMasters } from "@/lib/facilities/resolve-by-master";
import {
  filterPrechecksByDate,
  filterPrechecksByStatus,
  parsePrecheckQuery,
  sortPrechecks,
  summarizePrechecks,
} from "@/lib/prechecks/query";
import { withRequestId } from "@/lib/logger";
import { logApiError } from "@/lib/logger/api";
import type { ApiError, PrecheckItem, SummaryListResponse } from "@/lib/types";
import type { PrecheckSummary } from "@/lib/prechecks/query";

const ROUTE = "/api/prechecks";

function errorResponse(error: ApiError, status: number) {
  return NextResponse.json(error, { status });
}

export async function GET(request: Request) {
  return withRequestId(request, async () => {
    const { searchParams } = new URL(request.url);
    const parsed = parsePrecheckQuery(searchParams);
    if (!parsed.ok) {
      return errorResponse(parsed.error, parsed.status);
    }

    let rows: PrecheckItem[];
    try {
      // ★★日付範囲を SQL に降ろす★★（指示書AC 段階4）—
      //   ★`filterPrechecksByDate()` は**残す**★（指示書AC C-5。絞り込み規則の「正」は
      //   純粋関数のまま。SQL 側はその写し）。
      //   ★★生の `searchParams` を渡していない★★（§E-2）— `parsePrecheckQuery()` が
      //   `YYYY-MM-DD` の形式を検証し、不正なら 422 で上で返している。
      //   ★`filterPrechecksByDate()` と**同じ文字列**を渡すこと★（片方だけ `Date` に
      //   直すと、DBの壁時計値との取り違え（C-6）が入り込む）。
      //   ★★分類（`group_id` / `customer_id`）は施設IDの配列に解決してから SQL に渡す★★
      //   （指示書AK 段階4）— ★`null` = 絞らない / `[]` = 0件★（★罠1★）。
      //   ★`/prechecks` には施設名の検索が無い★ので積集合は要らない
      //   （`d-watch-api.yaml` のクエリパラメータは date_from / date_to / group_id /
      //   customer_id / status / page / per_page のみ）。
      //   ★★施設名で絞りたくなったら先に YAML を直し、`/clean-logs` と同じく
      //   `intersectFacilityIds()` で AND に畳むこと★★（`CLAUDE.md` 作業ルール1）。
      //
      //   ★★サマリ（`summary`）にも効く★★ — ここで母集団ごと絞るので、
      //   ★一覧と「未対応◯件」のカードが同じ母集団から作られる★
      //   （指示書AK §7-2 が `/dashboard` の数値カードについて言っているのと同じ）。
      rows = await db.prechecks({
        date_from: parsed.query.dateFrom,
        date_to: parsed.query.dateTo,
        facility_ids: await resolveFacilityIdsByMasters(parsed.query),
      });
    } catch (e) {
      const body: ApiError = {
        error: { code: "internal_error", message: "データの取得に失敗しました", details: null },
      };
      logApiError({ route: ROUTE, method: "GET", body, status: 500, err: e });
      return errorResponse(body, 500);
    }

    const dated = filterPrechecksByDate(rows, parsed.query);
    // ★summaryは日付範囲で絞った後・対応状況フィルタの前に計算する（D-054）★
    //   状況フィルタの後だと、既定表示（status=open）で解消済みカードが常に0になり、
    //   サマリーの役目を果たさなくなる。日付範囲を変えたときだけ summary が変わる
    const summary: PrecheckSummary = summarizePrechecks(dated);
    const sorted = sortPrechecks(
      filterPrechecksByStatus(dated, parsed.query.status)
    );

    const { page, perPage } = parsed.query;
    // ★meta.total と summary.total は意味が違う★
    //   meta.total   = 一覧（対応状況フィルタ後）の総件数。ページング計算用
    //   summary.total = 日付範囲で絞った当日の全件（対応状況フィルタの影響を受けない）
    //   status=all のときだけ一致する。status=open 等で絞ると meta.total < summary.total になりうる
    const total = sorted.length;
    const start = (page - 1) * perPage;
    const items = sorted.slice(start, start + perPage);

    const body: SummaryListResponse<PrecheckItem, PrecheckSummary> = {
      summary,
      items,
      meta: { total, page, per_page: perPage },
    };
    return NextResponse.json(body);
  });
}
