import { and, eq } from "drizzle-orm";

import { jsonFailure, jsonSuccess, readJsonBody } from "@/modules/core/server/api";
import { recordAuditLog } from "@/modules/core/server/audit";
import { requirePermission } from "@/modules/core/server/auth";
import { getDatabase } from "@/modules/core/server/db";
import { systemIncidents } from "@/modules/core/server/schema";
import type { IncidentStatus } from "@/modules/core/types";

type RouteContext = {
  params: Promise<{
    id: string;
  }>;
};

const INCIDENT_STATUSES: IncidentStatus[] = ["open", "acknowledged", "resolved", "closed"];

function isRecord(value: unknown): value is Record<string, unknown> {
  return typeof value === "object" && value !== null && !Array.isArray(value);
}

function readStatus(value: unknown): IncidentStatus | null {
  if (typeof value !== "string") {
    return null;
  }

  return INCIDENT_STATUSES.find((status) => status === value) ?? null;
}

export async function PATCH(request: Request, context: RouteContext): Promise<Response> {
  const { id } = await context.params;
  const auth = await requirePermission("incident:manage", {
    action: "incident.update",
    targetType: "incident",
    targetId: id,
  });

  if (!auth.success) {
    return auth.response;
  }

  const body = await readJsonBody(request);
  if (!isRecord(body)) {
    return jsonFailure("请求数据格式无效");
  }

  const status = readStatus(body.status);
  if (!status) {
    return jsonFailure("故障状态无效");
  }

  const database = getDatabase();
  const organizationId = auth.context.organization?.id;
  const updateValues = {
    status,
    updatedAt: new Date(),
    acknowledgedByAccountId: status === "acknowledged" ? auth.context.account.id : undefined,
    acknowledgedAt: status === "acknowledged" ? new Date() : undefined,
    resolvedByAccountId: status === "resolved" || status === "closed" ? auth.context.account.id : undefined,
    resolvedAt: status === "resolved" || status === "closed" ? new Date() : undefined,
  };
  const rows = organizationId
    ? await database
        .update(systemIncidents)
        .set(updateValues)
        .where(and(eq(systemIncidents.id, id), eq(systemIncidents.organizationId, organizationId)))
        .returning()
    : await database.update(systemIncidents).set(updateValues).where(eq(systemIncidents.id, id)).returning();
  const incident = rows[0];
  if (!incident) {
    return jsonFailure("故障事件不存在", 404);
  }

  await recordAuditLog({
    actor: auth.context.account,
    organizationId: incident.organizationId ?? undefined,
    action: "incident.update",
    targetType: "incident",
    targetId: incident.id,
    result: "success",
    reason: `故障状态更新为：${status}`,
  });

  return jsonSuccess("故障事件已更新", { incident });
}
