"use server";

import { auth } from "@/auth";
import { db } from "@/lib/db";
import { canPerformAction } from "@/lib/po-state-machine";
import { notify } from "@/lib/notifier";
import { revalidatePath } from "next/cache";

export async function confirmReceipt({
  poId,
  notes,
  deliveries,
}: {
  poId: string;
  notes?: string;
  /**
   * Per-line delivery quantities for this receipt event.
   * Key = line item id, value = quantity delivered now (not cumulative).
   * If omitted or empty, all items are treated as fully delivered.
   */
  deliveries?: Record<string, number>;
}): Promise<{ ok: true; partial: boolean } | { error: string }> {
  const session = await auth();
  if (!session?.user) return { error: "Unauthorized" };

  const po = await db.purchaseOrder.findUnique({
    where: { id: poId },
    include: {
      submitter: true,
      lineItems: true,
      vessel: true,
    },
  });
  if (!po) return { error: "PO not found" };

  const isAllowedStatus =
    po.status === "PAID_DELIVERED" ||
    po.status === "PARTIALLY_CLOSED" ||
    po.status === "PARTIALLY_PAID";
  if (!isAllowedStatus) {
    return { error: "You cannot confirm receipt on this PO in its current state." };
  }
  if (
    !canPerformAction(po.status, "confirm_receipt", session.user.role) &&
    !canPerformAction(po.status, "confirm_partial_receipt", session.user.role)
  ) {
    return { error: "You do not have permission to confirm receipt on this PO." };
  }
  if (po.submitterId !== session.user.id && session.user.role !== "SUPERUSER") {
    return { error: "You can only confirm receipt on your own purchase orders." };
  }

  // Reject negative delivery values — only remaining items may be delivered
  if (deliveries) {
    for (const [id, qty] of Object.entries(deliveries)) {
      if (qty < 0) return { error: `Invalid delivery quantity for item ${id}: must be ≥ 0.` };
    }
  }

  // Compute the updated deliveredQuantity for each line item
  const lineUpdates = po.lineItems.map((li) => {
    const prevDelivered = Number(li.deliveredQuantity ?? 0);
    const nowDelivered = deliveries ? (deliveries[li.id] ?? 0) : Number(li.quantity);
    const totalDelivered = prevDelivered + nowDelivered;
    const ordered = Number(li.quantity);
    return {
      id: li.id,
      productId: li.productId,
      quantity: ordered,
      deliveredQuantity: Math.min(totalDelivered, ordered),
      nowDelivered: Math.min(nowDelivered, ordered - prevDelivered),
    };
  });

  // Determine if all items are now fully delivered
  const allDelivered = lineUpdates.every((u) => u.deliveredQuantity >= u.quantity);

  // Re-fetch paidAmount for accurate check
  const updatedPo = await db.purchaseOrder.findUnique({
    where: { id: poId },
    select: { paidAmount: true, totalAmount: true },
  });
  const fullyPaid =
    Number(updatedPo?.paidAmount ?? 0) >= Number(updatedPo?.totalAmount ?? 0);

  const newStatus: "CLOSED" | "PARTIALLY_CLOSED" | "PARTIALLY_PAID" =
    allDelivered && fullyPaid
      ? "CLOSED"
      : !allDelivered && fullyPaid
      ? "PARTIALLY_CLOSED"
      : "PARTIALLY_PAID";

  const isPartial = newStatus !== "CLOSED";

  // Persist delivery quantities
  await Promise.all(
    lineUpdates.map((u) =>
      db.pOLineItem.update({
        where: { id: u.id },
        data: { deliveredQuantity: u.deliveredQuantity },
      })
    )
  );

  // Update PO status and log action
  await db.purchaseOrder.update({
    where: { id: poId },
    data: {
      status: newStatus,
      closedAt: newStatus === "CLOSED" ? new Date() : undefined,
      receipt: notes
        ? {
            upsert: {
              create: { storageKey: "", fileName: "no-file", notes },
              update: { notes },
            },
          }
        : undefined,
      actions: {
        create: {
          actionType: isPartial ? "PARTIAL_RECEIPT_CONFIRMED" : "RECEIPT_CONFIRMED",
          actorId: session.user.id,
          note: notes ?? null,
          metadata: isPartial
            ? {
                deliveries: lineUpdates.map((u) => ({
                  lineItemId: u.id,
                  deliveredNow: u.nowDelivered,
                  totalDelivered: u.deliveredQuantity,
                  ordered: u.quantity,
                })),
              }
            : undefined,
        },
      },
    },
  });

  // Closing a PO auto-verifies its vendor (proof of a real, completed transaction).
  if (newStatus === "CLOSED" && po.vendorId) {
    await db.vendor.update({ where: { id: po.vendorId }, data: { isVerified: true } });
    revalidatePath("/admin/vendors");
    revalidatePath("/inventory/vendors");
  }

  const managers = await db.user.findMany({ where: { role: "MANAGER", isActive: true } });
  if (newStatus === "CLOSED") {
    const accounts = await db.user.findMany({ where: { role: "ACCOUNTS", isActive: true } });
    await notify({ event: "RECEIPT_CONFIRMED", po, recipients: [...managers, ...accounts] });
  } else {
    await notify({ event: "PARTIAL_RECEIPT_CONFIRMED", po, recipients: managers });
  }

  revalidatePath(`/po/${poId}`);
  revalidatePath("/dashboard");
  revalidatePath("/my-orders");
  return { ok: true, partial: isPartial };
}
