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 AuthorListItem = {
  id: string;
  name: string;
  slug: string;
  role: string | null;
  bio: string | null;
  /** Root-relative ("/uploads/…") or absolute. */
  profileImage: string | null;
  status: EntityStatus;
  /** Articles in any status, drafts included. */
  blogCount: number;
  updatedAt: Date;
};

/** An author as offered in pickers, such as the blog editor. */
export type AuthorOption = {
  id: string;
  name: string;
  role: string | null;
  profileImage: string | null;
  status: EntityStatus;
};

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

function toOption(row: unknown): AuthorOption {
  return {
    id: idOf(row),
    name: str(row, "name"),
    role: strOrNull(row, "role"),
    profileImage: strOrNull(row, "profile_image"),
    status: statusOf(row),
  };
}

function toListItem(row: unknown): AuthorListItem {
  return {
    ...toOption(row),
    slug: str(row, "slug"),
    bio: strOrNull(row, "bio"),
    blogCount: num(row, "blogs_count", num(row, "blog_count")),
    updatedAt: dateOf(row, "updated_at"),
  };
}

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

/**
 * Every author, inactive ones included so an article can keep showing the
 * author it already has. Pickers should only offer active ones for new picks.
 * Empty until the CMS serves authors.
 */
export const getAuthorOptions = cache(async (): Promise<AuthorOption[]> =>
  withFallback(
    cmsData<unknown>(cmsPaths.authors, {
      query: { page: 1, pageSize: 500 },
    }).then((body) => paginated(body, toOption).items),
    [],
  ),
);
