/**
 * GET / POST / DELETE /ds-devices/{serial_number}/agent-token — 制御盤トークンの発行日時・発行・失効
 * （指示書AY 段階7-1。D16・P1・P2・D-179）
 *
 * 仕様の正は `d-watch-api.yaml` の同パス。★既存の cookie 認証のパス★（制御盤のトークンでは作り直せない。表4 A11）。
 * ★生のトークンは POST の応答で1回だけ★（`Cache-Control: no-store`）。保存は SHA-256 だけ（DFA 独自ストア。メインDBには書かない）。
 * ★ログは `serial_number` だけ★（表3 KA8）。
 */
import { NextResponse } from "next/server";
import { parsePathSerialNumber } from "@/lib/api/path-params";
import { db } from "@/lib/db";
import { errorBody, jsonError, noContent } from "@/lib/ds-agent/agent-request";
import { ensureDsAgentLogging } from "@/lib/ds-agent/relay-log";
import { agentTokenIssuedAt, issueAgentToken, revokeAgentToken } from "@/lib/ds-agent/tokens";
import { logEvent, withRequestId } from "@/lib/logger";
import { logApiError } from "@/lib/logger/api";
import type { DsAgentTokenIssued, DsAgentTokenStatus } from "@/lib/types";

const ROUTE = "/api/ds-devices/[serial_number]/agent-token";

type Method = "GET" | "POST" | "DELETE";

async function withDevice(
  method: Method,
  request: Request,
  params: Promise<{ serial_number: string }>,
  action: (serial: string) => Promise<Response>
): Promise<Response> {
  return withRequestId(request, async () => {
    ensureDsAgentLogging();
    const { serial_number: serialRaw } = await params;
    const parsedSerial = parsePathSerialNumber(serialRaw);
    if (!parsedSerial.ok) return NextResponse.json(parsedSerial.error, { status: parsedSerial.status });
    const serial = parsedSerial.query;
    try {
      if (!(await db.dsDeviceExists(serial))) return jsonError(404, "not_found", "デバイスが見つかりません");
      return await action(serial);
    } catch (e) {
      const body = errorBody("internal_error", "制御盤トークンの処理に失敗しました");
      logApiError({ route: ROUTE, method, body, status: 500, err: e });
      return NextResponse.json(body, { status: 500 });
    }
  });
}

export async function GET(request: Request, { params }: { params: Promise<{ serial_number: string }> }) {
  return withDevice("GET", request, params, async (serial) => {
    const body: DsAgentTokenStatus = { issued_at: await agentTokenIssuedAt(serial) };
    return NextResponse.json(body);
  });
}

export async function POST(request: Request, { params }: { params: Promise<{ serial_number: string }> }) {
  return withDevice("POST", request, params, async (serial) => {
    const issued = await issueAgentToken(serial);
    logEvent("info", { event: "ds_agent.token_issued", serial_number: serial });
    const body: DsAgentTokenIssued = { token: issued.token, issued_at: issued.issued_at };
    return NextResponse.json(body, { status: 201, headers: { "Cache-Control": "no-store" } });
  });
}

export async function DELETE(request: Request, { params }: { params: Promise<{ serial_number: string }> }) {
  return withDevice("DELETE", request, params, async (serial) => {
    // ★未発行でも 204（冪等。P2）★。ログは実際に失効させたときだけ
    if (await revokeAgentToken(serial)) {
      logEvent("info", { event: "ds_agent.token_revoked", serial_number: serial });
    }
    return noContent();
  });
}
