"use server";

import { eq, count } from "drizzle-orm";
import { revalidatePath } from "next/cache";
import { db } from "@/db";
import {
  merkmale,
  merkmalOptionen,
  merkmalValues,
  vehicleTemplateMerkmale,
  equipmentCategoryMerkmale,
} from "@/db/schema";
import { requirePlatformAdmin } from "@/lib/auth/guards";
import { writeAudit } from "@/lib/audit";
import {
  merkmalCreateSchema,
  merkmalUpdateSchema,
} from "@/lib/validation/merkmal";
import { slugify } from "@/lib/admin/slug";

export type ActionResult =
  | { ok: true }
  | { ok: false; error: string };

/**
 * Legt ein neues Merkmal an (Status `active`, da vom Admin kuratiert) inkl.
 * Enum-Optionen. Guard zuerst (default-deny). Audit `merkmal.create`.
 */
export async function createMerkmal(input: unknown): Promise<ActionResult> {
  const s = await requirePlatformAdmin();
  const parsed = merkmalCreateSchema.safeParse(input);
  if (!parsed.success) {
    return { ok: false, error: parsed.error.issues[0]?.message ?? "Ungültige Eingabe." };
  }
  const d = parsed.data;

  await db.transaction(async (tx) => {
    const [m] = await tx
      .insert(merkmale)
      .values({
        slug: slugify(d.name),
        name: d.name,
        typ: d.typ,
        einheit: d.einheit ?? null,
        geltungsbereich: d.geltungsbereich,
        status: "active",
      })
      .returning();
    if (!m) throw new Error("Merkmal konnte nicht angelegt werden.");

    if (d.typ === "enum") {
      await tx.insert(merkmalOptionen).values(
        d.optionen.map((o, i) => ({
          merkmalId: m.id,
          wert: o.wert,
          label: o.label,
          reihenfolge: i,
        })),
      );
    }

    await writeAudit(
      s.user.id,
      "merkmal.create",
      "merkmal",
      m.id,
      { name: d.name, typ: d.typ },
      tx,
    );
  });

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

/**
 * Aktualisiert ein Merkmal und ersetzt seine Optionen (delete-then-insert für
 * Enum). Guard zuerst.
 */
export async function updateMerkmal(input: unknown): Promise<ActionResult> {
  const s = await requirePlatformAdmin();
  const parsed = merkmalUpdateSchema.safeParse(input);
  if (!parsed.success) {
    return { ok: false, error: parsed.error.issues[0]?.message ?? "Ungültige Eingabe." };
  }
  const d = parsed.data;

  await db.transaction(async (tx) => {
    await tx
      .update(merkmale)
      .set({
        name: d.name,
        typ: d.typ,
        einheit: d.einheit ?? null,
        geltungsbereich: d.geltungsbereich,
      })
      .where(eq(merkmale.id, d.id));

    await tx.delete(merkmalOptionen).where(eq(merkmalOptionen.merkmalId, d.id));
    if (d.typ === "enum") {
      await tx.insert(merkmalOptionen).values(
        d.optionen.map((o, i) => ({
          merkmalId: d.id,
          wert: o.wert,
          label: o.label,
          reihenfolge: i,
        })),
      );
    }

    await writeAudit(s.user.id, "merkmal.update", "merkmal", d.id, undefined, tx);
  });

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

/**
 * Löscht ein Merkmal — blockiert, wenn es in Werten, Vorlagen oder Kategorien
 * referenziert wird (klare deutsche Fehlermeldung, kein 500).
 */
export async function deleteMerkmal(merkmalId: string): Promise<ActionResult> {
  const s = await requirePlatformAdmin();

  const [vals, tmpl, cats] = await Promise.all([
    db
      .select({ c: count() })
      .from(merkmalValues)
      .where(eq(merkmalValues.merkmalId, merkmalId)),
    db
      .select({ c: count() })
      .from(vehicleTemplateMerkmale)
      .where(eq(vehicleTemplateMerkmale.merkmalId, merkmalId)),
    db
      .select({ c: count() })
      .from(equipmentCategoryMerkmale)
      .where(eq(equipmentCategoryMerkmale.merkmalId, merkmalId)),
  ]);

  const referenced =
    (vals[0]?.c ?? 0) + (tmpl[0]?.c ?? 0) + (cats[0]?.c ?? 0) > 0;
  if (referenced) {
    return {
      ok: false,
      error: "Merkmal wird verwendet und kann nicht gelöscht werden.",
    };
  }

  await db.transaction(async (tx) => {
    await tx
      .delete(merkmalOptionen)
      .where(eq(merkmalOptionen.merkmalId, merkmalId));
    await tx.delete(merkmale).where(eq(merkmale.id, merkmalId));
    await writeAudit(s.user.id, "merkmal.delete", "merkmal", merkmalId, undefined, tx);
  });

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