"use server";

import { auth } from "@/auth";
import { db } from "@/lib/db";
import { hasPermission } from "@/lib/permissions";
import { geocodePincode } from "@/lib/geo";
import { z } from "zod";
import { revalidatePath } from "next/cache";

type ActionResult = { ok: true } | { error: string };

const contactSchema = z.object({
  name: z.string().min(1),
  role: z.string().optional(),
  mobile: z.string().optional(),
  email: z.string().optional(),
  isPrimary: z.boolean().default(false),
});

const vendorSchema = z.object({
  name: z.string().min(1, "Vendor name is required"),
  vendorId: z.string().regex(/^[A-Z0-9]+-\d+$/i, "Vendor ID must be in format PREFIX-NUMBER (e.g. VND-001)").optional(),
  address: z.string().optional(),
  pincode: z.string().optional(),
  gstin: z.string().optional(),
});

function parseContacts(formData: FormData) {
  const contacts: z.infer<typeof contactSchema>[] = [];
  let i = 0;
  while (formData.has(`contacts[${i}].name`)) {
    const name = (formData.get(`contacts[${i}].name`) as string).trim();
    if (name) {
      contacts.push({
        name,
        role: (formData.get(`contacts[${i}].role`) as string) || undefined,
        mobile: (formData.get(`contacts[${i}].mobile`) as string) || undefined,
        email: (formData.get(`contacts[${i}].email`) as string) || undefined,
        isPrimary: formData.get(`contacts[${i}].isPrimary`) === "true",
      });
    }
    i++;
  }
  return contacts;
}

async function resolveLatLng(pincode?: string) {
  if (!pincode) return { latitude: null, longitude: null };
  const coords = await geocodePincode(pincode);
  return { latitude: coords?.lat ?? null, longitude: coords?.lng ?? null };
}

export async function createVendor(formData: FormData): Promise<ActionResult> {
  const session = await auth();
  if (!session?.user || !hasPermission(session.user.role, "create_vendor")) {
    return { error: "Unauthorized" };
  }

  // Submitters (no manage_vendors) may create vendors, but they stay UNVERIFIED
  // until a PO closes with them or a Manager/Accounts/Admin approves them.
  const canVerify = hasPermission(session.user.role, "manage_vendors");

  const parsed = vendorSchema.safeParse({
    name: formData.get("name"),
    vendorId: formData.get("vendorId") || undefined,
    address: formData.get("address") || undefined,
    pincode: formData.get("pincode") || undefined,
    gstin: formData.get("gstin") || undefined,
  });
  if (!parsed.success) return { error: parsed.error.errors[0]?.message ?? "Validation failed" };

  const data = parsed.data;
  // Only verifiers may assign a Vendor ID (which marks a vendor as verified).
  const vendorId = canVerify ? data.vendorId : undefined;
  if (vendorId) {
    const exists = await db.vendor.findUnique({ where: { vendorId } });
    if (exists) return { error: "A vendor with that Vendor ID already exists" };
  }

  const { latitude, longitude } = await resolveLatLng(data.pincode);
  const contacts = parseContacts(formData);

  await db.vendor.create({
    data: {
      name: data.name,
      vendorId: vendorId ?? null,
      address: data.address ?? null,
      pincode: data.pincode ?? null,
      gstin: data.gstin ?? null,
      latitude,
      longitude,
      isVerified: canVerify ? !!vendorId : false,
      contacts: contacts.length > 0 ? { create: contacts } : undefined,
    },
  });

  revalidatePath("/admin/vendors");
  revalidatePath("/catalogue/vendors");
  return { ok: true };
}

/** Approve / verify a vendor — Manager, Accounts or Admin only. */
export async function verifyVendor(vendorId: string): Promise<ActionResult> {
  const session = await auth();
  if (!session?.user || !hasPermission(session.user.role, "manage_vendors")) {
    return { error: "Unauthorized" };
  }

  await db.vendor.update({ where: { id: vendorId }, data: { isVerified: true } });
  revalidatePath("/admin/vendors");
  revalidatePath("/catalogue/vendors");
  revalidatePath(`/admin/vendors/${vendorId}`);
  return { ok: true };
}

