"use server";

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

const siteSchema = z.object({
  name: z.string().min(1, "Name is required"),
  code: z.string().min(1, "Code is required").max(20).toUpperCase(),
  address: z.string().optional(),
  pincode: z.string().optional(),
  latitude: z.coerce.number().optional(),
  longitude: z.coerce.number().optional(),
});

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

export async function createSite(formData: FormData): Promise<Result> {
  const session = await auth();
  if (!session?.user || !hasPermission(session.user.role, "manage_sites")) return { error: "Forbidden" };

  const parsed = siteSchema.safeParse(Object.fromEntries(formData));
  if (!parsed.success) return { error: parsed.error.errors[0].message };
  const { name, code, address, pincode, latitude, longitude } = parsed.data;

  let lat = latitude, lng = longitude;
  if (!lat && pincode) {
    const geo = await geocodePincode(pincode);
    if (geo) { lat = geo.lat; lng = geo.lng; }
  }

  try {
    await db.site.create({ data: { name, code, address: address ?? null, latitude: lat ?? null, longitude: lng ?? null } });
  } catch {
    return { error: "A site with that code already exists." };
  }
  revalidatePath("/admin/sites");
  return { ok: true };
}

export async function updateSite(id: string, formData: FormData): Promise<Result> {
  const session = await auth();
  if (!session?.user || !hasPermission(session.user.role, "manage_sites")) return { error: "Forbidden" };

  const parsed = siteSchema.safeParse(Object.fromEntries(formData));
  if (!parsed.success) return { error: parsed.error.errors[0].message };
  const { name, code, address, pincode, latitude, longitude } = parsed.data;

  let lat = latitude, lng = longitude;
  if (!lat && pincode) {
    const geo = await geocodePincode(pincode);
    if (geo) { lat = geo.lat; lng = geo.lng; }
  }

  await db.site.update({ where: { id }, data: { name, code, address: address ?? null, latitude: lat ?? null, longitude: lng ?? null } });
  revalidatePath("/admin/sites");
  revalidatePath(`/admin/sites/${id}`);
  return { ok: true };
}

export async function toggleSiteActive(id: string): Promise<Result> {
  const session = await auth();
  if (!session?.user || !hasPermission(session.user.role, "manage_sites")) return { error: "Forbidden" };

  const site = await db.site.findUnique({ where: { id }, select: { isActive: true } });
  if (!site) return { error: "Not found" };
  await db.site.update({ where: { id }, data: { isActive: !site.isActive } });
  revalidatePath("/admin/sites");
  return { ok: true };
}

export async function deleteSite(id: string): Promise<Result> {
  const session = await auth();
  if (!session?.user || !hasPermission(session.user.role, "manage_sites")) return { error: "Forbidden" };

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

  await db.$transaction(async (tx) => {
    await tx.purchaseOrder.updateMany({ where: { siteId: id, status: "DRAFT" }, data: { siteId: null } });
    await tx.itemConsumption.deleteMany({ where: { siteId: id } });
    await tx.itemInventory.deleteMany({ where: { siteId: id } });
    await tx.site.delete({ where: { id } });
  });

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

export async function recordConsumption(formData: FormData): Promise<Result> {
  const session = await auth();
  if (!session?.user) return { error: "Unauthorized" };

  const schema = z.object({
    siteId: z.string().min(1),
    productId: z.string().min(1),
    date: z.string().min(1),
    quantity: z.coerce.number().positive(),
    note: z.string().optional(),
  });
  const parsed = schema.safeParse(Object.fromEntries(formData));
  if (!parsed.success) return { error: parsed.error.errors[0].message };
  const { siteId, productId, date, quantity, note } = parsed.data;

  await db.itemConsumption.upsert({
    where: { productId_siteId_date: { productId, siteId, date: new Date(date) } },
    update: { quantity, note: note ?? null, recordedById: session.user.id },
    create: { productId, siteId, date: new Date(date), quantity, note: note ?? null, recordedById: session.user.id },
  });
  revalidatePath(`/admin/sites/${siteId}`);
  return { ok: true };
}
