"use server";

// quote_items NEVER exposed — security constraint from Phase 1 (CLAUDE.md)
// Only accepted_total is visible to client-facing routes

import { db } from "@/db";
import { quote_items, clients, projects } from "@/db/schema";
import { revalidatePath } from "next/cache";
import { eq, asc } from "drizzle-orm";
import { z } from "zod";
import { getServerSession } from "next-auth";
import { authOptions } from "@/lib/auth";

async function requireAdmin() {
  const session = await getServerSession(authOptions);
  if (!session) throw new Error("Non autorizzato");
}

// Works for both clientId and projectId inputs
async function resolveEntity(id: string): Promise<{ projectId: string | null; path: string }> {
  const asProject = await db
    .select({ id: projects.id })
    .from(projects)
    .where(eq(projects.id, id))
    .limit(1);

  if (asProject[0]) {
    return { projectId: id, path: `/admin/projects/${id}` };
  }

  const asClient = await db
    .select({ id: projects.id })
    .from(projects)
    .where(eq(projects.client_id, id))
    .orderBy(asc(projects.created_at))
    .limit(1);

  return { projectId: asClient[0]?.id ?? null, path: `/admin/clients/${id}` };
}

const quoteItemSchema = z.object({
  service_id: z.string().nullable(),
  custom_label: z.string().nullable(),
  quantity: z.coerce.number().min(0.01, "Quantità deve essere > 0"),
  unit_price: z.coerce.number().min(0.01, "Prezzo deve essere > 0"),
});

export async function addQuoteItem(id: string, formData: FormData) {
  await requireAdmin();

  const rawServiceId = formData.get("service_id") as string | null;
  const rawCustomLabel = formData.get("custom_label") as string | null;

  const parsed = quoteItemSchema.safeParse({
    service_id: rawServiceId && rawServiceId !== "" ? rawServiceId : null,
    custom_label: rawCustomLabel && rawCustomLabel !== "" ? rawCustomLabel : null,
    quantity: formData.get("quantity"),
    unit_price: formData.get("unit_price"),
  });

  if (!parsed.success) throw new Error(parsed.error.issues[0].message);

  if (!parsed.data.service_id && !parsed.data.custom_label) {
    throw new Error("Seleziona un servizio dal catalogo o inserisci il nome di una voce libera");
  }

  const { projectId, path } = await resolveEntity(id);
  if (!projectId) throw new Error("Nessun progetto trovato per questo cliente");

  const { service_id, custom_label, quantity, unit_price } = parsed.data;
  const subtotal = (quantity * unit_price).toFixed(2);

  await db.insert(quote_items).values({
    project_id: projectId,
    service_id: service_id ?? null,
    custom_label: custom_label ?? null,
    quantity: quantity.toFixed(2),
    unit_price: unit_price.toFixed(2),
    subtotal,
  });

  revalidatePath(path);
}

export async function removeQuoteItem(quoteItemId: string, id: string) {
  await requireAdmin();
  await db.delete(quote_items).where(eq(quote_items.id, quoteItemId));
  const { path } = await resolveEntity(id);
  revalidatePath(path);
}

export async function updateAcceptedTotal(id: string, formData: FormData) {
  await requireAdmin();
  const raw = (formData.get("accepted_total") as string)?.trim();
  const val = parseFloat(raw);
  if (isNaN(val) || val < 0) throw new Error("Importo non valido");

  const asProject = await db
    .select({ id: projects.id })
    .from(projects)
    .where(eq(projects.id, id))
    .limit(1);

  if (asProject[0]) {
    await db.update(projects).set({ accepted_total: val.toFixed(2) }).where(eq(projects.id, id));
    revalidatePath(`/admin/projects/${id}`);
  } else {
    await db.update(clients).set({ accepted_total: val.toFixed(2) }).where(eq(clients.id, id));
    revalidatePath(`/admin/clients/${id}`);
  }
}