"use server";

import { revalidatePath } from "next/cache";
import { hasPermission } from "@/lib/adminAuth";
import { connectDB } from "@/lib/db";
import { BlogPost } from "@/models/BlogPost";
import { saveBlogImage, deletePublicUploadImage } from "@/lib/uploads";

const BLOG_ADMIN_PATH = "/de/admin/blog";

type FormState = { error?: string };

function revalidateBlogPaths() {
  revalidatePath(BLOG_ADMIN_PATH);
  revalidatePath("/de/blog");
  revalidatePath("/en/blog");
}

function slugify(input: string): string {
  return input
    .toLowerCase()
    .replace(/ä/g, "ae")
    .replace(/ö/g, "oe")
    .replace(/ü/g, "ue")
    .replace(/ß/g, "ss")
    .normalize("NFKD")
    .replace(/[̀-ͯ]/g, "")
    .replace(/[^a-z0-9]+/g, "-")
    .replace(/^-+|-+$/g, "")
    .slice(0, 150);
}

async function uniqueSlug(base: string, excludeId?: string): Promise<string> {
  const root = slugify(base) || "beitrag";
  let candidate = root;
  let n = 2;
  while (await BlogPost.findOne({ slug: candidate, _id: { $ne: excludeId } }).select("_id").lean()) {
    candidate = `${root}-${n}`;
    n += 1;
  }
  return candidate;
}

function parseTags(value: FormDataEntryValue | null): string[] {
  return String(value || "")
    .split(",")
    .map((t) => t.trim())
    .filter(Boolean)
    .slice(0, 10);
}

function parseDate(value: FormDataEntryValue | null): Date | null {
  const s = String(value || "").trim();
  if (!s) return null;
  const d = new Date(s);
  return Number.isNaN(d.getTime()) ? null : d;
}

export async function createBlogPostAction(_prev: FormState, formData: FormData): Promise<FormState> {
  if (!(await hasPermission("blog_create"))) return { error: "Keine Berechtigung." };
  const title = String(formData.get("title") || "").trim();
  const content = String(formData.get("content") || "").trim();
  if (!title) return { error: "Bitte einen Titel eingeben." };
  if (!content) return { error: "Bitte einen Text eingeben." };

  let coverImage = "";
  const image = formData.get("coverImage");
  if (image instanceof File && image.size > 0) {
    try {
      coverImage = await saveBlogImage(image);
    } catch (err) {
      return { error: err instanceof Error ? err.message : "Bild konnte nicht gespeichert werden." };
    }
  }

  await connectDB();
  const slug = await uniqueSlug(title);
  await BlogPost.create({
    title,
    titleEn: String(formData.get("titleEn") || "").trim(),
    slug,
    excerpt: String(formData.get("excerpt") || "").trim(),
    excerptEn: String(formData.get("excerptEn") || "").trim(),
    content,
    contentEn: String(formData.get("contentEn") || "").trim(),
    coverImage,
    tags: parseTags(formData.get("tags")),
    publishedAt: parseDate(formData.get("publishedAt")) || new Date(),
    visible: formData.get("visible") === "on",
  });

  revalidateBlogPaths();
  return {};
}

export async function updateBlogPostAction(postId: string, formData: FormData) {
  if (!(await hasPermission("blog_edit"))) return;
  const title = String(formData.get("title") || "").trim();
  const content = String(formData.get("content") || "").trim();
  if (!title || !content) return;

  await connectDB();
  const existing = await BlogPost.findById(postId).select("coverImage").lean();
  if (!existing) return;
  // "visible" bewusst nicht Teil dieses Formulars — Sichtbarkeit läuft über
  // den separaten Schalter in der Zeilen-Übersicht (setBlogPostVisibleAction),
  // gleiches Muster wie bei FAQ/Testimonials/Conventions in dieser Runde.
  const update: Record<string, unknown> = {
    title,
    titleEn: String(formData.get("titleEn") || "").trim(),
    excerpt: String(formData.get("excerpt") || "").trim(),
    excerptEn: String(formData.get("excerptEn") || "").trim(),
    content,
    contentEn: String(formData.get("contentEn") || "").trim(),
    tags: parseTags(formData.get("tags")),
  };

  const publishedAt = parseDate(formData.get("publishedAt"));
  if (publishedAt) update.publishedAt = publishedAt;

  const image = formData.get("coverImage");
  if (image instanceof File && image.size > 0) {
    update.coverImage = await saveBlogImage(image);
    if (existing.coverImage) await deletePublicUploadImage(existing.coverImage);
  }

  await BlogPost.findByIdAndUpdate(postId, update);
  revalidateBlogPaths();
}

export async function setBlogPostVisibleAction(postId: string, visible: boolean) {
  if (!(await hasPermission("blog_edit"))) return;
  await connectDB();
  await BlogPost.findByIdAndUpdate(postId, { visible });
  revalidateBlogPaths();
}

export async function deleteBlogPostAction(postId: string) {
  if (!(await hasPermission("blog_delete"))) return;
  await connectDB();
  const post = await BlogPost.findByIdAndDelete(postId).select("coverImage").lean();
  if (post?.coverImage) await deletePublicUploadImage(post.coverImage);
  revalidateBlogPaths();
}
