"use server";

import { auth } from "@/auth";
import { db } from "@/lib/db";
import { hasPermission } from "@/lib/permissions";
import { generatePoNumber } from "@/lib/po-number";
import { revalidatePath } from "next/cache";
import type { ParsedImportLine } from "@/app/api/po/import/route";

export type ImportPoInput = {
  title: string;
  vesselId: string;
  accountId: string;
  companyId?: string;
  /** Original PO number from the imported Excel — preserved as-is on the PO record.
   *  If absent, a new structured number is generated. */
  originalPoNumber?: string;
  /** vendorId of an existing vendor, if pre-matched in the UI */
  vendorId?: string;
  /** Raw vendor name from the Excel — used to auto-create if no vendorId matched */
  parsedVendorName?: string;
  parsedVendorAddress?: string;
  parsedVendorContact?: string;
  piQuotationNo?: string;
  placeOfDelivery?: string;
  tcDelivery?: string;
  tcDispatch?: string;
  tcInspection?: string;
  tcTransitInsurance?: string;
  tcPaymentTerms?: string;
  tcOthers?: string;
  lineItems: ParsedImportLine[];
};

export async function importPo(
  input: ImportPoInput
): Promise<{ id: string } | { error: string }> {
  const session = await auth();
  if (!session?.user) return { error: "Unauthorized" };
  if (!hasPermission(session.user.role, "create_po") && session.user.role !== "ADMIN") {
    return { error: "You do not have permission to import purchase orders." };
  }

  const now = new Date();

  // ── 1. Resolve / auto-create vendor ───────────────────────────────────────
  let resolvedVendorId: string | null = input.vendorId ?? null;

  if (!resolvedVendorId && input.parsedVendorName) {
    // Try case-insensitive match first
    const existing = await db.vendor.findFirst({
      where: { name: { equals: input.parsedVendorName, mode: "insensitive" } },
      select: { id: true },
    });
    if (existing) {
      resolvedVendorId = existing.id;
    } else {
      // Auto-create vendor from imported data
      const newVendor = await db.vendor.create({
        data: {
          name: input.parsedVendorName,
          address: input.parsedVendorAddress || null,
          contacts: input.parsedVendorContact
            ? {
                create: {
                  name: input.parsedVendorContact,
                  isPrimary: true,
                },
              }
            : undefined,
        },
      });
      resolvedVendorId = newVendor.id;
    }
  }

  // ── 2. Resolve / auto-create products ─────────────────────────────────────
  const resolvedLineItems: Array<
    ParsedImportLine & { productId?: string }
  > = [];

  for (const item of input.lineItems) {
    const existing = await db.product.findFirst({
      where: { name: { equals: item.name, mode: "insensitive" } },
      select: { id: true },
    });

    let productId: string | undefined;
    if (existing) {
      productId = existing.id;
      // Update lastPrice / lastVendor on the product
      if (item.unitPrice > 0) {
        await db.product.update({
          where: { id: existing.id },
          data: {
            lastPrice: item.unitPrice,
            ...(resolvedVendorId ? { lastVendorId: resolvedVendorId } : {}),
          },
        });
      }
    } else {
      // Auto-create product
      const count = await db.product.count();
      const code = `PROD-${String(count + 1).padStart(4, "0")}`;
      const newProduct = await db.product.create({
        data: {
          code,
          name: item.name,
          lastPrice: item.unitPrice > 0 ? item.unitPrice : null,
          lastVendorId: resolvedVendorId ?? null,
        },
      });
      productId = newProduct.id;
    }

    // Upsert per-vendor price so the item catalogue reflects actual invoice prices
    if (productId && resolvedVendorId && item.unitPrice > 0) {
      await db.productVendorPrice.upsert({
        where: { productId_vendorId: { productId, vendorId: resolvedVendorId } },
        update: { price: item.unitPrice },
        create: { productId, vendorId: resolvedVendorId, price: item.unitPrice },
      });
    }

    resolvedLineItems.push({ ...item, productId });
  }

  // ── 3. Calculate total ─────────────────────────────────────────────────────
  const total = resolvedLineItems.reduce(
    (sum, item) => sum + item.quantity * item.unitPrice * (1 + (item.gstRate ?? 0.18)),
    0
  );

  // ── 4. Determine PO number ────────────────────────────────────────────────
  // Preserve the original PO number from the imported document when available;
  // otherwise generate a new structured number starting from 9000+.
  const poNumber = input.originalPoNumber?.trim() || await generatePoNumber(input.vesselId, input.companyId);

  // ── 5. Create PO in CLOSED state ──────────────────────────────────────────
  // Imported POs bypass the approval workflow — they are historical records.
  const po = await db.purchaseOrder.create({
    data: {
      poNumber,
      title: input.title,
      status: "CLOSED",
      totalAmount: total,
      currency: "INR",
      vesselId: input.vesselId,
      accountId: input.accountId,
      companyId: input.companyId ?? null,
      vendorId: resolvedVendorId,
      piQuotationNo: input.piQuotationNo ?? null,
      placeOfDelivery: input.placeOfDelivery ?? null,
      tcDelivery: input.tcDelivery ?? null,
      tcDispatch: input.tcDispatch ?? null,
      tcInspection: input.tcInspection ?? null,
      tcTransitInsurance: input.tcTransitInsurance ?? null,
      tcPaymentTerms: input.tcPaymentTerms ?? null,
      tcOthers: input.tcOthers ?? null,
      submitterId: session.user.id,
      submittedAt: now,
      approvedAt: now,
      paidAt: now,
      closedAt: now,
      lineItems: {
        create: resolvedLineItems.map((item, idx) => ({
          name: item.name,
          quantity: item.quantity,
          unit: item.unit,
          unitPrice: item.unitPrice,
          totalPrice: item.quantity * item.unitPrice,
          gstRate: item.gstRate ?? 0.18,
          sortOrder: idx,
          productId: item.productId ?? null,
        })),
      },
      actions: {
        create: [
          { actionType: "CREATED",   actorId: session.user.id, createdAt: now },
          { actionType: "SUBMITTED", actorId: session.user.id, createdAt: now },
          { actionType: "APPROVED",  actorId: session.user.id, createdAt: now },
          { actionType: "CLOSED",    actorId: session.user.id, createdAt: now },
        ],
      },
    },
  });

  // Imported PO is CLOSED → its vendor is proven by a real transaction, so verify it.
  if (resolvedVendorId) {
    await db.vendor.update({ where: { id: resolvedVendorId }, data: { isVerified: true } });
    revalidatePath("/admin/vendors");
    revalidatePath("/catalogue/vendors");
  }

  revalidatePath("/history");
  revalidatePath("/dashboard");
  return { id: po.id };
}
