import type { Dispatch, ReactNode, SetStateAction } from "react";
import { Badge, Checkbox, Text, Tooltip } from "@mantine/core";
import type { TFunction } from "i18next";
import {
  APPLICANT_NAME_TYPE_KEYS,
  STATUS_COLORS,
  STATUS_LABELS,
  applicantOrCompanyName,
  localized,
  type LicenseApplication,
  type QueueFilter,
} from "@ema-platform/api";
import type { AdvancedColumn } from "@ema-platform/ui";
import { dateDisplayer } from "@ema-platform/shared";
import { computeSla } from "../../sla";

export function licenseQueueColumns(
  t: TFunction,
  locale: string,
  opts: {
    typeCode: string | undefined;
    items: LicenseApplication[];
    selected: string[];
    setSelected: Dispatch<SetStateAction<string[]>>;
    allSelected: boolean;
    sortableHeader: (
      label: string,
      field: NonNullable<QueueFilter["sortBy"]>,
    ) => ReactNode;
  },
): AdvancedColumn<LicenseApplication>[] {
  const { typeCode, items, selected, setSelected, allSelected, sortableHeader } =
    opts;
  return [
    {
      header: (
        <Checkbox
          aria-label={t("queue.selectAll", "Select all")}
          checked={allSelected}
          indeterminate={selected.length > 0 && !allSelected}
          onChange={() =>
            setSelected(allSelected ? [] : items.map((a) => a.id))
          }
        />
      ),
      size: 40,
      cell: ({ row }) => (
        <Checkbox
          aria-label={t("queue.selectRow", {
            number: row.original.applicationNumber,
            defaultValue: "Select {{number}}",
          })}
          checked={selected.includes(row.original.id)}
          onChange={(e) => {
            const checked = e.currentTarget.checked;
            setSelected((prev) =>
              checked
                ? [...prev, row.original.id]
                : prev.filter((id) => id !== row.original.id),
            );
          }}
        />
      ),
    },
    {
      header: sortableHeader(t("queue.number", "App #"), "applicationNumber"),
      label: t("queue.number", "App #"),
      cell: ({ row }) => (
        <Text size="sm" fw={500}>
          {row.original.applicationNumber}
        </Text>
      ),
    },
    {
      header: sortableHeader(
        typeCode && APPLICANT_NAME_TYPE_KEYS.includes(typeCode)
          ? t("queue.applicant", "Applicant")
          : t("queue.company", "Company"),
        "companyName",
      ),
      label: t("queue.company", "Company"),
      cell: ({ row }) => (
        <Text size="sm">{applicantOrCompanyName(row.original) ?? "—"}</Text>
      ),
    },
    {
      header: t("queue.tin", "TIN"),
      cell: ({ row }) => (
        <Text size="sm" c="dimmed">
          {row.original.tinNumber ?? "—"}
        </Text>
      ),
    },
    {
      header: t("queue.typeCol", "Type"),
      cell: ({ row }) => (
        <Text size="sm">
          {localized(row.original.licenseType?.name, locale) || "—"}
        </Text>
      ),
    },
    {
      header: sortableHeader(t("queue.statusCol", "Status"), "status"),
      label: t("queue.statusCol", "Status"),
      cell: ({ row }) => (
        <Badge color={STATUS_COLORS[row.original.status]} variant="light">
          {t(
            `queue.statusValues.${row.original.status}`,
            STATUS_LABELS[row.original.status],
          )}
        </Badge>
      ),
    },
    {
      header: sortableHeader(
        t("queue.submitted", "Submitted"),
        "submittedAt",
      ),
      label: t("queue.submitted", "Submitted"),
      cell: ({ row }) => (
        <Text size="sm" c="dimmed">
          {dateDisplayer(row.original.submittedAt, locale)}
        </Text>
      ),
    },
    {
      header: t("queue.sla", "Age / SLA"),
      cell: ({ row }) => {
        // eslint-disable-next-line @typescript-eslint/no-explicit-any -- i18next's overloaded TFunction type doesn't structurally match a plain callback signature
        const sla = computeSla(row.original, undefined, locale, (key, options) => t(key, options as any) as string);
        return (
          // Colour is never the only signal — the label says the same thing.
          <Tooltip label={sla.tooltip} withArrow>
            <Badge color={sla.color} variant="light" size="sm">
              {sla.label}
            </Badge>
          </Tooltip>
        );
      },
    },
  ];
}
