import type { ColumnDef, ExpandedState, Header, SortingState } from '@tanstack/react-table';
import {
  flexRender,
  getCoreRowModel,
  getExpandedRowModel,
  getPaginationRowModel,
  getSortedRowModel,
  useReactTable,
} from '@tanstack/react-table';
import { ArrowDownIcon, ArrowUpIcon, ChevronLeftIcon, ChevronRightIcon } from '@trail-ui/icons';
import { Avatar } from '../avatar';
import { AvatarGroup } from '../avatar';
import { Checkbox } from '../checkbox';
import { Lozenge } from '../lozenge';
import { Button } from '../button';
import { clsx } from '@trail-ui/shared-utils';
import { ReactNode, useState } from 'react';
import { commonColors } from '@trail-ui/theme';
// import { Link } from 'react-router-dom';

type ObjectFitProps = 'contain' | 'cover' | 'fill' | 'none' | 'scale-down';

interface Column {
  id: string;
  name: string;
  accessor: string;
  type:
    | 'id'
    | 'text'
    | 'date'
    | 'number'
    | 'status'
    | 'percentage'
    | 'usersList'
    | 'image'
    | 'link'
    | 'username';
  width?: number;
  objectFit?: ObjectFitProps;
  linkTo: string;
}

export default function TanstackGroupTable({
  columns,
  data,
  tableData,
  checkBoxSelectedName,
  tableName,
}: {
  columns: Column[];
  data: any[];
  tableData?: number;
  checkBoxSelectedName?: string;
  tableName?: string;
}) {
  const tableColumns: ColumnDef<object>[] = columns.map((column: Column) => {
    return {
      id: column.id,
      size: column.width,
      header: () => {
        switch (column.type) {
          case 'id':
            return (
              <div
                // aria-checked={
                //   Object.keys(rowSelection).length === data.length
                //     ? 'true'
                //     : Object.keys(rowSelection).length > 0 &&
                //         Object.keys(rowSelection).length < data.length
                //       ? 'mixed'
                //       : 'false'
                // }
                className="text-center"
              >
                <Checkbox
                  aria-label={`Select All ${tableName}`}
                  classNames={{ control: 'mr-0 text-center' }}
                  {...{
                    isSelected: Object.keys(rowSelection).length === data.length,
                    isIndeterminate:
                      Object.keys(rowSelection).length > 0 &&
                      Object.keys(rowSelection).length < data.length,
                    checked: Object.keys(rowSelection).length === data.length,
                    onChange: () => {
                      const allSelected = Object.keys(rowSelection).length === data.length;
                      const newSelection = allSelected
                        ? {}
                        : data.reduce((acc, row) => {
                            acc[row.id] = true;
                            return acc;
                          }, {});
                      setRowSelection(newSelection);
                    },
                  }}
                />
              </div>
            );
          default:
            return column.name;
        }
      },
      accessorKey: column.accessor,
      cell: ({ cell }) => {
        switch (column.type) {
          case 'id':
            return (
              <>
                <Checkbox
                  aria-labelledby={`Select ${(cell.row.original as Record<string, unknown>)[checkBoxSelectedName ?? '']}`}
                  classNames={{ control: 'mr-0 text-center' }}
                  {...{
                    isSelected: cell.row.getIsSelected(),
                    onChange: () => cell.row.toggleSelected(),
                  }}
                />
              </>
            );
          case 'text':
            return cell.getValue() as string;
          case 'date':
            return new Date(cell.getValue() as string).toLocaleDateString();
          case 'number':
            return cell.getValue() as number;
          case 'status':
            return (
              <Lozenge
                size="sm"
                variant="light"
                value={cell.getValue() as string}
                color={
                  cell.getValue() === 'Active'
                    ? 'green'
                    : cell.getValue() === 'Inactive'
                      ? 'red'
                      : 'yellow'
                }
              />
            );
          case 'percentage':
            return (
              <Lozenge
                size="sm"
                variant="light"
                value={`${cell.getValue() as number}`}
                color={
                  (cell.getValue() as number) > 0
                    ? 'green'
                    : (cell.getValue() as number) < 0
                      ? 'red'
                      : 'yellow'
                }
              />
            );
          case 'image':
            return (
              <figure className="min-w-36">
                <img
                  className="h-10"
                  src={cell.getValue() as string}
                  style={{
                    objectFit: column.objectFit ? column.objectFit : 'cover',
                    width: column.objectFit === 'contain' ? 'max-content' : '100%',
                  }}
                  alt=""
                />
              </figure>
            );
          //   case 'link':
          //     return (
          //       <Link
          //         className="text-purple-600 underline transition-all hover:underline"
          //         to={column.linkTo}
          //       >
          //         {cell.getValue() as string}
          //       </Link>
          //     );
          case 'username':
            return (
              <p className="flex items-center gap-1 text-sm text-neutral-900">
                <Avatar
                  id={cell.getValue() as string}
                  size="md"
                  is="span"
                  name={cell.getValue() as string}
                  getInitials={(name: string) => name.toUpperCase().slice(0, 2)}
                  showFallback
                  color={
                    ['green', 'red', 'yellow', 'default', 'purple', 'blue'][
                      Math.floor(Math.random() * 6)
                    ] as 'green' | 'red' | 'yellow' | 'default' | 'purple' | 'blue' | undefined
                  }
                />
                {/* <span className="text-neutral-900 text-sm">
                    {cell.getValue() as string}
                  </span> */}
              </p>
            );
          case 'usersList':
            return (
              <AvatarGroup size="md" max={2}>
                {((cell.getValue() as any[]) || []).map((user: any) => (
                  <Avatar
                    size="md"
                    key={user.id}
                    is="span"
                    src={user.avatar}
                    name={user.name}
                    getInitials={(name: string) => name.toUpperCase().slice(0, 2)}
                    showFallback
                    color={
                      ['green', 'red', 'yellow', 'default', 'purple', 'blue'][
                        Math.floor(Math.random() * 6)
                      ] as 'green' | 'red' | 'yellow' | 'default' | 'purple' | 'blue' | undefined
                    }
                  />
                ))}
              </AvatarGroup>
            );
          default:
            return cell.getValue() as ReactNode;
        }
      },
    };
  });

  const [sorting, setSorting] = useState<SortingState>([]);
  const [rowSelection, setRowSelection] = useState({});
  const [expanded, setExpanded] = useState<ExpandedState>({});

  const table = useReactTable<(typeof data)[number]>({
    enableRowSelection: true,
    columns: tableColumns as ColumnDef<(typeof data)[number], typeof data>[],
    data: data,
    // sortDescFirst: true,
    // enableSortingRemoval: false,
    defaultColumn: {
      size: 100,
    },

    getCoreRowModel: getCoreRowModel(),
    getSortedRowModel: getSortedRowModel(),
    getExpandedRowModel: getExpandedRowModel(),
    onRowSelectionChange: setRowSelection,
    onSortingChange: setSorting,
    onExpandedChange: setExpanded,
    getPaginationRowModel: getPaginationRowModel(),
    state: {
      sorting,
      rowSelection,
      expanded,
    },
    initialState: {
      pagination: {
        pageSize: tableData ? tableData : 10,
        pageIndex: 0,
      },
    },
  });

  const currentPage = table.getState().pagination.pageIndex + 1;
  const pageCount = table.getPageCount();

  const pageNumbers = [];
  const maxButtonsToShow = 5;

  if (pageCount <= maxButtonsToShow) {
    for (let i = 1; i <= pageCount; i++) {
      pageNumbers.push(i);
    }
  } else {
    let startPage, endPage;
    const middleButtonsToShow = maxButtonsToShow - 2;
    const halfMiddleButtonsToShow = Math.floor(middleButtonsToShow / 2);

    if (currentPage <= halfMiddleButtonsToShow + 1) {
      startPage = 2;
      endPage = middleButtonsToShow + 1;
    } else if (currentPage + halfMiddleButtonsToShow >= pageCount) {
      startPage = pageCount - middleButtonsToShow;
      endPage = pageCount - 1;
    } else {
      startPage = currentPage - halfMiddleButtonsToShow;
      endPage = currentPage + halfMiddleButtonsToShow;
    }

    pageNumbers.push(1);
    if (startPage > 2) {
      pageNumbers.push('...');
    }

    for (let i = startPage; i <= endPage; i++) {
      pageNumbers.push(i);
    }

    if (endPage < pageCount - 1) {
      pageNumbers.push('...');
    }
    pageNumbers.push(pageCount);
  }

  // const [currentSort, setCurrentSort] = useState<string>('issueName')

  function toggleSort(header: Header<any, any>) {
    const sortingHandler = header.column.getToggleSortingHandler();
    if (sortingHandler) {
      sortingHandler({ persist: () => {} }); // Call the returned function with a mock event
    }
    // setCurrentSort(header.id)
  }

  return (
    <>
      <div className="rounded">
        <div className="h-full overflow-auto rounded border border-neutral-200">
          <div className="grid-container">
            <table className="w-full table-auto overflow-x-auto bg-white">
              <thead className="border-b border-b-neutral-200 text-neutral-600">
                {table.getHeaderGroups().map((headerGroup) => (
                  <tr key={headerGroup.id}>
                    {headerGroup.headers.map((header) => (
                      <th
                        key={header.id}
                        scope="col"
                        colSpan={header.colSpan}
                        className={`h-10 min-h-10 border-r border-r-neutral-200 bg-neutral-100 p-2 text-sm font-semibold text-neutral-900 first:w-10 first:text-center last:border-r-0`}
                      >
                        {header.isPlaceholder &&
                        header.column.getIndex() === 0 ? null : header.id == 'id' ? (
                          <span>
                            {flexRender(header.column.columnDef.header, header.getContext())}
                          </span>
                        ) : (
                          <Button
                            appearance="transparent"
                            className={clsx(
                              header.column.getCanSort() ? 'cursor-pointer select-none' : '',
                              `'justify-start' w-full items-center px-0 text-sm font-semibold text-neutral-900`,
                            )}
                            onPress={() => toggleSort(header)}
                            onKeyDown={(event) => {
                              if (event.key === 'Enter' || event.key === ' ') {
                                header.column.getToggleSortingHandler();
                              }
                            }}
                          >
                            <span className={`'justify-between' flex w-full items-center gap-4`}>
                              {flexRender(header.column.columnDef.header, header.getContext())}
                              {header.column.getCanSort() && header.id !== 'id' ? (
                                // currentSort === header.id
                                <span className="sort-icon">
                                  {{
                                    asc: (
                                      <ArrowUpIcon
                                        color={commonColors.neutral[800]}
                                        width={16}
                                        height={16}
                                      />
                                    ),
                                    desc: (
                                      <ArrowDownIcon
                                        color={commonColors.neutral[800]}
                                        width={16}
                                        height={16}
                                      />
                                    ),
                                  }[header.column.getIsSorted() as string] ?? null}
                                </span>
                              ) : null}
                            </span>
                          </Button>
                        )}
                      </th>
                    ))}
                  </tr>
                ))}
              </thead>
              <tbody className="text-neutral-900">
                {table.getRowModel().rows.map((row) => (
                  <>
                    {!row.getIsExpanded() && (
                      <tr key={`${row.id}-expanded`} className="border-b border-b-neutral-200">
                        <td className="h-10 border-b border-l border-b-neutral-200 border-l-neutral-200 px-2 py-2 text-sm font-normal text-neutral-900 first:w-10 first:border-l-0 first:text-center">
                          <Checkbox
                            aria-label="Select textual description issue"
                            classNames={{ control: 'm-0' }}
                            {...{
                              isSelected: row.getIsSelected(),
                              onChange: () => row.toggleSelected(),
                            }}
                          />
                        </td>
                        <td
                          className="border-b border-l border-b-neutral-200 border-l-neutral-200 p-2 px-2 py-2 text-sm font-normal text-neutral-900 first:w-10 first:border-l-0 first:text-center"
                          colSpan={tableColumns.length}
                        >
                          {' '}
                          {/* Adjust colSpan here */}
                          <span className="text-sm font-medium text-neutral-900">
                            1. An incomplete textual description &quot;PF Harris&quot; is provided
                            for the logo image link instead of &quot;PF Harris logo&quot; in the
                            header section (4 instances)
                          </span>
                        </td>
                      </tr>
                    )}
                    <tr key={row.id}>
                      {row.getVisibleCells().map((cell) => (
                        <td
                          key={cell.id}
                          className="border-b border-l border-b-neutral-200 border-l-neutral-200 px-2 py-2 text-sm font-normal text-neutral-900 first:w-10 first:border-l-0 first:text-center"
                        >
                          {flexRender(cell.column.columnDef.cell, cell.getContext())}
                        </td>
                      ))}
                    </tr>
                    <tr key={row.id + 1}>
                      {row.getVisibleCells().map((cell) => (
                        <td
                          key={cell.id + 1}
                          className="first:text-centerpy-2 border-b border-l border-b-neutral-200 border-l-neutral-200 px-2 py-2 text-sm font-normal text-neutral-900 first:w-10 first:border-l-0 first:text-center"
                        >
                          {flexRender(cell.column.columnDef.cell, cell.getContext())}
                        </td>
                      ))}
                    </tr>
                    <tr key={row.id + 2}>
                      {row.getVisibleCells().map((cell) => (
                        <td
                          key={cell.id + 2}
                          className="border-b border-l border-b-neutral-200 border-l-neutral-200 px-2 py-2 text-sm font-normal text-neutral-900 first:w-10 first:border-l-0 first:text-center"
                        >
                          {flexRender(cell.column.columnDef.cell, cell.getContext())}
                        </td>
                      ))}
                    </tr>
                    <tr key={row.id + 3}>
                      {row.getVisibleCells().map((cell) => (
                        <td
                          key={cell.id + 3}
                          className="first:text-centerpy-2 border-b border-l border-b-neutral-200 border-l-neutral-200 px-2 py-2 text-sm font-normal text-neutral-900 first:w-10 first:border-l-0 first:text-center"
                        >
                          {flexRender(cell.column.columnDef.cell, cell.getContext())}
                        </td>
                      ))}
                    </tr>
                  </>
                ))}
              </tbody>
            </table>
          </div>
        </div>

        <div className="mt-2 flex items-center justify-between space-x-2 p-2">
          <div>
            <p className="text-sm text-neutral-600">
              Showing {table.getRowModel().rows.length} out of {data.length} results
            </p>
          </div>
          <nav aria-label="Pagination" className="flex justify-end">
            <ul className="justtify-end flex">
              <li>
                <Button
                  aria-label="Previous page"
                  appearance="transparent"
                  isDisabled={!table.getCanPreviousPage()}
                  onPress={() => table.previousPage()}
                >
                  <ChevronLeftIcon
                    color={`${currentPage === 1 ? '#B0ACBB' : '#302E38'}`}
                    width={24}
                    height={24}
                  />
                </Button>
              </li>
              {pageNumbers.map((pageNumber: any, index: number) => (
                <li key={index}>
                  {pageNumber === '...' ? (
                    <span>...</span>
                  ) : (
                    <button
                      {...(pageNumber === currentPage ? { 'aria-current': 'page' } : {})}
                      aria-current={pageNumber === currentPage ? 'page' : undefined}
                      // appearance="transparent"
                      onClick={() => {
                        if (pageNumber !== '...') {
                          table.setPageIndex(pageNumber - 1);
                          // e.target.setAttribute('data-focused', 'true')
                        }
                      }}
                      className={`px-3 py-1 text-sm font-normal text-neutral-800 ${
                        pageNumber === currentPage ? 'rounded-sm bg-purple-100' : 'bg-white'
                      } ${pageNumber !== '...' ? 'underline' : ''}`}
                    >
                      {pageNumber}
                    </button>
                  )}
                </li>
              ))}
              <li>
                <Button
                  appearance="transparent"
                  isDisabled={!table.getCanNextPage()}
                  onPress={() => table.nextPage()}
                  aria-label="Next page"
                >
                  <ChevronRightIcon
                    color={!table.getCanNextPage() ? '#B0ACBB' : '#302E38'}
                    width={24}
                    height={24}
                  />
                </Button>
              </li>
            </ul>
          </nav>
        </div>
      </div>
    </>
  );
}
