"use client";

import { useMemo, useState } from "react";
import {
  useReactTable,
  getCoreRowModel,
  getSortedRowModel,
  flexRender,
  createColumnHelper,
  type SortingState,
  type ColumnDef,
} from "@tanstack/react-table";
import { FaChevronRight, FaSort, FaSortUp, FaSortDown } from "react-icons/fa6";
import { FiCopy } from "react-icons/fi";
import { Tooltip } from "@nextui-org/react";
import toast from "react-hot-toast";
import { useRouter } from "next/navigation";
import { SlSpeech } from "react-icons/sl";

import {
  Participant,
  FieldKey,
  FieldConfig,
} from "@/types/participant-list/provisional-types";
import { isFieldVisible } from "@/components/pages/client/participant-list/common/utils";
import StatusBadge from "@/components/pages/client/participant-list/participants/partials/status-badge";
import { formatIncentives } from "@/components/pages/client/participant-list/participants/utils";
import { useClientPortalAuth } from "@/components/pages/client/participant-list/common/client-portal-auth-context";

type ParticipantTableProps = {
  participants: Participant[];
  page: number;
  pageSize: number;
  visibilityControls: FieldConfig[];
};

const columnHelper = createColumnHelper<Participant>();

function buildVisibleColumn(
  field: FieldConfig,
  visibilityControls: FieldConfig[],
): ColumnDef<Participant, unknown> | null {
  if (!isFieldVisible(field.key, visibilityControls)) return null;

  switch (field.key) {
    case "firstName":
      return columnHelper.accessor("firstName", {
        id: "firstName",
        header: "First name",
        cell: (info) => {
          const p = info.row.original;
          return (
            <span className="text-sm text-gray-900 dark:text-white">
              {p.firstName.split(" ")[0]}
            </span>
          );
        },
        enableSorting: true,
      }) as ColumnDef<Participant, unknown>;

    case "lastName":
      return columnHelper.accessor("lastName", {
        id: "lastName",
        header: "Last name",
        cell: (info) => (
          <span className="text-sm text-gray-900 dark:text-white">
            {info.getValue()}
          </span>
        ),
        enableSorting: true,
      }) as ColumnDef<Participant, unknown>;

    case "age":
      return columnHelper.accessor("age", {
        id: "age",
        header: "Age",
        cell: (info) => (
          <span className="text-sm text-gray-900 dark:text-white tabular-nums">
            {info.getValue()}
          </span>
        ),
        enableSorting: true,
      }) as ColumnDef<Participant, unknown>;

    case "phone":
      return columnHelper.accessor("phone", {
        id: "phone",
        header: "Phone",
        cell: (info) => (
          <span className="text-sm text-gray-600 dark:text-neutral-400">
            {info.getValue()}
          </span>
        ),
        enableSorting: false,
      }) as ColumnDef<Participant, unknown>;

    case "sessionLink":
      return columnHelper.accessor((row) => row.session.link, {
        id: "session",
        header: "Session",
        cell: (info) => {
          const { session } = info.row.original;
          const link = session.link;

          if (!link) {
            return (
              <span className="text-xs text-gray-400 dark:text-gray-300">
                {session.location ?? session.type}
              </span>
            );
          }

          const truncated = link.length > 20 ? `${link.slice(0, 20)}…` : link;

          return (
            <div className="flex items-center gap-1.5">
              <Tooltip content={link} size="sm">
                <span className="text-xs text-gray-600 dark:text-neutral-400 truncate max-w-[120px] cursor-default">
                  {truncated}
                </span>
              </Tooltip>
              <button
                aria-label="Copy session link"
                className="text-gray-400 dark:text-gray-300 hover:text-gray-700 dark:hover:text-neutral-200 transition-colors"
                type="button"
                onClick={() => {
                  navigator.clipboard.writeText(link);
                  toast.success("Session link copied to clipboard.");
                }}
              >
                <FiCopy className="size-3" />
              </button>
            </div>
          );
        },
        enableSorting: true,
      }) as ColumnDef<Participant, unknown>;

    default:
      return null;
  }
}

function SortIcon({ isSorted }: { isSorted: false | "asc" | "desc" }) {
  if (!isSorted) {
    return <FaSort className="size-2.5 text-gray-300 dark:text-neutral-600" />;
  }
  return isSorted === "asc" ? (
    <FaSortUp className="size-2.5 text-gray-500 dark:text-neutral-400" />
  ) : (
    <FaSortDown className="size-2.5 text-gray-500 dark:text-neutral-400" />
  );
}

