"use server";

import { z } from "zod";
import { eq } from "drizzle-orm";
import { revalidatePath } from "next/cache";
import { redirect } from "next/navigation";
import { db, schema } from "@/lib/db";
import { requireAdmin } from "@/lib/guards";

const statusEnum = z.enum([
  "formulaire",
  "en_attente_paiement",
  "en_cours",
  "termine",
  "annule",
]);

export async function updateDossierStatus(input: {
  dossierId: string;
  status: z.infer<typeof statusEnum>;
}): Promise<{ ok: true } | { ok: false; error: string }> {
  const session = await requireAdmin();
  const parsed = z
    .object({ dossierId: z.string().min(1), status: statusEnum })
    .safeParse(input);
  if (!parsed.success) return { ok: false, error: "Données invalides" };

  const completedAt =
    parsed.data.status === "termine" ? new Date() : null;

  await db
    .update(schema.dossier)
    .set({
      status: parsed.data.status,
      ...(completedAt ? { completedAt } : {}),
      updatedAt: new Date(),
    })
    .where(eq(schema.dossier.id, parsed.data.dossierId));

  await db.insert(schema.activityLog).values({
    dossierId: parsed.data.dossierId,
    actorId: session.user.id,
    action: "statut_change",
    payload: { status: parsed.data.status },
  });

  revalidatePath(`/socialexadmin/dossiers/${parsed.data.dossierId}`);
  revalidatePath("/socialexadmin/dossiers/en-cours");
  revalidatePath("/socialexadmin/dossiers/termines");
  return { ok: true };
}

export async function updateInvoiceStatus(input: {
  invoiceId: string;
  dossierId: string;
  status: "envoyee" | "payee" | "annulee";
}): Promise<{ ok: true } | { ok: false; error: string }> {
  const session = await requireAdmin();
  const parsed = z
    .object({
      invoiceId: z.string().min(1),
      dossierId: z.string().min(1),
      status: z.enum(["envoyee", "payee", "annulee"]),
    })
    .safeParse(input);
  if (!parsed.success) return { ok: false, error: "Données invalides" };

  await db
    .update(schema.invoice)
    .set({
      status: parsed.data.status,
      ...(parsed.data.status === "payee" ? { paidAt: new Date() } : {}),
      updatedAt: new Date(),
    })
    .where(eq(schema.invoice.id, parsed.data.invoiceId));

  await db.insert(schema.activityLog).values({
    dossierId: parsed.data.dossierId,
    actorId: session.user.id,
    action: "facture_statut_change",
    payload: { invoiceId: parsed.data.invoiceId, status: parsed.data.status },
  });

  // Si la facture est payée et que le dossier est en attente paiement,
  // on bascule automatiquement le dossier en cours.
  if (parsed.data.status === "payee") {
    const dossier = (
      await db
        .select()
        .from(schema.dossier)
        .where(eq(schema.dossier.id, parsed.data.dossierId))
        .limit(1)
    )[0];
    if (dossier && dossier.status === "en_attente_paiement") {
      await db
        .update(schema.dossier)
        .set({ status: "en_cours", updatedAt: new Date() })
        .where(eq(schema.dossier.id, parsed.data.dossierId));
    }
  }

  revalidatePath(`/socialexadmin/dossiers/${parsed.data.dossierId}`);
  return { ok: true };
}

export async function updateDocumentStatus(input: {
  documentId: string;
  dossierId: string;
  status: "demande" | "uploade" | "valide" | "rejete";
}): Promise<{ ok: true } | { ok: false; error: string }> {
  const session = await requireAdmin();
  const parsed = z
    .object({
      documentId: z.string().min(1),
      dossierId: z.string().min(1),
      status: z.enum(["demande", "uploade", "valide", "rejete"]),
    })
    .safeParse(input);
  if (!parsed.success) return { ok: false, error: "Données invalides" };

  await db
    .update(schema.document)
    .set({
      status: parsed.data.status,
      ...(parsed.data.status === "valide"
        ? { validatedAt: new Date(), validatedById: session.user.id }
        : {}),
    })
    .where(eq(schema.document.id, parsed.data.documentId));

  revalidatePath(`/socialexadmin/dossiers/${parsed.data.dossierId}`);
  return { ok: true };
}

export async function deleteDossier(dossierId: string): Promise<void> {
  await requireAdmin();
  // Cascade : documents, activity_log via FK onDelete cascade.
  // Les factures associées ont leur dossierId mis à null (set null en FK)
  // pour préserver l'historique comptable.
  await db.delete(schema.dossier).where(eq(schema.dossier.id, dossierId));
  redirect("/socialexadmin/dossiers/en-cours");
}

export async function deleteInvoice(input: {
  invoiceId: string;
  dossierId: string;
}): Promise<{ ok: true } | { ok: false; error: string }> {
  await requireAdmin();
  const parsed = z
    .object({
      invoiceId: z.string().min(1),
      dossierId: z.string().min(1),
    })
    .safeParse(input);
  if (!parsed.success) return { ok: false, error: "Données invalides" };

  await db
    .delete(schema.invoice)
    .where(eq(schema.invoice.id, parsed.data.invoiceId));

  revalidatePath(`/socialexadmin/dossiers/${parsed.data.dossierId}`);
  revalidatePath("/socialexadmin/factures");
  return { ok: true };
}
