import { getModules, getSectors, getT } from "@/lib/content";
import type { Locale } from "@/lib/locales";
import { MODULES, type SectorId } from "@/lib/routes";
import type { PublicClient } from "@/lib/schemas";

import { RecordTable, type Column, type Row } from "./RecordTable";

/**
 * The references table.
 *
 * Blueprint 02 and 17 rule 4: a reference is named only with written
 * permission. The loader has already stripped the names, so this component
 * never holds one it may not print.
 *
 * It has two shapes, and picks between them from the data:
 *
 *  · Once any reference may be named, it is the Blueprint's row-per-reference
 *    table — business, sector, town, modules.
 *  · Until then, printing one row per reference would be fourteen rows of the
 *    same four sector names with empty cells beside them, which reads as a
 *    broken table rather than as discretion. So it summarises by sector
 *    instead, carrying the towns and modules that are actually evidenced.
 *
 * Neither shape states a number of clients: the twenty references are what
 * public sources happen to show, not Sulsys's client base, and a count would
 * read as the latter.
 */
export function ReferenceTable({
  locale,
  clients,
  limit,
}: {
  locale: Locale;
  clients: PublicClient[];
  limit?: number;
}) {
  const t = getT(locale);
  const sectors = getSectors(locale);
  const modules = getModules(locale);

  const sectorName = (id: string) => sectors.find((sector) => sector.id === id)?.name ?? id;

  const moduleLabel = (id: string) => {
    const meta = MODULES.find((module) => module.id === id);
    const content = modules.find((module) => module.id === id);
    if (!meta) return id;
    return content ? `${meta.code} ${content.name}` : `${meta.code} ${meta.brandName}`;
  };

  if (clients.length === 0) {
    return <p>{t("clients.empty")}</p>;
  }

  const anyNamed = clients.some((client) => client.name !== null);
  const order: SectorId[] = sectors.map((sector) => sector.id as SectorId);

  /* ---- Shape 1: named references exist ---------------------------------- */

  if (anyNamed) {
    const anyTown = clients.some((client) => client.town !== null);
    const anyModules = clients.some((client) => client.modules.length > 0);

    const sorted = [...clients].sort((a, b) => {
      const bySector = order.indexOf(a.sector as SectorId) - order.indexOf(b.sector as SectorId);
      if (bySector !== 0) return bySector;
      return (a.name ?? "").localeCompare(b.name ?? "", locale);
    });

    const visible = limit ? sorted.slice(0, limit) : sorted;

    const columns: Column[] = [
      { key: "nr", label: t("table.nr"), code: true },
      { key: "business", label: t("table.business"), subject: true },
      { key: "sector", label: t("table.sector") },
      ...(anyTown ? [{ key: "town", label: t("table.town") }] : []),
      ...(anyModules ? [{ key: "modules", label: t("table.modules") }] : []),
    ];

    const rows: Row[] = visible.map((client, index) => ({
      id: client.id,
      cells: [
        String(index + 1).padStart(2, "0"),
        client.name ?? "",
        sectorName(client.sector),
        ...(anyTown ? [client.town ?? ""] : []),
        ...(anyModules ? [client.modules.map(moduleLabel).join(" · ")] : []),
      ],
    }));

    return <RecordTable columns={columns} rows={rows} caption={t("clients.title")} />;
  }

  /* ---- Shape 2: nothing may be named yet -------------------------------- */

  const grouped = order
    .map((sectorId) => {
      const inSector = clients.filter((client) => client.sector === sectorId);
      if (inSector.length === 0) return null;

      const towns = [...new Set(inSector.map((c) => c.town).filter((t): t is string => !!t))];
      const used = [...new Set(inSector.flatMap((c) => c.modules))];

      return {
        id: sectorId,
        sector: sectorName(sectorId),
        towns: towns.join(", "),
        modules: used.map(moduleLabel).join(" · "),
      };
    })
    .filter((row): row is NonNullable<typeof row> => row !== null);

  const anyTown = grouped.some((row) => row.towns.length > 0);
  const anyModules = grouped.some((row) => row.modules.length > 0);

  const columns: Column[] = [
    { key: "nr", label: t("table.nr"), code: true },
    { key: "sector", label: t("table.sector"), subject: true },
    ...(anyTown ? [{ key: "towns", label: t("table.towns") }] : []),
    ...(anyModules ? [{ key: "modules", label: t("table.modules") }] : []),
  ];

  const rows: Row[] = grouped.map((row, index) => ({
    id: row.id,
    cells: [
      String(index + 1).padStart(2, "0"),
      row.sector,
      ...(anyTown ? [row.towns] : []),
      ...(anyModules ? [row.modules] : []),
    ],
  }));

  return <RecordTable columns={columns} rows={rows} caption={t("clients.title")} />;
}
