import { z } from "zod";
import { NextRequest } from "next/server";
import { apiError, apiOk, requireApiToken } from "@/lib/api-auth";
import { prisma } from "@/lib/db";
import { createArticle } from "@/lib/articles-repo";

export const runtime = "nodejs";

// GET /api/v1/articles?status=&category=&q=&page=&pageSize=&sort=
const ListQuery = z.object({
  status: z.enum(["draft", "published", "scheduled", "archived"]).optional(),
  category: z.string().optional(),
  q: z.string().optional(),
  page: z.coerce.number().int().min(1).default(1),
  pageSize: z.coerce.number().int().min(1).max(100).default(20),
  sort: z.enum(["newest", "oldest", "viewed"]).default("newest"),
});

export async function GET(req: NextRequest) {
  const ctx = await requireApiToken(req, ["post:read"]);
  if (ctx instanceof Response) return ctx;

  const url = new URL(req.url);
  const parsed = ListQuery.safeParse(Object.fromEntries(url.searchParams));
  if (!parsed.success)
    return apiError(400, "bad_query", "Query không hợp lệ.", parsed.error.flatten());
  const q = parsed.data;

  const where: Record<string, unknown> = {};
  if (q.status) where.status = q.status;
  if (q.category) where.category = { slug: q.category };
  if (q.q)
    where.OR = [
      { title: { contains: q.q, mode: "insensitive" } },
      { excerpt: { contains: q.q, mode: "insensitive" } },
      { content: { contains: q.q, mode: "insensitive" } },
    ];

  const orderBy =
    q.sort === "oldest"
      ? { publishedAt: "asc" as const }
      : q.sort === "viewed"
      ? [{ viewCount: "desc" as const }, { publishedAt: "desc" as const }]
      : { publishedAt: "desc" as const };

  const [items, total] = await Promise.all([
    prisma.article.findMany({
      where,
      orderBy,
      skip: (q.page - 1) * q.pageSize,
      take: q.pageSize,
      select: {
        id: true,
        slug: true,
        title: true,
        excerpt: true,
        status: true,
        publishedAt: true,
        coverImage: true,
        seoScore: true,
        viewCount: true,
        createdAt: true,
        updatedAt: true,
        category: { select: { slug: true, name: true } },
        author: { select: { id: true, name: true } },
      },
    }),
    prisma.article.count({ where }),
  ]);

  return apiOk({
    page: q.page,
    pageSize: q.pageSize,
    total,
    totalPages: Math.ceil(total / q.pageSize),
    items,
  });
}

// POST /api/v1/articles  — create
const CreateBody = z.object({
  title: z.string().min(1).max(200),
  slug: z.string().max(96).optional(),
  excerpt: z.string().max(500).optional(),
  content: z.string().min(1),
  coverImage: z.string().url().optional().nullable(),
  status: z.enum(["draft", "published", "scheduled"]).default("draft"),
  publishedAt: z.coerce.date().optional(),
  scheduledFor: z.coerce.date().optional(),
  metaTitle: z.string().max(120).optional(),
  metaDesc: z.string().max(300).optional(),
  metaKeywords: z.string().max(300).optional(),
  focusKeyword: z.string().max(80).optional(),
  ogImage: z.string().url().optional(),
  canonicalUrl: z.string().url().optional(),
  noIndex: z.boolean().optional(),
  categoryId: z.string().optional(),
  categorySlug: z.string().optional(),
  tags: z.array(z.string()).max(20).optional(),
});

export async function POST(req: NextRequest) {
  const required = ["post:write" as const];
  const ctx = await requireApiToken(req, required);
  if (ctx instanceof Response) return ctx;

  let body: unknown;
  try {
    body = await req.json();
  } catch {
    return apiError(400, "bad_json", "Body không phải JSON hợp lệ.");
  }

  const parsed = CreateBody.safeParse(body);
  if (!parsed.success)
    return apiError(400, "bad_body", "Body không hợp lệ.", parsed.error.flatten());

  const data = parsed.data;
  if (data.status === "published" && !ctx.scopes.includes("post:publish"))
    return apiError(
      403,
      "insufficient_scope",
      "Token cần scope post:publish để tạo bài đã đăng.",
    );

  try {
    const a = await createArticle({
      ...data,
      authorId: ctx.userId,
    });
    await ctx.audit({
      action: "article.create",
      target: a.id,
      meta: { slug: a.slug, status: a.status },
    });
    return apiOk(
      {
        id: a.id,
        slug: a.slug,
        status: a.status,
        seoScore: a.seoScore,
        url: `/bai-viet/${a.slug}`,
      },
      201,
    );
  } catch (err) {
    return apiError(500, "create_failed", String(err instanceof Error ? err.message : err));
  }
}
