"use server";

import { db } from "@/db";
import {
  offer_macros,
  offer_micros,
  offer_services,
  offer_micro_services,
} from "@/db/schema";
import { revalidatePath } from "next/cache";
import { eq } 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");
}

// ── Macro-offer CRUD ─────────────────────────────────────────────────────────

const macroSchema = z.object({
  internal_name: z.string().min(1, "Nome interno richiesto"),
  public_name: z.string().min(1, "Nome pubblico richiesto"),
  transformation_promise: z.string().optional(),
});

export async function createMacro(formData: FormData) {
  await requireAdmin();
  const parsed = macroSchema.safeParse({
    internal_name: formData.get("internal_name"),
    public_name: formData.get("public_name"),
    transformation_promise: formData.get("transformation_promise") ?? "",
  });
  if (!parsed.success) throw new Error(parsed.error.issues[0].message);
  await db.insert(offer_macros).values({
    internal_name: parsed.data.internal_name,
    public_name: parsed.data.public_name,
    transformation_promise: parsed.data.transformation_promise || null,
  });
  revalidatePath("/admin/offers");
}

export async function deleteMacro(macroId: string) {
  await requireAdmin();
  await db.delete(offer_macros).where(eq(offer_macros.id, macroId));
  revalidatePath("/admin/offers");
}

// ── Micro-offer CRUD ─────────────────────────────────────────────────────────

const microSchema = z.object({
  macro_id: z.string().min(1, "Macro offerta richiesta"),
  internal_name: z.string().min(1, "Nome interno richiesto"),
  public_name: z.string().min(1, "Nome pubblico richiesto"),
  transformation_promise: z.string().optional(),
  duration_months: z.coerce.number().int().min(1, "Durata minima 1 mese"),
});

export async function createMicro(formData: FormData) {
  await requireAdmin();
  const parsed = microSchema.safeParse({
    macro_id: formData.get("macro_id"),
    internal_name: formData.get("internal_name"),
    public_name: formData.get("public_name"),
    transformation_promise: formData.get("transformation_promise") ?? "",
    duration_months: formData.get("duration_months"),
  });
  if (!parsed.success) throw new Error(parsed.error.issues[0].message);
  await db.insert(offer_micros).values({
    macro_id: parsed.data.macro_id,
    internal_name: parsed.data.internal_name,
    public_name: parsed.data.public_name,
    transformation_promise: parsed.data.transformation_promise || null,
    duration_months: parsed.data.duration_months,
  });
  revalidatePath("/admin/offers");
}

export async function deleteMicro(microId: string) {
  await requireAdmin();
  // offer_micro_services will cascade; project_offers will restrict (DB constraint)
  await db.delete(offer_micros).where(eq(offer_micros.id, microId));
  revalidatePath("/admin/offers");
}

// ── Offer service CRUD ───────────────────────────────────────────────────────

const offerServiceSchema = z.object({
  name: z.string().min(1, "Nome richiesto"),
  price: z.coerce.number().min(0, "Prezzo non può essere negativo"),
  transformation_description: z.string().optional(),
});

export async function createOfferService(formData: FormData) {
  await requireAdmin();
  const parsed = offerServiceSchema.safeParse({
    name: formData.get("name"),
    price: formData.get("price"),
    transformation_description: formData.get("transformation_description") ?? "",
  });
  if (!parsed.success) throw new Error(parsed.error.issues[0].message);
  await db.insert(offer_services).values({
    name: parsed.data.name,
    price: parsed.data.price.toFixed(2),
    transformation_description: parsed.data.transformation_description || null,
  });
  revalidatePath("/admin/offers");
}

export async function toggleOfferServiceActive(serviceId: string, active: boolean) {
  await requireAdmin();
  await db.update(offer_services).set({ active }).where(eq(offer_services.id, serviceId));
  revalidatePath("/admin/offers");
}

// ── Multi-select service assignment ─────────────────────────────────────────

// Replaces all assignments for a micro with the provided serviceIds (upsert-replace pattern)
export async function updateMicroOfferServices(microId: string, serviceIds: string[]) {
  await requireAdmin();
  // Delete existing assignments for this micro
  await db.delete(offer_micro_services).where(eq(offer_micro_services.micro_id, microId));
  // Re-insert with new set (empty array = unassign all)
  if (serviceIds.length > 0) {
    await db.insert(offer_micro_services).values(
      serviceIds.map((serviceId) => ({ micro_id: microId, service_id: serviceId }))
    );
  }
  revalidatePath("/admin/offers");
}
