"use server";

import { revalidatePath } from "next/cache";
import { headers } from "next/headers";
import { hasPermission } from "@/lib/adminAuth";
import { getSessionClientId } from "@/lib/auth";
import { connectDB } from "@/lib/db";
import { DocumentTemplate } from "@/models/DocumentTemplate";
import { GeneratedDocument } from "@/models/GeneratedDocument";
import { Client } from "@/models/Client";
import { DOCUMENT_CATEGORIES, documentCategoryPermission, type DocumentCategory } from "@/lib/documentConstants";

const DOCS_PATH = "/de/admin/documents";

type FormState = { error?: string };

function readCategory(formData: FormData): DocumentCategory {
  const raw = String(formData.get("category") || "other");
  return (DOCUMENT_CATEGORIES.includes(raw as DocumentCategory) ? raw : "other") as DocumentCategory;
}

export async function createTemplateAction(_prev: FormState, formData: FormData): Promise<FormState> {
  const category = readCategory(formData);
  if (!(await hasPermission(documentCategoryPermission(category, "create")))) return { error: "Keine Berechtigung für diese Kategorie." };
  const name = String(formData.get("name") || "").trim();
  const body = String(formData.get("body") || "").trim();
  if (!name) return { error: "Bitte einen Namen eingeben." };
  if (!body) return { error: "Bitte einen Vorlagentext eingeben." };

  await connectDB();
  await DocumentTemplate.create({
    name,
    category,
    body,
    defaultIncludeLetterhead: formData.get("defaultIncludeLetterhead") === "on",
    defaultIncludeFooter: formData.get("defaultIncludeFooter") === "on",
    defaultFooterText: String(formData.get("defaultFooterText") || "").trim(),
    defaultIncludeRecipientAddress: formData.get("defaultIncludeRecipientAddress") === "on",
    sortOrder: Date.now(),
  });
  revalidatePath(DOCS_PATH);
  return {};
}

export async function updateTemplateAction(templateId: string, formData: FormData) {
  await connectDB();
  const existing = await DocumentTemplate.findById(templateId).select("category").lean();
  if (!existing) return;
  const newCategory = readCategory(formData);
  // Braucht Rechte für die bisherige UND (falls geändert) die neue Kategorie —
  // sonst könnte man ein Dokument in eine Kategorie verschieben, auf die man
  // selbst gar keinen Zugriff hat.
  if (!(await hasPermission(documentCategoryPermission(existing.category, "edit")))) return;
  if (!(await hasPermission(documentCategoryPermission(newCategory, "edit")))) return;

  const name = String(formData.get("name") || "").trim();
  const body = String(formData.get("body") || "").trim();
  if (!name || !body) return;

  await DocumentTemplate.findByIdAndUpdate(templateId, {
    name,
    category: newCategory,
    body,
    defaultIncludeLetterhead: formData.get("defaultIncludeLetterhead") === "on",
    defaultIncludeFooter: formData.get("defaultIncludeFooter") === "on",
    defaultFooterText: String(formData.get("defaultFooterText") || "").trim(),
    defaultIncludeRecipientAddress: formData.get("defaultIncludeRecipientAddress") === "on",
  });
  revalidatePath(DOCS_PATH);
}

export async function deleteTemplateAction(id: string) {
  await connectDB();
  const existing = await DocumentTemplate.findById(id).select("category").lean();
  if (!existing) return;
  if (!(await hasPermission(documentCategoryPermission(existing.category, "delete")))) return;
  await DocumentTemplate.findByIdAndDelete(id);
  revalidatePath(DOCS_PATH);
}

