"use server";

import { mkdir, writeFile, unlink } from "node:fs/promises";
import { extname, join } from "node:path";
import { randomBytes } from "node:crypto";
import { revalidatePath } from "next/cache";
import { prisma } from "@/lib/db";
import { requireAdmin } from "@/lib/admin-guard";
import { generateAltForMedia } from "@/lib/seo/image-alt";

const MAX_BYTES = 10 * 1024 * 1024;
const ALLOWED_MIME = new Set([
  "image/jpeg",
  "image/png",
  "image/webp",
  "image/avif",
  "image/gif",
  "image/svg+xml",
]);

const UPLOAD_DIR = process.env.MEDIA_UPLOAD_DIR ?? "public/uploads";
const PUBLIC_BASE = process.env.MEDIA_PUBLIC_BASE ?? "/uploads";

function safeFilename(orig: string): string {
  const base = orig
    .replace(/[^\w.-]+/g, "-")
    .replace(/-+/g, "-")
    .toLowerCase();
  const ext = extname(base) || ".bin";
  const stem = base.slice(0, base.length - ext.length).slice(0, 60) || "file";
  const rand = randomBytes(4).toString("hex");
  const yymm = new Date().toISOString().slice(2, 7).replace("-", "");
  return `${yymm}/${stem}-${rand}${ext}`;
}

export async function uploadMediaAction(formData: FormData) {
  const user = await requireAdmin();
  const file = formData.get("file");
  const alt = (formData.get("alt") as string | null)?.trim() || null;

  if (!(file instanceof File)) return { ok: false as const, error: "Thiếu file." };
  if (file.size === 0) return { ok: false as const, error: "File rỗng." };
  if (file.size > MAX_BYTES)
    return { ok: false as const, error: `File quá lớn (max ${MAX_BYTES / 1024 / 1024}MB).` };
  if (!ALLOWED_MIME.has(file.type))
    return { ok: false as const, error: `MIME không hỗ trợ: ${file.type}` };

  const rel = safeFilename(file.name || "upload");
  const subDir = rel.split("/")[0]!;
  await mkdir(join(UPLOAD_DIR, subDir), { recursive: true });
  const abs = join(UPLOAD_DIR, rel);
  const buf = Buffer.from(await file.arrayBuffer());
  await writeFile(abs, buf);

  const url = `${PUBLIC_BASE.replace(/\/$/, "")}/${rel}`;

  const media = await prisma.media.create({
    data: {
      filename: file.name,
      url,
      mime: file.type,
      size: file.size,
      alt,
      altSource: alt ? "override" : null,
      uploadedBy: user.id,
    },
  });

  // Auto-alt: nếu user upload không kèm alt, sinh thử bằng heuristic + AI.
  // Best-effort — không chặn upload nếu lỗi.
  if (!alt) {
    try {
      const sug = await generateAltForMedia({
        id: media.id,
        url: media.url,
        filename: media.filename,
      });
      if (sug.alt) {
        await prisma.media.update({
          where: { id: media.id },
          data: { alt: sug.alt, altSource: sug.source },
        });
      }
    } catch (e) {
      console.error("[uploadMedia] auto-alt failed:", e);
    }
  }
  await prisma.auditLog.create({
    data: {
      actorId: user.id,
      actorName: user.name,
      actorEmail: user.email,
      source: "admin",
      action: "media.upload",
      target: media.id,
      meta: { filename: file.name, size: file.size, mime: file.type, url } as never,
    },
  });
  revalidatePath("/admin/media");
  return { ok: true as const, id: media.id, url };
}

export async function updateMediaAltAction(id: string, alt: string) {
  const user = await requireAdmin();
  const trimmed = alt.trim();
  await prisma.media.update({
    where: { id },
    data: {
      alt: trimmed || null,
      altSource: trimmed ? "override" : null,
    },
  });
  await prisma.auditLog.create({
    data: {
      actorId: user.id,
      actorName: user.name,
      actorEmail: user.email,
      source: "admin",
      action: "media.update",
      target: id,
      meta: { alt } as never,
    },
  });
  revalidatePath("/admin/media");
  return { ok: true as const };
}

export async function deleteMediaAction(id: string) {
  const user = await requireAdmin();
  const m = await prisma.media.findUnique({ where: { id } });
  if (!m) return { ok: false as const, error: "Không tìm thấy." };

  // Best-effort delete file
  try {
    const rel = m.url.replace(PUBLIC_BASE.replace(/\/$/, ""), "").replace(/^\//, "");
    await unlink(join(UPLOAD_DIR, rel));
  } catch {
    // file may not exist anymore — continue
  }

  await prisma.media.delete({ where: { id } });
  await prisma.auditLog.create({
    data: {
      actorId: user.id,
      actorName: user.name,
      actorEmail: user.email,
      source: "admin",
      action: "media.delete",
      target: id,
      meta: { filename: m.filename, url: m.url } as never,
    },
  });
  revalidatePath("/admin/media");
  return { ok: true as const };
}
