"use server";

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

export async function provideVendorId({
  poId,
  vendorId,
}: {
  poId: string;
  vendorId: string;
}): Promise<{ ok: true } | { error: string }> {
  const session = await auth();
  if (!session?.user) return { error: "Unauthorized" };

  if (!vendorId) return { error: "Please select a vendor with a verified ID." };

  const po = await db.purchaseOrder.findUnique({
    where: { id: poId },
    include: { submitter: true },
  });
  if (!po) return { error: "PO not found" };
  if (!canPerformAction(po.status, "provide_vendor_id", session.user.role)) {
    return { error: "You cannot provide a vendor ID for this PO in its current state." };
  }

  const vendor = await db.vendor.findUnique({ where: { id: vendorId } });
  if (!vendor?.vendorId) return { error: "The selected vendor does not have a verified ID." };

  await db.purchaseOrder.update({
    where: { id: poId },
    data: {
      vendorId,
      status: "MGR_REVIEW",
      actions: {
        create: { actionType: "VENDOR_ID_PROVIDED", actorId: session.user.id },
      },
    },
  });

  const managers = await db.user.findMany({ where: { role: "MANAGER", isActive: true } });
  await notify({ event: "VENDOR_ID_PROVIDED", po, recipients: managers });

  revalidatePath(`/po/${poId}`);
  return { ok: true };
}

export async function submitDraftPo(
  poId: string
): Promise<{ ok: true } | { error: string }> {
  const session = await auth();
  if (!session?.user) return { error: "Unauthorized" };

  const po = await db.purchaseOrder.findUnique({
    where: { id: poId },
    include: { submitter: true },
  });
  if (!po) return { error: "PO not found" };
  if (po.status !== "DRAFT") return { error: "Only draft purchase orders can be submitted." };
  if (po.submitterId !== session.user.id && session.user.role !== "SUPERUSER") {
    return { error: "You can only submit your own purchase orders." };
  }

  await db.purchaseOrder.update({
    where: { id: poId },
    data: {
      status: "MGR_REVIEW",
      submittedAt: new Date(),
      actions: {
        create: { actionType: "SUBMITTED", actorId: session.user.id },
      },
    },
  });

  const managers = await db.user.findMany({ where: { role: "MANAGER", isActive: true } });
  await notify({ event: "PO_SUBMITTED", po, recipients: managers });

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

export async function discardDraftPo(
  poId: string
): Promise<{ ok: true } | { error: string }> {
  const session = await auth();
  if (!session?.user) return { error: "Unauthorized" };

  const po = await db.purchaseOrder.findUnique({
    where: { id: poId },
    select: { id: true, status: true, submitterId: true },
  });
  if (!po) return { error: "PO not found" };
  if (po.status !== "DRAFT") return { error: "Only DRAFT purchase orders can be discarded." };

  const { role, id: userId } = session.user;
  const canDiscard =
    po.submitterId === userId || ["MANAGER", "SUPERUSER"].includes(role);
  if (!canDiscard) return { error: "You do not have permission to discard this PO." };

  // POAction has no cascade — delete child records before the PO
  await db.$transaction([
    db.pOAction.deleteMany({ where: { poId } }),
    db.notification.deleteMany({ where: { poId } }),
    db.purchaseOrder.delete({ where: { id: poId } }),
  ]);

  revalidatePath("/my-orders");
  revalidatePath("/dashboard");
  return { ok: true };
}

// ── Cancel a PO ───────────────────────────────────────────────────────────────
// MANAGER / SUPERUSER only, from any state, with a mandatory reason. A cancelled
// PO drops out of every spend tracker (those filter on POST_APPROVAL_STATUSES /
// explicit whitelists, none of which include CANCELLED).

export async function cancelPo({
  poId,
  reason,
}: {
  poId: string;
  reason: string;
}): Promise<{ ok: true } | { error: string }> {
  const session = await auth();
  if (!session?.user) return { error: "Unauthorized" };
  if (!hasPermission(session.user.role, "cancel_po")) {
    return { error: "You do not have permission to cancel purchase orders." };
  }

  const trimmed = (reason ?? "").trim();
  if (!trimmed) return { error: "A cancellation reason is required." };

  const po = await db.purchaseOrder.findUnique({
    where: { id: poId },
    include: { submitter: true },
  });
  if (!po) return { error: "PO not found" };
  if (!canCancel(po.status, session.user.role)) {
    return {
      error: po.status === "CANCELLED"
        ? "This purchase order is already cancelled."
        : "You cannot cancel this purchase order.",
    };
  }

  await db.purchaseOrder.update({
    where: { id: poId },
    data: {
      status: "CANCELLED",
      cancelledAt: new Date(),
      cancellationReason: trimmed,
      actions: { create: { actionType: "CANCELLED", actorId: session.user.id, note: trimmed } },
    },
  });

  // Notify the submitter and Accounts (they track spend).
  const accounts = await db.user.findMany({ where: { role: "ACCOUNTS", isActive: true } });
  const recipients = [po.submitter, ...accounts].filter(
    (u, i, arr) => arr.findIndex((x) => x.id === u.id) === i
  );
  await notify({ event: "PO_CANCELLED", po, recipients, note: trimmed });

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

// ── Supersede a cancelled PO with an existing replacement PO ────────────────────
// Links a cancelled PO to the existing PO that replaces it (by PO number). No
// vessel/account/vendor match is enforced. The reciprocal "supersedes" link is
// surfaced on the replacement via the schema self-relation.

export async function supersedePo({
  poId,
  replacementPoNumber,
}: {
  poId: string;
  replacementPoNumber: string;
}): Promise<{ ok: true } | { error: string }> {
  const session = await auth();
  if (!session?.user) return { error: "Unauthorized" };
  if (!hasPermission(session.user.role, "cancel_po")) {
    return { error: "You do not have permission to link a superseding purchase order." };
  }

  const num = (replacementPoNumber ?? "").trim();
  if (!num) return { error: "Enter the PO number that supersedes this one." };

  const po = await db.purchaseOrder.findUnique({
    where: { id: poId },
    select: { id: true, status: true },
  });
  if (!po) return { error: "PO not found" };
  if (po.status !== "CANCELLED") {
    return { error: "Only a cancelled purchase order can be superseded." };
  }

  const replacement = await db.purchaseOrder.findUnique({
    where: { poNumber: num },
    select: { id: true, poNumber: true },
  });
  if (!replacement) return { error: `No purchase order found with number "${num}".` };
  if (replacement.id === po.id) return { error: "A purchase order cannot supersede itself." };

  await db.purchaseOrder.update({
    where: { id: poId },
    data: {
      supersededById: replacement.id,
      actions: {
        create: {
          actionType: "SUPERSEDED",
          actorId: session.user.id,
          note: `Superseded by ${replacement.poNumber}`,
        },
      },
    },
  });

  revalidatePath(`/po/${poId}`);
  revalidatePath(`/po/${replacement.id}`);
  return { ok: true };
}