// Der volle Dokumenttext kommt bereits fertig bearbeitet aus dem Formular
// (siehe GenerateDocumentPanel) — hier wird nur noch gespeichert, nicht mehr
// aus Platzhaltern zusammengesetzt. So kann für jede Person frei am Text
// gefeilt werden, ohne die Vorlage selbst zu verändern.
export async function generateDocumentAction(
  _prev: FormState,
  formData: FormData
): Promise<FormState & { documentId?: string }> {
  const category = readCategory(formData);
  if (!(await hasPermission(documentCategoryPermission(category, "create")))) return { error: "Keine Berechtigung für diese Kategorie." };
  const createdBy = await getSessionClientId();
  if (!createdBy) return { error: "Nicht eingeloggt." };

  const templateId = String(formData.get("templateId") || "") || null;
  const clientId = String(formData.get("clientId") || "") || null;
  const templateName = String(formData.get("templateName") || "").trim();
  const body = String(formData.get("body") || "").trim();
  if (!templateName) return { error: "Bitte einen Dokumenttitel eingeben." };
  if (!body) return { error: "Bitte einen Dokumenttext eingeben." };

  await connectDB();
  const client = clientId ? await Client.findById(clientId).lean() : null;

  const doc = await GeneratedDocument.create({
    templateId,
    templateName,
    category,
    clientId: client?._id ?? null,
    clientName: client?.name ?? "",
    renderedBody: body,
    includeLetterhead: formData.get("includeLetterhead") === "on",
    includeFooter: formData.get("includeFooter") === "on",
    footerText: String(formData.get("footerText") || "").trim(),
    includeRecipientAddress: formData.get("includeRecipientAddress") === "on",
    recipientAddress: String(formData.get("recipientAddress") || "").trim(),
    createdBy,
  });

  revalidatePath(DOCS_PATH);
  return { documentId: String(doc._id) };
}

// Erstellte Dokumente sind bewusst nicht mehr unveränderlich — anders als
// Rechnungen sind es keine ausgestellten Belege, sondern Arbeitsdokumente,
// bei denen ein Tippfehler nicht gleich ein neues Dokument rechtfertigt.
export async function updateGeneratedDocumentAction(documentId: string, formData: FormData) {
  await connectDB();
  const existing = await GeneratedDocument.findById(documentId).select("category").lean();
  if (!existing) return;
  const newCategory = readCategory(formData);
  if (!(await hasPermission(documentCategoryPermission(existing.category, "edit")))) return;
  if (!(await hasPermission(documentCategoryPermission(newCategory, "edit")))) return;

  const templateName = String(formData.get("templateName") || "").trim();
  const body = String(formData.get("body") || "").trim();
  if (!templateName || !body) return;

  await GeneratedDocument.findByIdAndUpdate(documentId, {
    templateName,
    category: newCategory,
    renderedBody: body,
    includeLetterhead: formData.get("includeLetterhead") === "on",
    includeFooter: formData.get("includeFooter") === "on",
    footerText: String(formData.get("footerText") || "").trim(),
    includeRecipientAddress: formData.get("includeRecipientAddress") === "on",
    recipientAddress: String(formData.get("recipientAddress") || "").trim(),
  });
  revalidatePath(DOCS_PATH);
}

// Einfache elektronische Unterschrift direkt am Dokument — analog zur
// bestehenden TFP-Vertragsunterschrift (Name + Zeitstempel + IP statt
// gezeichnetem Bild). Ein bereits unterschriebenes Dokument kann nicht
// erneut unterschrieben werden, damit der Zeitstempel verlässlich bleibt.
export async function signGeneratedDocumentAction(documentId: string, name: string) {
  await connectDB();
  const existing = await GeneratedDocument.findById(documentId).select("category signature").lean();
  if (!existing || existing.signature) return;
  if (!(await hasPermission(documentCategoryPermission(existing.category, "edit")))) return;
  const trimmedName = name.trim();
  if (!trimmedName) return;

  const ip = (await headers()).get("x-real-ip") || (await headers()).get("x-forwarded-for") || "unknown";
  await GeneratedDocument.findByIdAndUpdate(documentId, {
    signature: { name: trimmedName, signedAt: new Date(), ip },
  });
  revalidatePath(DOCS_PATH);
}

export async function deleteGeneratedDocumentAction(id: string) {
  await connectDB();
  const existing = await GeneratedDocument.findById(id).select("category").lean();
  if (!existing) return;
  if (!(await hasPermission(documentCategoryPermission(existing.category, "delete")))) return;
  await GeneratedDocument.findByIdAndDelete(id);
  revalidatePath(DOCS_PATH);
}
