/**
 * GET /errors — エラー一覧（`robot_error_reports` の未対応エラー。D-160 / 指示書AW 段階4-2）
 *
 * 形は `app/api/clean-logs/route.ts`（動く見本）と `app/api/prechecks/route.ts` に揃えている。
 * 仕様の正は `d-watch-api.yaml` の /errors。
 *
 * ★対象は `robot_error_reports` の行★（事前チェック・本清掃・予定なし・制御盤・セキュリティ・清掃開始失敗を問わない）。★削除済みの施設・清掃エリアの行はデータ層が外す（指示書AX U8。このルートは何もしない）★。
 *   `/prechecks`（アラート画面）は事前チェック行に紐づくエラーと出発失敗だけなので、そちらとは別のルートにした。
 *
 * このルートがやっていること
 *   1. クエリパラメータのパース（`parseErrorReportQuery()`。不正なら422）
 *   2. ★施設名・分類 → 施設ID の解決★（`resolveFacilityIdsByName()` / `resolveFacilityIdsByMasters()` を
 *      `intersectFacilityIds()` で AND に畳む。`/clean-logs` と同じ。★`null` = 絞らない / `[]` = 0件★）
 *   3. `db.errorReports()` — ★絞り込み・並べ替え・ページ分けはデータ層の中★（2段階で読む。指示書AW D8）。
 *      ★`errored_at ?? created_at` の順は Prisma のクエリビルダで書けない★ので、ルートで並べ直す必要は無い
 *      （fixtures 版・Prisma 版とも `filterSortErrorReportKeys()` を通る）
 *   4. `{ items, meta }` 形式で返却（`summary` は無い）
 *
 * ★対応状況の更新（PATCH /errors/{error_id}/status）は `app/api/errors/[error_id]/status/route.ts`★
 */
import { NextResponse } from "next/server";
import { db } from "@/lib/db";
import { parseErrorReportQuery } from "@/lib/error-reports/query";
import { intersectFacilityIds } from "@/lib/facilities/intersect-ids";
import { resolveFacilityIdsByMasters } from "@/lib/facilities/resolve-by-master";
import { resolveFacilityIdsByName } from "@/lib/facilities/resolve-by-name";
import { withRequestId } from "@/lib/logger";
import { logApiError } from "@/lib/logger/api";
import type { ApiError, ErrorReportItem, ListResponse } from "@/lib/types";

const ROUTE = "/api/errors";

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 = parseErrorReportQuery(searchParams);
    if (!parsed.ok) {
      return errorResponse(parsed.error, parsed.status);
    }
    const q = parsed.query;

    let result: { items: ErrorReportItem[]; total: number };
    try {
      // ★★2本の解決結果は `intersectFacilityIds()` で AND に畳む★★（`/clean-logs` と同じ。指示書AW D10）—
      //   ★どちらか片方を捨てないこと★（`??` で書くと片方の条件が静かに消える）。
      //   ★積集合が空なら `[]`（＝0件）★。`null` にすると「絞らない」になり、0件ヒットが全件表示に化ける（罠1）
      const [nameIds, masterIds] = await Promise.all([
        resolveFacilityIdsByName(q.facilityName),
        resolveFacilityIdsByMasters(q),
      ]);
      result = await db.errorReports({
        include_resolved: q.includeResolved,
        facility_ids: intersectFacilityIds(nameIds, masterIds),
        // ★`parseErrorReportQuery()` を通った値を渡す★（空文字は `null` に正規化済み）
        date_from: q.dateFrom,
        date_to: q.dateTo,
        error_type: q.errorType,
        sort: q.sort,
        order: q.order,
        schedule: q.schedule,
        page: q.page,
        per_page: q.perPage,
      });
    } 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 body: ListResponse<ErrorReportItem> = {
      items: result.items,
      meta: { total: result.total, page: q.page, per_page: q.perPage },
    };
    return NextResponse.json(body);
  });
}
