import "server-only";

import { cache } from "react";

import {
  cmsData,
  cmsPaths,
  dateOf,
  idOf,
  num,
  paginated,
  str,
  strOrNull,
  withFallback,
} from "@/lib/cms/api";
import type { EntityStatus } from "@/lib/cms/types";

export type CategoryListItem = {
  id: string;
  name: string;
  slug: string;
  description: string | null;
  status: EntityStatus;
  /** Articles in any status, drafts included. */
  blogCount: number;
  updatedAt: Date;
};

/** A category as offered in pickers, such as the blog editor. */
export type CategoryOption = {
  id: string;
  name: string;
  status: EntityStatus;
};

const statusOf = (row: unknown): EntityStatus =>
  str(row, "status") === "INACTIVE" ? "INACTIVE" : "ACTIVE";

function toListItem(row: unknown): CategoryListItem {
  return {
    id: idOf(row),
    name: str(row, "name"),
    slug: str(row, "slug"),
    description: strOrNull(row, "description"),
    status: statusOf(row),
    blogCount: num(row, "blogs_count", num(row, "blog_count")),
    updatedAt: dateOf(row, "updated_at"),
  };
}

/** `GET admin/categories?q=&status=&page=&pageSize=` */
export async function listCategories({
  query,
  status,
  page = 1,
  pageSize = 20,
}: {
  query?: string;
  status?: EntityStatus;
  page?: number;
  pageSize?: number;
}): Promise<{ items: CategoryListItem[]; total: number }> {
  const body = await cmsData<unknown>(cmsPaths.categories, {
    query: { q: query?.trim(), status, page, pageSize },
  });
  return paginated(body, toListItem);
}

/**
 * Every category, inactive ones included so an article can keep showing the
 * category it already has. Pickers should only offer active ones for new picks.
 * Empty until the CMS serves categories.
 */
export const getCategoryOptions = cache(async (): Promise<CategoryOption[]> =>
  withFallback(
    cmsData<unknown>(cmsPaths.categories, {
      query: { page: 1, pageSize: 500 },
    }).then(
      (body) =>
        paginated(body, (row) => ({
          id: idOf(row),
          name: str(row, "name"),
          status: statusOf(row),
        })).items,
    ),
    [],
  ),
);
