"use server";

import { revalidatePath } from "next/cache";
import { redirect } from "next/navigation";
import { eq, inArray } from "drizzle-orm";
import { z } from "zod";
import { db } from "@/lib/db/client";
import { blogPosts } from "@/lib/db/schema";
import { requireAdmin } from "@/lib/auth/admin-guard";
import { logAdminAction } from "@/lib/audit";
import { getLegacyPosts } from "@/lib/legacy/content";

function slugify(input: string): string {
  return input
    .toLowerCase()
    .trim()
    .replace(/[^a-z0-9\s-]/g, "")
    .replace(/\s+/g, "-")
    .replace(/-+/g, "-")
    .slice(0, 80);
}

async function ensureAdmin() {
  const session = await requireAdmin();
  return (session.user as { id?: string }).id!;
}

const blogStatusValues = ["draft", "published", "archived"] as const;

const createPostSchema = z.object({
  title: z.string().min(3).max(200),
  excerpt: z.string().max(600).optional(),
});

export async function createBlogPost(formData: FormData) {
  const adminId = await ensureAdmin();
  const parsed = createPostSchema.parse({
    title: formData.get("title"),
    excerpt: formData.get("excerpt") ?? "",
  });

  let slug = slugify(parsed.title) || "post";
  const [existing] = await db
    .select({ id: blogPosts.id })
    .from(blogPosts)
    .where(eq(blogPosts.slug, slug))
    .limit(1);
  if (existing) slug = `${slug}-${Math.random().toString(36).slice(2, 6)}`;

  const [row] = await db
    .insert(blogPosts)
    .values({
      slug,
      title: parsed.title,
      excerpt: parsed.excerpt ?? "",
      authorUserId: adminId,
    })
    .returning({ id: blogPosts.id });

  await logAdminAction({
    adminUserId: adminId,
    action: "create_blog_post",
    targetId: row.id,
  });

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

const updatePostSchema = z.object({
  id: z.string().uuid(),
  title: z.string().min(3).max(200),
  excerpt: z.string().max(600),
  content: z.string().max(100_000),
  coverImage: z.string().max(400),
  coverImageAlt: z.string().max(400),
  authorName: z.string().max(200),
  tags: z.string().max(400),
  scheduledAt: z.string().max(40).optional(),
});

export async function updateBlogPost(formData: FormData) {
  const adminId = await ensureAdmin();
  const parsed = updatePostSchema.parse({
    id: formData.get("id"),
    title: formData.get("title") ?? "",
    excerpt: formData.get("excerpt") ?? "",
    content: formData.get("content") ?? "",
    coverImage: formData.get("coverImage") ?? "",
    coverImageAlt: formData.get("coverImageAlt") ?? "",
    authorName: formData.get("authorName") ?? "",
    tags: formData.get("tags") ?? "",
    scheduledAt: (formData.get("scheduledAt") as string) ?? "",
  });

  const tags = parsed.tags
    .split(",")
    .map((t) => t.trim())
    .filter(Boolean);

  let scheduledAt: Date | null = null;
  if (parsed.scheduledAt && parsed.scheduledAt.trim().length > 0) {
    const parsedDate = new Date(parsed.scheduledAt);
    if (!Number.isNaN(parsedDate.getTime())) scheduledAt = parsedDate;
  }

  await db
    .update(blogPosts)
    .set({
      title: parsed.title,
      excerpt: parsed.excerpt,
      content: parsed.content,
      coverImage: parsed.coverImage || null,
      coverImageAlt: parsed.coverImageAlt || null,
      authorName: parsed.authorName,
      tags,
      scheduledAt,
      updatedAt: new Date(),
    })
    .where(eq(blogPosts.id, parsed.id));

  await logAdminAction({
    adminUserId: adminId,
    action: "update_blog_post",
    targetId: parsed.id,
  });

  revalidatePath("/admin/blog");
  revalidatePath(`/admin/blog/${parsed.id}`);
  revalidatePath("/blog");
}

const setStatusSchema = z.object({
  id: z.string().uuid(),
  status: z.enum(blogStatusValues),
});

export async function setBlogPostStatus(formData: FormData) {
  const adminId = await ensureAdmin();
  const parsed = setStatusSchema.parse({
    id: formData.get("id"),
    status: formData.get("status"),
  });

  await db
    .update(blogPosts)
    .set({
      status: parsed.status,
      publishedAt: parsed.status === "published" ? new Date() : null,
      updatedAt: new Date(),
    })
    .where(eq(blogPosts.id, parsed.id));

  await logAdminAction({
    adminUserId: adminId,
    action: `blog_post_${parsed.status}`,
    targetId: parsed.id,
  });

  revalidatePath("/admin/blog");
  revalidatePath(`/admin/blog/${parsed.id}`);
  revalidatePath("/blog");
}

/**
 * Import content extracted from the old WordPress dump into blog_posts.
 *
 * Reads the pre-staged payload at src/data/legacy-content.json (built by
 * scripts/extract-legacy-content.py) and upserts each post as a DRAFT —
 * the admin must review and publish. Idempotent: running twice updates
 * the stored body/excerpt but never republishes.
 *
 * Slug prefix "legacy-" avoids colliding with new posts.
 */
export async function importLegacyContent(_formData?: FormData): Promise<void> {
  const adminId = await ensureAdmin();
  const legacy = getLegacyPosts();

  if (legacy.length === 0) {
    revalidatePath("/admin/blog");
    return;
  }

  const legacySlugs = legacy.map((p) => `legacy-${p.slug}`);
  const existing = await db
    .select({ id: blogPosts.id, slug: blogPosts.slug })
    .from(blogPosts)
    .where(inArray(blogPosts.slug, legacySlugs));
  const existingBySlug = new Map(existing.map((r) => [r.slug, r.id]));

  let imported = 0;
  let updated = 0;

  for (const post of legacy) {
    const slug = `legacy-${post.slug}`;
    const title = post.title?.trim() || post.slug;
    const excerpt = (post.excerpt ?? "").slice(0, 600);
    const content = post.html ?? "";
    const coverImage = post.featuredImage || null;

    const tags: string[] = [];
    if (post.type) tags.push(post.type);
    tags.push("legacy");

    const existingId = existingBySlug.get(slug);
    if (existingId) {
      await db
        .update(blogPosts)
        .set({
          title,
          excerpt,
          content,
          coverImage,
          tags,
          updatedAt: new Date(),
        })
        .where(eq(blogPosts.id, existingId));
      updated += 1;
    } else {
      await db.insert(blogPosts).values({
        slug,
        title,
        excerpt,
        content,
        coverImage,
        authorName: "Legacy archive",
        tags,
        status: "draft",
      });
      imported += 1;
    }
  }

  await logAdminAction({
    adminUserId: adminId,
    action: "import_legacy_content",
    metadata: { imported, updated, total: legacy.length },
  });

  revalidatePath("/admin/blog");
  revalidatePath("/blog");
}

export async function deleteBlogPost(formData: FormData) {
  const adminId = await ensureAdmin();
  const id = z.string().uuid().parse(formData.get("id"));
  await db.delete(blogPosts).where(eq(blogPosts.id, id));
  await logAdminAction({
    adminUserId: adminId,
    action: "delete_blog_post",
    targetId: id,
  });
  revalidatePath("/admin/blog");
  revalidatePath("/blog");
  redirect("/admin/blog");
}
