/**
 * Server-side reads for editorial content (Blog, Learn) and CMS pages from the
 * FlatRender V2 API gateway.
 *
 * All three are backed by the content service's `Blog` entity, discriminated by
 * `kind` (Blog | Learn | Page). Articles (Blog/Learn) are listed + read by slug;
 * CMS pages (About, Privacy, …) are single rows fetched by their slug.
 *
 * Every function returns a safe fallback (empty array / null) when the gateway is
 * unset or unreachable, so the site still renders standalone.
 */

import { gatewayUrl } from "@/lib/api/gateway";

export type ArticleKind = "Blog" | "Learn" | "Page";

export interface Article {
  id: string;
  slug: string;
  title: string;
  shortDescription?: string;
  content: string;
  image?: string;
  cover?: string;
  authorDisplayName?: string;
  isPublished: boolean;
  publishDate?: string;
  viewCount: number;
  createdAt: string;
  updatedAt?: string;
  metaTitle?: string;
  metaDescription?: string;
  metaKeywords?: string;
}

// ── V2 content-service shapes (snake_case JSON) ───────────────────────────────

interface V2BlogSummary {
  id: string;
  slug: string;
  title: string;
  short_description?: string | null;
  image?: string | null;
  cover?: string | null;
  author_display_name?: string | null;
  is_published: boolean;
  publish_date?: string | null;
  view_count: number;
  created_at: string;
}

interface V2BlogDetail extends V2BlogSummary {
  content: string;
  meta_title?: string | null;
  meta_description?: string | null;
  meta_keywords?: string | null;
  updated_at?: string | null;
}

interface V2Paged<T> {
  items: T[];
  meta?: { page: number; page_size: number; total: number; total_pages: number };
}

function mapArticle(b: V2BlogSummary | V2BlogDetail): Article {
  const d = b as V2BlogDetail;
  return {
    id: b.id,
    slug: b.slug,
    title: b.title,
    shortDescription: b.short_description ?? undefined,
    content: d.content ?? "",
    image: b.image ?? undefined,
    cover: b.cover ?? undefined,
    authorDisplayName: b.author_display_name ?? undefined,
    isPublished: b.is_published,
    publishDate: b.publish_date ?? undefined,
    viewCount: b.view_count ?? 0,
    createdAt: b.created_at,
    updatedAt: d.updated_at ?? undefined,
    metaTitle: d.meta_title ?? undefined,
    metaDescription: d.meta_description ?? undefined,
    metaKeywords: d.meta_keywords ?? undefined,
  };
}

async function safeGet<T>(path: string, revalidate = 60): Promise<T | null> {
  try {
    const res = await fetch(gatewayUrl(path), {
      next: { revalidate },
      headers: { Accept: "application/json" },
    });
    if (!res.ok) return null;
    return (await res.json()) as T;
  } catch {
    return null;
  }
}

export interface ArticleListResult {
  items: Article[];
  total: number;
  page: number;
  pageSize: number;
}

/** Published articles of a given kind (Blog or Learn), newest first. */
export async function fetchArticles(
  kind: ArticleKind,
  opts?: { page?: number; pageSize?: number; search?: string },
): Promise<ArticleListResult> {
  const params = new URLSearchParams();
  params.set("kind", kind);
  params.set("isPublished", "true");
  if (opts?.page) params.set("page", String(opts.page));
  params.set("pageSize", String(opts?.pageSize ?? 24));
  if (opts?.search) params.set("search", opts.search);

  const data = await safeGet<V2Paged<V2BlogSummary>>(`/v1/blogs?${params.toString()}`);
  if (!data?.items) return { items: [], total: 0, page: 1, pageSize: opts?.pageSize ?? 24 };
  return {
    items: data.items.map(mapArticle),
    total: data.meta?.total ?? data.items.length,
    page: data.meta?.page ?? 1,
    pageSize: data.meta?.page_size ?? (opts?.pageSize ?? 24),
  };
}

/** A single article by slug (Blog or Learn). Returns null if not found. */
export async function fetchArticle(slug: string): Promise<Article | null> {
  const data = await safeGet<V2BlogDetail>(`/v1/blogs/${encodeURIComponent(slug)}`);
  return data ? mapArticle(data) : null;
}

/**
 * A CMS page (kind = Page) by its well-known slug, e.g. "about" / "privacy".
 * Pages are looked up by the same slug endpoint; returns null when unset so the
 * caller can fall back to built-in default copy.
 */
export async function fetchPage(slug: string): Promise<Article | null> {
  const data = await safeGet<V2BlogDetail>(`/v1/blogs/${encodeURIComponent(slug)}`, 300);
  return data ? mapArticle(data) : null;
}
