import { NextResponse } from "next/server";
import { prisma } from "@/lib/db";
import { requireAdmin } from "@/lib/admin-guard";
import { generateAltForMedia } from "@/lib/seo/image-alt";

/**
 * POST /api/admin/media/[id]/generate-alt
 * body: { apply?: boolean }
 *
 * Generate an alt-text suggestion. When apply=true, persist it to Media.alt
 * AND propagate to article body Markdown (replace `![](.../filename)` with
 * `![alt](.../filename)`).
 */
export const runtime = "nodejs";
export const dynamic = "force-dynamic";

export async function POST(
  req: Request,
  { params }: { params: Promise<{ id: string }> },
) {
  const user = await requireAdmin();
  const { id } = await params;

  const media = await prisma.media.findUnique({ where: { id } });
  if (!media) return NextResponse.json({ ok: false, error: "Not found" }, { status: 404 });

  let body: { apply?: boolean; override?: string };
  try {
    body = (await req.json()) as { apply?: boolean; override?: string };
  } catch {
    body = {};
  }

  const suggestion = await generateAltForMedia({
    id: media.id,
    url: media.url,
    filename: media.filename,
  });

  if (body.apply) {
    const finalAlt = (body.override ?? suggestion.alt).trim().slice(0, 200);
    const altSource = body.override ? "override" : suggestion.source;
    if (finalAlt) {
      await prisma.media.update({
        where: { id },
        data: { alt: finalAlt, altSource },
      });

      // Propagate to article bodies that embed this image with empty alt.
      // We only rewrite `![](.../filename)` → `![finalAlt](...)` to avoid
      // overwriting alts the editor already set manually.
      const variants = [media.url, `/${media.filename}`, media.filename];
      const referenced = await prisma.article.findMany({
        where: { OR: variants.map((v) => ({ content: { contains: v } })) },
        select: { id: true, content: true },
      });

      for (const a of referenced) {
        if (!a.content) continue;
        let content = a.content;
        let touched = false;
        for (const v of variants) {
          // match `![]( v ... )` (ignoring spaces) and inject alt
          const re = new RegExp(
            `!\\[\\]\\(([^)]*${v.replace(/[.*+?^${}()|[\\]\\\\]/g, "\\$&")}[^)]*)\\)`,
            "g",
          );
          const before = content;
          content = content.replace(re, `![${finalAlt}]($1)`);
          if (before !== content) touched = true;
        }
        if (touched) {
          await prisma.article.update({
            where: { id: a.id },
            data: { content },
          });
        }
      }

      // Audit
      await prisma.auditLog.create({
        data: {
          actorId: user.id,
          actorName: user.name,
          actorEmail: user.email,
          source: "admin",
          action: "media.alt_generate",
          target: media.id,
          meta: {
            filename: media.filename,
            alt: finalAlt,
            generationSource: suggestion.source,
            propagatedTo: referenced.map((r) => r.id),
          } as never,
        },
      });
    }
  }

  return NextResponse.json({ ok: true, suggestion });
}