function ParticipantTable({
  participants,
  page,
  pageSize,
  visibilityControls,
}: ParticipantTableProps) {
  const { routes } = useClientPortalAuth();
  const router = useRouter();
  const [sorting, setSorting] = useState<SortingState>([]);

  const columns = useMemo(() => {
    const cols: ColumnDef<Participant, unknown>[] = [];

    const COLUMN_ORDER: FieldKey[] = [
      "firstName",
      "lastName",
      "age",
      "phone",
      "sessionLink",
    ];

    if (isFieldVisible("id", visibilityControls))
      cols.push(
        columnHelper.accessor("id", {
          id: "participant",
          header: "Participant ID",
          cell: (info) => (
            <span className="text-xs text-gray-400 dark:text-gray-300 tabular-nums">
              ID: {info.getValue()}
            </span>
          ),
          enableSorting: true,
        }) as ColumnDef<Participant, unknown>,
      );

    for (const key of COLUMN_ORDER) {
      const col = buildVisibleColumn(
        { key, label: key, isVisible: true },
        visibilityControls,
      );
      if (col) cols.push(col);
    }

    cols.push(
      columnHelper.accessor((row) => row.incentives[0]?.amount ?? 0, {
        id: "incentive",
        header: "Incentive",
        cell: (info) => (
          <span className="text-sm text-gray-900 dark:text-white">
            {formatIncentives(info.row.original.incentives)}
          </span>
        ),
        enableSorting: true,
      }) as ColumnDef<Participant, unknown>,
    );

    cols.push(
      columnHelper.accessor("status", {
        id: "status",
        header: "Status",
        cell: (info) => <StatusBadge status={info.getValue()} />,
        enableSorting: true,
      }) as ColumnDef<Participant, unknown>,
    );

    cols.push(
      columnHelper.accessor("queries", {
        id: "queries",
        header: "Queries",
        cell: (info) => {
          const count = info.getValue() as number;
          return count > 0 ? (
            <span className="text-xs font-medium text-gray-600 dark:text-neutral-400">
              <SlSpeech className="size-3 inline" /> {count} open
            </span>
          ) : (
            <span className="text-gray-300 dark:text-neutral-600">&mdash;</span>
          );
        },
        enableSorting: true,
      }) as ColumnDef<Participant, unknown>,
    );

    cols.push(
      columnHelper.display({
        id: "actions",
        header: "",
        cell: (info) => (
          <button
            className="inline-flex items-center gap-1 text-xs font-medium text-gray-500 dark:text-neutral-400 hover:text-gray-900 dark:hover:text-white transition-colors"
            type="button"
            onClick={() =>
              router.push(
                `${routes.participants}/${encodeURIComponent(info.row.original.reference)}`,
              )
            }
          >
            View
            <FaChevronRight className="size-2" />
          </button>
        ),
      }),
    );

    return cols;
  }, [router, routes.participants, visibilityControls]);

  const table = useReactTable({
    data: participants,
    columns,
    getRowId: (participant) => participant.reference,
    state: { sorting },
    onSortingChange: setSorting,
    getCoreRowModel: getCoreRowModel(),
    getSortedRowModel: getSortedRowModel(),
  });

  return (
    <div className="overflow-x-auto rounded-xl border border-gray-200 dark:border-neutral-700 bg-white dark:bg-neutral-800">
      <table className="w-full text-left">
        <thead>
          {table.getHeaderGroups().map((headerGroup) => (
            <tr
              key={headerGroup.id}
              className="border-b border-gray-100 dark:border-neutral-700"
            >
              {headerGroup.headers.map((header) => (
                <th
                  key={header.id}
                  className="px-4 py-3 text-[11px] uppercase tracking-wider font-semibold text-gray-400 dark:text-gray-300 whitespace-nowrap"
                  style={{ width: header.id === "actions" ? 60 : undefined }}
                >
                  {header.isPlaceholder ? null : header.column.getCanSort() ? (
                    <button
                      className="inline-flex items-center gap-1.5 uppercase hover:text-gray-600 dark:hover:text-neutral-300 transition-colors"
                      type="button"
                      onClick={header.column.getToggleSortingHandler()}
                    >
                      {flexRender(
                        header.column.columnDef.header,
                        header.getContext(),
                      )}
                      <SortIcon isSorted={header.column.getIsSorted()} />
                    </button>
                  ) : (
                    flexRender(
                      header.column.columnDef.header,
                      header.getContext(),
                    )
                  )}
                </th>
              ))}
            </tr>
          ))}
        </thead>
        <tbody>
          {table
            .getSortedRowModel()
            .rows.slice((page - 1) * pageSize, page * pageSize)
            .map((row) => (
              <tr
                key={row.id}
                className="border-b border-gray-50 dark:border-neutral-700/50 last:border-b-0 hover:bg-gray-50/50 dark:hover:bg-neutral-700/30 transition-colors"
              >
                {row.getVisibleCells().map((cell) => (
                  <td key={cell.id} className="px-4 py-3">
                    {flexRender(cell.column.columnDef.cell, cell.getContext())}
                  </td>
                ))}
              </tr>
            ))}
        </tbody>
      </table>
    </div>
  );
}

export default ParticipantTable;
