"use server";

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

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

function randomAlpha(len: number): string {
  const chars = "abcdefghijklmnopqrstuvwxyz0123456789";
  return Array.from({ length: len }, () => chars[Math.floor(Math.random() * chars.length)]).join("");
}

function toSlug(name: string): string {
  const base = name
    .toLowerCase()
    .normalize("NFD")
    .replace(/[̀-ͯ]/g, "")
    .replace(/[^a-z0-9]+/g, "-")
    .replace(/^-+|-+$/g, "")
    .slice(0, 44);
  return `${base}-${randomAlpha(4)}`;
}

async function uniqueSlug(base: string): Promise<string | null> {
  if (base.length < 3) return null;
  const candidates = [base, ...Array.from({ length: 8 }, (_, i) => `${base.slice(0, 47)}-${i + 2}`)];
  for (const candidate of candidates) {
    const rows = await db.select({ id: clients.id }).from(clients).where(eq(clients.slug, candidate)).limit(1);
    if (rows.length === 0) return candidate;
  }
  return null;
}

const createClientSchema = z.object({
  name: z.string().min(1, "Nome richiesto"),
  brand_name: z.string().min(1, "Nome brand richiesto"),
  brief: z.string().min(1, "Brief richiesto"),
  email: z.string().optional(),
  phone: z.string().optional(),
});

// Shared core used by both the manual create form and the lead→client
// conversion. Creates the client (+ slug + token), a default project (optionally
// linked to the originating lead), and the two 50/50 payment stubs. Returns the
// new ids. Does NOT redirect — callers decide where to go next.
export async function createClientCore(input: {
  name: string;
  brand_name: string;
  brief: string;
  email?: string | null;
  phone?: string | null;
  created_from_lead_id?: string | null;
}): Promise<{ clientId: string; projectId: string }> {
  const slug = await uniqueSlug(toSlug(input.name));

  const [newClient] = await db
    .insert(clients)
    .values({
      name: input.name,
      brand_name: input.brand_name,
      brief: input.brief,
      email: input.email?.trim() || null,
      phone: input.phone?.trim() || null,
      slug,
    })
    .returning({ id: clients.id, brand_name: clients.brand_name });

  const [newProject] = await db
    .insert(projects)
    .values({
      client_id: newClient.id,
      name: newClient.brand_name,
      created_from_lead_id: input.created_from_lead_id ?? null,
    })
    .returning({ id: projects.id });

  await db.insert(payments).values([
    { project_id: newProject.id, label: "Acconto 50%", amount: "0", status: "da_saldare" },
    { project_id: newProject.id, label: "Saldo 50%", amount: "0", status: "da_saldare" },
  ]);

  return { clientId: newClient.id, projectId: newProject.id };
}

export async function createClient(formData: FormData) {
  await requireAdmin();
  const parsed = createClientSchema.safeParse({
    name: formData.get("name") as string,
    brand_name: formData.get("brand_name") as string,
    brief: formData.get("brief") as string,
    email: (formData.get("email") as string) ?? "",
    phone: (formData.get("phone") as string) ?? "",
  });
  if (!parsed.success) {
    throw new Error(parsed.error.issues.map((i) => i.message).join(", "));
  }

  const { clientId } = await createClientCore(parsed.data);

  revalidatePath("/admin");
  redirect(`/admin/clients/${clientId}`);
}