export async function updateVendor(formData: FormData): Promise<ActionResult> {
  const session = await auth();
  if (!session?.user || !hasPermission(session.user.role, "manage_vendors")) {
    return { error: "Unauthorized" };
  }

  const id = formData.get("id") as string;
  if (!id) return { error: "Vendor ID is required" };

  const parsed = vendorSchema.safeParse({
    name: formData.get("name"),
    vendorId: formData.get("vendorId") || undefined,
    address: formData.get("address") || undefined,
    pincode: formData.get("pincode") || undefined,
    gstin: formData.get("gstin") || undefined,
  });
  if (!parsed.success) return { error: parsed.error.errors[0]?.message ?? "Validation failed" };

  const data = parsed.data;
  if (data.vendorId) {
    const conflict = await db.vendor.findFirst({ where: { vendorId: data.vendorId, id: { not: id } } });
    if (conflict) return { error: "Another vendor already has that Vendor ID" };
  }

  const existing = await db.vendor.findUnique({ where: { id }, select: { pincode: true, latitude: true, longitude: true } });
  const pincodeChanged = data.pincode !== (existing?.pincode ?? undefined);
  const { latitude, longitude } = pincodeChanged
    ? await resolveLatLng(data.pincode)
    : { latitude: existing?.latitude ?? null, longitude: existing?.longitude ?? null };

  const contacts = parseContacts(formData);

  await db.$transaction(async (tx) => {
    await tx.vendor.update({
      where: { id },
      data: {
        name: data.name,
        vendorId: data.vendorId ?? null,
        address: data.address ?? null,
        pincode: data.pincode ?? null,
        gstin: data.gstin ?? null,
        latitude,
        longitude,
        isVerified: !!data.vendorId,
      },
    });
    // Replace contacts wholesale
    await tx.vendorContact.deleteMany({ where: { vendorId: id } });
    if (contacts.length > 0) {
      await tx.vendorContact.createMany({ data: contacts.map((c) => ({ ...c, vendorId: id })) });
    }
  });

  revalidatePath("/admin/vendors");
  revalidatePath(`/admin/vendors/${id}`);
  return { ok: true };
}

export async function toggleVendorActive(vendorId: string): Promise<ActionResult> {
  const session = await auth();
  if (!session?.user || !hasPermission(session.user.role, "manage_vendors")) {
    return { error: "Unauthorized" };
  }

  const vendor = await db.vendor.findUnique({ where: { id: vendorId }, select: { isActive: true } });
  if (!vendor) return { error: "Vendor not found" };

  await db.vendor.update({ where: { id: vendorId }, data: { isActive: !vendor.isActive } });
  revalidatePath("/admin/vendors");
  return { ok: true };
}

export async function deleteVendor(id: string): Promise<ActionResult> {
  const session = await auth();
  if (!session?.user || !hasPermission(session.user.role, "manage_vendors")) return { error: "Unauthorized" };

  const blocked = await db.purchaseOrder.findFirst({
    where: { vendorId: id, status: { not: "DRAFT" } },
  });
  if (blocked) return { error: "Cannot delete: vendor is referenced in submitted or active purchase orders." };

  try {
    await db.$transaction(
      async (tx) => {
        await tx.purchaseOrder.updateMany({ where: { vendorId: id, status: "DRAFT" }, data: { vendorId: null } });
        await tx.product.updateMany({ where: { lastVendorId: id }, data: { lastVendorId: null } });
        await tx.productVendorPrice.deleteMany({ where: { vendorId: id } });
        await tx.vendor.delete({ where: { id } });
      },
      { timeout: 30000 },
    );
  } catch (err: unknown) {
    const code = (err as { code?: string })?.code;
    if (code === "P2028") {
      return { error: "Delete timed out — please try again." };
    }
    throw err;
  }

  revalidatePath("/admin/vendors");
  return { ok: true };
}
