"use server";

import { and, eq } from "drizzle-orm";
import { revalidatePath } from "next/cache";
import { db } from "@/db";
import { users } from "@/db/schema";
import { requireWehrAdmin } from "@/lib/auth/guards";
import { hashPassword } from "@/lib/auth/password";
import { generateTempPassword } from "@/lib/admin/provisioning";
import { writeAudit } from "@/lib/audit";
import {
  brigadeUserCreateSchema,
  brigadeUserDeactivateSchema,
} from "@/lib/validation/brigade-user";

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

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

/**
 * Legt einen Benutzer (lokales Konto) der EIGENEN Wehr an. Rolle ist per Zod auf
 * `wehr_admin|wehr_read` beschränkt (platform_admin wird abgelehnt). Passwort
 * via argon2id (OWASP-Minima). `brigadeId`/`erstelltVon` kommen IMMER aus der
 * Session. Audit `user.create`. Liefert das Einmal-Passwort genau einmal.
 */
export async function createBrigadeUser(
  input: unknown,
): Promise<CreateUserResult> {
  const s = await requireWehrAdmin();
  const parsed = brigadeUserCreateSchema.safeParse(input);
  if (!parsed.success) {
    return {
      ok: false,
      error: parsed.error.issues[0]?.message ?? "Ungültige Eingabe.",
    };
  }
  const d = parsed.data;
  const temp = generateTempPassword();
  const hash = await hashPassword(temp);

  try {
    await db.transaction(async (tx) => {
      const [u] = await tx
        .insert(users)
        .values({
          brigadeId: s.user.brigadeId,
          rolle: d.rolle,
          authTyp: "local",
          email: d.email,
          name: d.name,
          passwortHash: hash,
          aktiv: true,
          erstelltVon: s.user.id,
        })
        .returning({ id: users.id });
      if (!u) throw new Error("Benutzer konnte nicht angelegt werden.");
      await writeAudit(
        s.user.id,
        "user.create",
        "user",
        u.id,
        { rolle: d.rolle, authTyp: "local" },
        tx,
      );
    });
  } catch (e) {
    // Eindeutigkeitsverletzung (E-Mail bereits vergeben) o. Ä.
    const msg =
      e instanceof Error && /unique|duplicate|users_email/i.test(e.message)
        ? "Diese E-Mail ist bereits vergeben."
        : "Benutzer konnte nicht angelegt werden.";
    return { ok: false, error: msg };
  }

  revalidatePath("/verwaltung/benutzer");
  return { ok: true, tempPassword: temp };
}

/**
 * Deaktiviert einen Benutzer der EIGENEN Wehr. Selbst-Deaktivierung ist
 * verboten (sonst sperrt sich ein Admin aus). Scope: nur Benutzer derselben
 * Wehr. Audit `user.deactivate`.
 */
export async function deactivateBrigadeUser(
  input: unknown,
): Promise<DeactivateResult> {
  const s = await requireWehrAdmin();
  const parsed = brigadeUserDeactivateSchema.safeParse(input);
  if (!parsed.success) return { ok: false, error: "Ungültige ID." };
  if (parsed.data.userId === s.user.id) {
    return { ok: false, error: "Sie können sich nicht selbst deaktivieren." };
  }

  const [target] = await db
    .select({ id: users.id })
    .from(users)
    .where(
      and(
        eq(users.id, parsed.data.userId),
        eq(users.brigadeId, s.user.brigadeId),
      ),
    );
  if (!target) return { ok: false, error: "Benutzer nicht gefunden." };

  await db.transaction(async (tx) => {
    await tx
      .update(users)
      .set({ aktiv: false })
      .where(
        and(
          eq(users.id, parsed.data.userId),
          eq(users.brigadeId, s.user.brigadeId),
        ),
      );
    await writeAudit(
      s.user.id,
      "user.deactivate",
      "user",
      parsed.data.userId,
      undefined,
      tx,
    );
  });

  revalidatePath("/verwaltung/benutzer");
  return { ok: true };
}
