import { NextResponse } from "next/server";

import { ensureSystemUser } from "@/features/purchases/lib/system-user";
import { generateReceiptNo } from "@/features/receipts/lib/generate-receipt-no";
import {
  serializeReceiptDetail,
  serializeReceiptListItem
} from "@/features/receipts/lib/serialize-receipt";
import { receiptInputSchema } from "@/features/receipts/schemas/receipt.schema";
import { createAuditTrailSafe } from "@/lib/audit-trail";
import { prisma } from "@/lib/prisma";
import { requireApiAccess } from "@/lib/authorization";

const receiptDetailInclude = {
  purchase: true,
  lines: {
    include: {
      grade: true,
      unit: true,
      warehouse: true,
      warehouseLocation: true
    }
  },
  lots: true
} as const;

export async function GET(request: Request) {
  const auth = requireApiAccess(request);
  if (!auth.ok) return auth.response;
  const data = await prisma.receipt.findMany({
    include: {
      purchase: true,
      lines: true,
      lots: true
    },
    orderBy: [{ createdAt: "desc" }]
  });

  return NextResponse.json({
    data: data.map(serializeReceiptListItem)
  });
}

export async function POST(request: Request) {
  const auth = requireApiAccess(request);
  if (!auth.ok) return auth.response;
  const parsed = receiptInputSchema.safeParse(await request.json());
  if (!parsed.success) {
    return NextResponse.json(
      { message: "Validasi gagal", errors: parsed.error.flatten().fieldErrors },
      { status: 400 }
    );
  }

  const systemUser = await ensureSystemUser();
  const receiptDate = new Date(`${parsed.data.receipt_date}T00:00:00.000Z`);
  const receiptNo = await generateReceiptNo(receiptDate);
  const purchaseId = BigInt(parsed.data.purchase_id);

  const purchase = await prisma.purchase.findUnique({
    where: { id: purchaseId },
    include: {
      _count: {
        select: {
          receipts: true,
          lots: true
        }
      }
    }
  });

  if (!purchase) {
    return NextResponse.json({ message: "Purchase not found" }, { status: 404 });
  }

  if (purchase.status !== "SUBMITTED") {
    return NextResponse.json(
      { message: "Purchase harus diajukan sebelum dibuatkan receipt." },
      { status: 409 }
    );
  }

  if (purchase._count.receipts > 0 || purchase._count.lots > 0) {
    return NextResponse.json(
      { message: "Purchase sudah memiliki receipt/lot." },
      { status: 409 }
    );
  }

  const receipt = await prisma.receipt.create({
    data: {
      receiptNo,
      purchaseId,
      receiptDate,
      status: "DRAFT",
      notes: parsed.data.notes || null,
      receivedById: systemUser.id,
      lines: {
        create: parsed.data.lines.map((line) => ({
          purchaseLineId: BigInt(line.purchase_line_id),
          gradeId: line.grade_id ? BigInt(line.grade_id) : null,
          qtyReceived: line.qty_received,
          qtyAccepted: line.qty_accepted,
          qtyRejected: line.qty_rejected,
          unitId: BigInt(line.unit_id),
          unitCost: line.unit_cost,
          warehouseId: BigInt(line.warehouse_id),
          warehouseLocationId: line.warehouse_location_id
            ? BigInt(line.warehouse_location_id)
            : null,
          notes: line.notes || null
        }))
      }
    },
    include: receiptDetailInclude
  });

  await createAuditTrailSafe({
    userId: auth.user.id,
    action: "RECEIPT_CREATED",
    entityType: "RECEIPT",
    entityId: receipt.id,
    method: request.method,
    pathname: new URL(request.url).pathname,
    statusCode: 201,
    summary: `Receipt ${receipt.receiptNo} dibuat`,
    metadata: {
      receipt_no: receipt.receiptNo,
      purchase_no: receipt.purchase.purchaseNo,
      line_count: receipt.lines.length
    }
  });

  return NextResponse.json({ data: serializeReceiptDetail(receipt) }, { status: 201 });
}
