"use server";

/**
 * Admin blog post actions: create, update, delete, toggle publish.
 * All require ADMIN role. All write to AuditLog.
 */
import { revalidatePath } from "next/cache";
import { headers } from "next/headers";
import { redirect } from "next/navigation";
import { prisma } from "@/lib/db";
import { requireAdmin, audit } from "@/lib/admin-guard";
import { isValidCategory, makeSlug, parseTags, estimateReadMinutes } from "@/lib/blog";

type ActionResult = { ok: boolean; message?: string; id?: string; slug?: string };

async function getIp(): Promise<string | null> {
  return (await headers()).get("x-forwarded-for")?.split(",")[0]?.trim() ?? null;
}

function readForm(formData: FormData) {
  const title = String(formData.get("title") ?? "").trim();
  const slugRaw = String(formData.get("slug") ?? "").trim();
  const excerpt = String(formData.get("excerpt") ?? "").trim();
  const content = String(formData.get("content") ?? "");
  const coverImage = String(formData.get("coverImage") ?? "").trim() || null;
  const category = String(formData.get("category") ?? "").trim();
  const tagsRaw = String(formData.get("tags") ?? "");
  const authorName = String(formData.get("authorName") ?? "").trim() || "Tử Vi Số";
  const publishNow = formData.get("publishNow") === "on";

  return {
    title,
    slug: slugRaw || makeSlug(title),
    excerpt,
    content,
    coverImage,
    category,
    tags: parseTags(tagsRaw),
    authorName,
    publishNow,
  };
}

function validate(data: ReturnType<typeof readForm>): string | null {
  if (!data.title) return "Tiêu đề không được trống";
  if (data.title.length > 200) return "Tiêu đề tối đa 200 ký tự";
  if (!data.slug) return "Slug không hợp lệ";
  if (!/^[a-z0-9-]+$/.test(data.slug)) return "Slug chỉ chứa a-z, 0-9, dấu gạch ngang";
  if (!data.excerpt) return "Tóm tắt không được trống";
  if (data.excerpt.length > 500) return "Tóm tắt tối đa 500 ký tự";
  if (!data.content || data.content.length < 50) return "Nội dung quá ngắn (tối thiểu 50 ký tự)";
  if (!isValidCategory(data.category)) return "Chuyên mục không hợp lệ";
  return null;
}

export async function createBlogPost(formData: FormData): Promise<ActionResult> {
  const admin = await requireAdmin();
  const data = readForm(formData);
  const err = validate(data);
  if (err) return { ok: false, message: err };

  // Ensure slug is unique
  const existing = await prisma.blogPost.findUnique({ where: { slug: data.slug } });
  if (existing) return { ok: false, message: "Slug đã tồn tại, đổi slug khác" };

  const post = await prisma.blogPost.create({
    data: {
      slug: data.slug,
      title: data.title,
      excerpt: data.excerpt,
      content: data.content,
      coverImage: data.coverImage,
      category: data.category,
      tags: data.tags,
      authorName: data.authorName,
      readMinutes: estimateReadMinutes(data.content),
      publishedAt: data.publishNow ? new Date() : null,
    },
  });

  await audit({
    actorId: admin.userId,
    actorName: admin.name,
    action: "blog.create",
    target: post.slug,
    metadata: { id: post.id, status: data.publishNow ? "published" : "draft" },
    ipAddress: (await getIp()) ?? undefined,
  });

  revalidatePath("/admin/blog");
  revalidatePath("/blog");
  redirect(`/admin/blog/${post.id}/edit`);
}

export async function updateBlogPost(id: string, formData: FormData): Promise<ActionResult> {
  const admin = await requireAdmin();
  const data = readForm(formData);
  const err = validate(data);
  if (err) return { ok: false, message: err };

  const current = await prisma.blogPost.findUnique({ where: { id } });
  if (!current) return { ok: false, message: "Không tìm thấy bài" };

  // If slug changed, check uniqueness
  if (data.slug !== current.slug) {
    const dup = await prisma.blogPost.findUnique({ where: { slug: data.slug } });
    if (dup) return { ok: false, message: "Slug đã tồn tại" };
  }

  await prisma.blogPost.update({
    where: { id },
    data: {
      slug: data.slug,
      title: data.title,
      excerpt: data.excerpt,
      content: data.content,
      coverImage: data.coverImage,
      category: data.category,
      tags: data.tags,
      authorName: data.authorName,
      readMinutes: estimateReadMinutes(data.content),
    },
  });

  await audit({
    actorId: admin.userId,
    actorName: admin.name,
    action: "blog.update",
    target: data.slug,
    metadata: { id, slugChanged: data.slug !== current.slug },
    ipAddress: (await getIp()) ?? undefined,
  });

  revalidatePath("/admin/blog");
  revalidatePath(`/admin/blog/${id}/edit`);
  revalidatePath("/blog");
  if (current.slug !== data.slug) revalidatePath(`/blog/${current.slug}`);
  revalidatePath(`/blog/${data.slug}`);

  return { ok: true, id, slug: data.slug };
}

export async function togglePublish(formData: FormData): Promise<ActionResult> {
  const admin = await requireAdmin();
  const id = String(formData.get("id") ?? "");
  if (!id) return { ok: false, message: "Thiếu id" };

  const post = await prisma.blogPost.findUnique({ where: { id } });
  if (!post) return { ok: false, message: "Không tìm thấy bài" };

  const newDate = post.publishedAt ? null : new Date();
  await prisma.blogPost.update({
    where: { id },
    data: { publishedAt: newDate },
  });

  await audit({
    actorId: admin.userId,
    actorName: admin.name,
    action: newDate ? "blog.publish" : "blog.unpublish",
    target: post.slug,
    metadata: { id },
    ipAddress: (await getIp()) ?? undefined,
  });

  revalidatePath("/admin/blog");
  revalidatePath("/blog");
  revalidatePath(`/blog/${post.slug}`);
  return { ok: true, id, slug: post.slug };
}

export async function deleteBlogPost(formData: FormData): Promise<ActionResult> {
  const admin = await requireAdmin();
  const id = String(formData.get("id") ?? "");
  if (!id) return { ok: false, message: "Thiếu id" };

  const post = await prisma.blogPost.findUnique({ where: { id } });
  if (!post) return { ok: false, message: "Không tìm thấy bài" };

  await prisma.blogPost.delete({ where: { id } });

  await audit({
    actorId: admin.userId,
    actorName: admin.name,
    action: "blog.delete",
    target: post.slug,
    metadata: { id, title: post.title },
    ipAddress: (await getIp()) ?? undefined,
  });

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

/* ---------- Thin void-returning wrappers for direct <form action={…}> usage. */
/* React 19 requires action handlers return Promise<void>. The returning */
/* variants above are kept for future useActionState integration. */

export async function createBlogPostFormAction(formData: FormData): Promise<void> {
  const result = await createBlogPost(formData);
  if (!result.ok) {
    // createBlogPost only returns when validation fails (success path redirects).
    // Bounce back to /admin/blog/new with error in query string.
    redirect(`/admin/blog/new?error=${encodeURIComponent(result.message ?? "error")}`);
  }
}

export async function togglePublishFormAction(formData: FormData): Promise<void> {
  await togglePublish(formData);
}

export async function deleteBlogPostFormAction(formData: FormData): Promise<void> {
  await deleteBlogPost(formData);
}
