import { PrismaClientKnownRequestError } from "@prisma/client/runtime/library";
import { NextResponse } from "next/server";

import { serializeWarehouse } from "@/features/warehouses/lib/serialize-warehouse";
import { warehouseInputSchema } from "@/features/warehouses/schemas/warehouse.schema";
import { createAuditTrailSafe } from "@/lib/audit-trail";
import { buildAuditChangeMetadata } from "@/lib/audit-trail-diff";
import { requireApiAccess } from "@/lib/authorization";
import { resolveMasterCode } from "@/lib/master-code";
import { prisma } from "@/lib/prisma";

type RouteContext = { params: Promise<{ id: string }> };
const parseId = (id: string) => { try { return BigInt(id); } catch { return null; } };

export async function GET(request: Request, context: RouteContext) {
  const auth = requireApiAccess(request);
  if (!auth.ok) return auth.response;

  const parsedId = parseId((await context.params).id);
  if (parsedId === null) return NextResponse.json({ message: "Invalid id" }, { status: 400 });
  const warehouse = await prisma.warehouse.findUnique({ where: { id: parsedId } });
  if (!warehouse) return NextResponse.json({ message: "Warehouse not found" }, { status: 404 });
  return NextResponse.json({ data: serializeWarehouse(warehouse) });
}

export async function PUT(request: Request, context: RouteContext) {
  const auth = requireApiAccess(request);
  if (!auth.ok) return auth.response;

  const parsedId = parseId((await context.params).id);
  if (parsedId === null) return NextResponse.json({ message: "Invalid id" }, { status: 400 });
  const parsed = warehouseInputSchema.safeParse(await request.json());
  if (!parsed.success) {
    return NextResponse.json({ message: "Validasi gagal", errors: parsed.error.flatten().fieldErrors }, { status: 400 });
  }
  try {
    const existing = await prisma.warehouse.findUnique({ where: { id: parsedId } });
    if (!existing) return NextResponse.json({ message: "Warehouse not found" }, { status: 404 });
    const resolvedCode = await resolveMasterCode({
      role: auth.user.role,
      prefix: "WHS",
      requestedCode: parsed.data.code,
      existingCode: existing.code,
      countExisting: () =>
        prisma.warehouse.count({ where: { code: { startsWith: "WHS" } } }),
      exists: async (code) =>
        (await prisma.warehouse.count({ where: { code, id: { not: parsedId } } })) > 0
    });
    if (!resolvedCode.ok) {
      return NextResponse.json({ message: "Validasi gagal", errors: { code: [resolvedCode.message] } }, { status: 400 });
    }
    const warehouse = await prisma.warehouse.update({
      where: { id: parsedId },
      data: {
        code: resolvedCode.code,
        name: parsed.data.name,
        address: parsed.data.address || null,
        status: parsed.data.status
      }
    });
    await createAuditTrailSafe({
      userId: auth.user.id,
      action: "WAREHOUSE_UPDATED",
      entityType: "WAREHOUSE",
      entityId: warehouse.id,
      method: request.method,
      pathname: new URL(request.url).pathname,
      statusCode: 200,
      summary: `Warehouse ${warehouse.code} diubah`,
      metadata: buildAuditChangeMetadata(
        {
          code: existing.code,
          name: existing.name,
          address: existing.address,
          status: existing.status
        },
        {
          code: warehouse.code,
          name: warehouse.name,
          address: warehouse.address,
          status: warehouse.status
        }
      )
    });
    return NextResponse.json({ data: serializeWarehouse(warehouse) });
  } catch (error) {
    if (error instanceof PrismaClientKnownRequestError && error.code === "P2025") {
      return NextResponse.json({ message: "Warehouse not found" }, { status: 404 });
    }
    if (error instanceof PrismaClientKnownRequestError && error.code === "P2002") {
      return NextResponse.json({ message: "Validasi gagal", errors: { code: ["Kode gudang sudah dipakai"] } }, { status: 409 });
    }
    throw error;
  }
}

export async function DELETE(request: Request, context: RouteContext) {
  const auth = requireApiAccess(request);
  if (!auth.ok) return auth.response;

  const parsedId = parseId((await context.params).id);
  if (parsedId === null) return NextResponse.json({ message: "Invalid id" }, { status: 400 });
  try {
    const existing = await prisma.warehouse.findUnique({ where: { id: parsedId } });
    await prisma.warehouse.delete({ where: { id: parsedId } });
    await createAuditTrailSafe({
      userId: auth.user.id,
      action: "WAREHOUSE_DELETED",
      entityType: "WAREHOUSE",
      entityId: parsedId,
      method: request.method,
      pathname: new URL(request.url).pathname,
      statusCode: 200,
      summary: `Warehouse ${existing?.code ?? parsedId.toString()} dihapus`
    });
    return NextResponse.json({ success: true });
  } catch (error) {
    if (error instanceof PrismaClientKnownRequestError && error.code === "P2025") {
      return NextResponse.json({ message: "Warehouse not found" }, { status: 404 });
    }
    throw error;
  }
}
