import React, { useState, useEffect, useMemo } from 'react';
import { format } from 'date-fns';
import {
  ColumnDef,
  ColumnFiltersState,
  ExpandedState,
  RowSelectionState,
  SortingState,
  VisibilityState,
  flexRender,
  getCoreRowModel,
  getExpandedRowModel,
  getFacetedRowModel,
  getFacetedUniqueValues,
  getFilteredRowModel,
  getSortedRowModel,
  useReactTable,
} from '@tanstack/react-table';
import { motion, AnimatePresence } from 'framer-motion';
import { IconBan, IconCheck, IconX, IconTrash } from '@tabler/icons-react';
import { useTranslation } from 'react-i18next';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table';
import { TableSkeleton } from '@/components/ui/table-skeleton';
import { PermissionGuard } from '@/components/permission-guard';
import { ServerSidePagination } from '@/components/server-side-pagination';
import { useModels } from '../context/models-context';
import { Model, ModelConnection } from '../data/schema';

const MotionTableRow = motion.create(TableRow);
const MotionExpandedRow = motion.create(TableRow);

interface ModelsTableProps {
  columns: ColumnDef<Model>[];
  data: Model[];
  loading?: boolean;
  pageInfo?: ModelConnection['pageInfo'];
  pageSize: number;
  totalCount?: number;
  nameFilter: string;
  sorting: SortingState;
  onSortingChange: (updater: SortingState | ((prev: SortingState) => SortingState)) => void;
  onNextPage: () => void;
  onPreviousPage: () => void;
  onPageSizeChange: (pageSize: number) => void;
  onNameFilterChange: (filter: string) => void;
  canWrite?: boolean;
}

export function ModelsTable({
  columns,
  data,
  loading,
  pageInfo,
  pageSize,
  totalCount,
  nameFilter,
  sorting,
  onSortingChange,
  onNextPage,
  onPreviousPage,
  onPageSizeChange,
  onNameFilterChange,
  canWrite = true,
}: ModelsTableProps) {
  const { t } = useTranslation();
  const { setSelectedModels, setResetRowSelection, setOpen } = useModels();
  const [rowSelection, setRowSelection] = useState<RowSelectionState>({});
  const [expanded, setExpanded] = useState<ExpandedState>({});
  const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({});
  const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);

  useEffect(() => {
    const newColumnFilters: ColumnFiltersState = [];
    if (nameFilter) {
      newColumnFilters.push({ id: 'name', value: nameFilter });
    }
    setColumnFilters(newColumnFilters);
  }, [nameFilter]);

  const handleColumnFiltersChange = (updater: ColumnFiltersState | ((prev: ColumnFiltersState) => ColumnFiltersState)) => {
    const newFilters = typeof updater === 'function' ? updater(columnFilters) : updater;
    setColumnFilters(newFilters);

    const nameFilterValue = newFilters.find((filter) => filter.id === 'name')?.value as string;
    const newNameFilter = nameFilterValue || '';

    if (newNameFilter !== nameFilter) {
      onNameFilterChange(newNameFilter);
    }
  };

  const table = useReactTable({
    data,
    columns,
    state: {
      sorting,
      columnVisibility,
      rowSelection,
      columnFilters,
      expanded,
    },
    enableRowSelection: true,
    getRowId: (row) => row.id,
    onRowSelectionChange: setRowSelection,
    onExpandedChange: setExpanded,
    onSortingChange,
    onColumnFiltersChange: handleColumnFiltersChange,
    onColumnVisibilityChange: setColumnVisibility,
    getCoreRowModel: getCoreRowModel(),
    getFilteredRowModel: getFilteredRowModel(),
    getSortedRowModel: getSortedRowModel(),
    getFacetedRowModel: getFacetedRowModel(),
    getFacetedUniqueValues: getFacetedUniqueValues(),
    getExpandedRowModel: getExpandedRowModel(),
    manualPagination: true,
    manualFiltering: true,
  });

  const filteredSelectedRows = useMemo(() => table.getFilteredSelectedRowModel().rows, [table, rowSelection, data]);

  const selectedCount = filteredSelectedRows.length;

  useEffect(() => {
    const resetFn = () => {
      setRowSelection({});
    };
    setResetRowSelection(resetFn);
  }, [setResetRowSelection]);

  useEffect(() => {
    const selected = filteredSelectedRows.map((row) => row.original as Model);
    setSelectedModels(selected);
  }, [filteredSelectedRows, setSelectedModels]);

  useEffect(() => {
    if (selectedCount === 0) {
      setSelectedModels([]);
    }
  }, [selectedCount, setSelectedModels]);

  useEffect(() => {
    if (Object.keys(rowSelection).length > 0 && data.length > 0) {
      const dataIds = new Set(data.map((model) => model.id));
      const selectedIds = Object.keys(rowSelection);
      const anySelectedIdMissing = selectedIds.some((id) => !dataIds.has(id));

      if (anySelectedIdMissing) {
        setRowSelection({});
      }
    }
  }, [data, rowSelection]);

  return (
    <div className='flex flex-1 flex-col overflow-hidden'>
      <div className='mb-4 flex items-center justify-between'>
        <div className='flex flex-1 items-center space-x-2'>
          <Input
            placeholder={t('models.filters.filterByName')}
            value={(table.getColumn('name')?.getFilterValue() as string) ?? ''}
            onChange={(event) => table.getColumn('name')?.setFilterValue(event.target.value)}
            className='h-8 w-[150px] lg:w-[250px]'
          />
        </div>
      </div>

      <div className='shadow-soft relative mt-4 flex-1 overflow-auto rounded-2xl border border-[var(--table-border)]'>
        <div className='min-w-max'>
        <Table data-testid='models-table' className='border-separate border-spacing-0 rounded-2xl bg-[var(--table-background)]'>
          <TableHeader className='sticky top-0 z-20 bg-[var(--table-header)] shadow-sm'>
            {table.getHeaderGroups().map((headerGroup) => (
              <TableRow key={headerGroup.id} className='group/row border-0'>
                {headerGroup.headers.map((header) => {
                  return (
                    <TableHead
                      key={header.id}
                      colSpan={header.colSpan}
                      className={`${header.column.columnDef.meta?.className ?? ''} text-muted-foreground border-0 text-xs font-semibold tracking-wider uppercase`}
                    >
                      {header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())}
                    </TableHead>
                  );
                })}
              </TableRow>
            ))}
          </TableHeader>
          <TableBody className='space-y-1 !bg-[var(--table-background)] p-2'>
            {loading ? (
              <TableSkeleton rows={pageSize} columns={columns.length} />
            ) : table.getRowModel().rows?.length ? (
              table.getRowModel().rows.map((row) => {
                const model = row.original;
                const modelCard = model.modelCard;
                return (
                  <React.Fragment key={row.id}>
                    <MotionTableRow
                      key={row.id}
                      data-state={row.getIsSelected() && 'selected'}
                      className='group/row table-row-hover rounded-xl border-0 !bg-[var(--table-background)] transition-all duration-200 ease-in-out'
                    >
                      {row.getVisibleCells().map((cell) => (
                        <TableCell key={cell.id} className={`${cell.column.columnDef.meta?.className ?? ''} border-0 bg-inherit px-4 py-3`}>
                          {flexRender(cell.column.columnDef.cell, cell.getContext())}
                        </TableCell>
                      ))}
                    </MotionTableRow>
                    <AnimatePresence>
                      {row.getIsExpanded() && (
                        <TableRow key={`${row.id}-expanded`} className='border-0'>
                          <TableCell colSpan={columns.length} className='p-0 border-0'>
                            <motion.div
                              initial={{ height: 0, opacity: 0 }}
                              animate={{ height: 'auto', opacity: 1 }}
                              exit={{ height: 0, opacity: 0 }}
                              transition={{ duration: 0.2, ease: 'easeInOut' }}
                              className='bg-muted/30 p-6 hover:bg-muted/50'
                            >
                              <div className='space-y-6'>
                            {/* Top Section: Basic Info (left) + Capabilities (right) */}
                            <div className='grid grid-cols-1 gap-6 md:grid-cols-2'>
                              {/* Basic Info */}
                              <div className='space-y-3'>
                                <h4 className='text-sm font-semibold'>{t('models.expandedRow.basic')}</h4>
                                <div className='space-y-2 text-sm'>
                                  <div className='flex justify-between'>
                                    <span className='text-muted-foreground'>{t('models.columns.modelId')}:</span>
                                    <span className='font-mono text-xs'>{model.modelID}</span>
                                  </div>
                                  <div className='flex items-center justify-between'>
                                    <span className='text-muted-foreground'>{t('models.columns.developer')}:</span>
                                    <Badge variant='outline'>{model.developer}</Badge>
                                  </div>
                                  <div className='flex items-center justify-between'>
                                    <span className='text-muted-foreground'>{t('models.columns.group')}:</span>
                                    <span>{model.group}</span>
                                  </div>
                                  <div className='flex justify-between'>
                                    <span className='text-muted-foreground'>{t('common.columns.createdAt')}:</span>
                                    <span>{format(model.createdAt, 'yyyy-MM-dd HH:mm')}</span>
                                  </div>
                                  <div className='flex justify-between'>
                                    <span className='text-muted-foreground'>{t('common.columns.updatedAt')}:</span>
                                    <span>{format(model.updatedAt, 'yyyy-MM-dd HH:mm')}</span>
                                  </div>
                                  {model.remark && (
                                    <div className='flex justify-between'>
                                      <span className='text-muted-foreground'>{t('models.columns.remark')}:</span>
                                      <span className='max-w-[200px] truncate text-right' title={model.remark}>
                                        {model.remark}
                                      </span>
                                    </div>
                                  )}
                                </div>
                              </div>

                              {/* Capabilities */}
                              <div className='space-y-3'>
                                <h4 className='text-sm font-semibold'>{t('models.expandedRow.capabilities')}</h4>
                                <div className='space-y-2 text-sm'>
                                  <div className='flex items-center justify-between'>
                                    <span className='text-muted-foreground'>{t('models.modelCard.toolCall')}:</span>
                                    <span>{modelCard?.toolCall ? <IconCheck className='h-4 w-4 text-green-600' /> : '-'}</span>
                                  </div>
                                  <div className='flex items-center justify-between'>
                                    <span className='text-muted-foreground'>{t('models.modelCard.vision')}:</span>
                                    <span>{modelCard?.vision ? <IconCheck className='h-4 w-4 text-green-600' /> : '-'}</span>
                                  </div>
                                  <div className='flex items-center justify-between'>
                                    <span className='text-muted-foreground'>{t('models.modelCard.temperature')}:</span>
                                    <span>{modelCard?.temperature ? <IconCheck className='h-4 w-4 text-green-600' /> : '-'}</span>
                                  </div>
                                  {/* Reasoning grouped */}
                                  <div className='space-y-1'>
                                    <span className='text-muted-foreground'>{t('models.modelCard.reasoning')}:</span>
                                    <div className='ml-4 space-y-1'>
                                      <div className='flex items-center justify-between'>
                                        <span className='text-muted-foreground text-xs'>{t('models.modelCard.reasoningSupported')}:</span>
                                        <span>
                                          {modelCard?.reasoning?.supported ? <IconCheck className='h-4 w-4 text-green-600' /> : '-'}
                                        </span>
                                      </div>
                                      <div className='flex items-center justify-between'>
                                        <span className='text-muted-foreground text-xs'>{t('models.modelCard.reasoningDefault')}:</span>
                                        <span>
                                          {modelCard?.reasoning?.default ? <IconCheck className='h-4 w-4 text-green-600' /> : '-'}
                                        </span>
                                      </div>
                                    </div>
                                  </div>
                                </div>
                              </div>
                            </div>

                            {/* Middle Section: Modalities + Limits (left) | Cost (right) */}
                            <div className='grid grid-cols-1 gap-6 border-t pt-4 md:grid-cols-2'>
                              {/* Left: Modalities + Limits */}
                              <div className='space-y-4'>
                                {/* Modalities */}
                                <div className='space-y-3'>
                                  <h4 className='text-sm font-semibold'>{t('models.modelCard.modalities')}</h4>
                                  <div className='space-y-2 text-sm'>
                                    <div className='flex items-start gap-2'>
                                      <span className='text-muted-foreground shrink-0'>{t('models.modelCard.input')}:</span>
                                      <div className='flex flex-wrap gap-1'>
                                        {modelCard?.modalities?.input?.length
                                          ? modelCard.modalities.input.map((m) => (
                                              <Badge key={m} variant='outline' className='text-xs'>
                                                {m}
                                              </Badge>
                                            ))
                                          : '-'}
                                      </div>
                                    </div>
                                    <div className='flex items-start gap-2'>
                                      <span className='text-muted-foreground shrink-0'>{t('models.modelCard.output')}:</span>
                                      <div className='flex flex-wrap gap-1'>
                                        {modelCard?.modalities?.output?.length
                                          ? modelCard.modalities.output.map((m) => (
                                              <Badge key={m} variant='outline' className='text-xs'>
                                                {m}
                                              </Badge>
                                            ))
                                          : '-'}
                                      </div>
                                    </div>
                                  </div>
                                </div>

                                {/* Limits */}
                                <div className='space-y-3'>
                                  <h4 className='text-sm font-semibold'>{t('models.modelCard.limit')}</h4>
                                  <div className='space-y-2 text-sm'>
                                    <div className='flex justify-between'>
                                      <span className='text-muted-foreground'>{t('models.modelCard.context')}:</span>
                                      <span className='font-mono text-xs'>{modelCard?.limit?.context?.toLocaleString() ?? '-'}</span>
                                    </div>
                                    <div className='flex justify-between'>
                                      <span className='text-muted-foreground'>{t('models.modelCard.output')}:</span>
                                      <span className='font-mono text-xs'>{modelCard?.limit?.output?.toLocaleString() ?? '-'}</span>
                                    </div>
                                  </div>
                                </div>
                              </div>

                              {/* Right: Cost */}
                              <div className='space-y-3'>
                                <h4 className='text-sm font-semibold'>{t('models.modelCard.cost')} ($/M)</h4>
                                <div className='space-y-2 text-sm'>
                                  <div className='flex justify-between'>
                                    <span className='text-muted-foreground'>{t('models.modelCard.input')}:</span>
                                    <span className='font-mono text-xs'>{modelCard?.cost?.input ?? '-'}</span>
                                  </div>
                                  <div className='flex justify-between'>
                                    <span className='text-muted-foreground'>{t('models.modelCard.output')}:</span>
                                    <span className='font-mono text-xs'>{modelCard?.cost?.output ?? '-'}</span>
                                  </div>
                                  {modelCard?.cost?.cacheRead !== undefined && (
                                    <div className='flex justify-between'>
                                      <span className='text-muted-foreground'>{t('models.modelCard.cacheRead')}:</span>
                                      <span className='font-mono text-xs'>{modelCard.cost.cacheRead}</span>
                                    </div>
                                  )}
                                  {modelCard?.cost?.cacheWrite !== undefined && (
                                    <div className='flex justify-between'>
                                      <span className='text-muted-foreground'>{t('models.modelCard.cacheWrite')}:</span>
                                      <span className='font-mono text-xs'>{modelCard.cost.cacheWrite}</span>
                                    </div>
                                  )}
                                </div>
                              </div>
                            </div>

                            {/* Bottom Section: Dates */}
                            <div className='border-t pt-4'>
                              <h4 className='mb-3 text-sm font-semibold'>{t('models.modelCard.dates')}</h4>
                              <div className='flex gap-6 text-sm'>
                                <div className='flex gap-2'>
                                  <span className='text-muted-foreground'>{t('models.modelCard.knowledge')}:</span>
                                  <span>{modelCard?.knowledge || '-'}</span>
                                </div>
                                <div className='flex gap-2'>
                                  <span className='text-muted-foreground'>{t('models.modelCard.releaseDate')}:</span>
                                  <span>{modelCard?.releaseDate || '-'}</span>
                                </div>
                                <div className='flex gap-2'>
                                  <span className='text-muted-foreground'>{t('models.modelCard.lastUpdated')}:</span>
                                  <span>{modelCard?.lastUpdated || '-'}</span>
                                </div>
                              </div>
                            </div>
                          </div>
                        </motion.div>
                    </TableCell>
                  </TableRow>
                    )}
                  </AnimatePresence>
                </React.Fragment>
                );
              })
            ) : (
              <TableRow className='!bg-[var(--table-background)]'>
                <TableCell colSpan={columns.length} className='h-24 !bg-[var(--table-background)] text-center'>
                  {t('common.noData')}
                </TableCell>
              </TableRow>
            )}
          </TableBody>
        </Table>
        </div>
      </div>

      <div className='mt-4 flex-shrink-0'>
        <ServerSidePagination
          pageInfo={pageInfo}
          pageSize={pageSize}
          dataLength={data.length}
          totalCount={totalCount}
          selectedRows={selectedCount}
          onNextPage={onNextPage}
          onPreviousPage={onPreviousPage}
          onPageSizeChange={onPageSizeChange}
        />
      </div>

      {selectedCount > 0 && canWrite && (
        <div className='fixed bottom-6 left-1/2 z-50 -translate-x-1/2'>
          <div className='flex items-center gap-2 rounded-lg border bg-[var(--table-background)] px-4 py-2 shadow-lg'>
            <div className='bg-border mx-2 h-6 w-px' />
            <Button variant='ghost' size='icon' className='h-8 w-8' onClick={() => setRowSelection({})}>
              <IconX className='h-4 w-4' />
            </Button>
            <div className='flex items-center gap-1.5 px-2'>
              <span className='bg-primary text-primary-foreground flex h-6 min-w-6 items-center justify-center rounded px-1.5 text-xs font-medium'>
                {selectedCount}
              </span>
              <span className='text-muted-foreground text-sm'>{t('common.selected')}</span>
            </div>
            <div className='bg-border mx-2 h-6 w-px' />
            <PermissionGuard requiredScope='write_channels'>
              <>
                <Button
                  variant='ghost'
                  size='icon'
                  className='h-8 w-8 text-green-600 hover:bg-green-100 hover:text-green-700'
                  onClick={() => setOpen('bulkEnable')}
                  title={t('common.buttons.enable')}
                >
                  <IconCheck className='h-4 w-4' />
                </Button>
                <Button
                  variant='ghost'
                  size='icon'
                  className='h-8 w-8 text-amber-600 hover:bg-amber-100 hover:text-amber-700'
                  onClick={() => setOpen('bulkDisable')}
                  title={t('common.buttons.disable')}
                >
                  <IconBan className='h-4 w-4' />
                </Button>
                <Button
                  variant='ghost'
                  size='icon'
                  className='text-destructive h-8 w-8 hover:bg-red-100 hover:text-red-700'
                  onClick={() => setOpen('delete')}
                  title={t('common.buttons.delete')}
                >
                  <IconTrash className='h-4 w-4' />
                </Button>
              </>
            </PermissionGuard>
          </div>
        </div>
      )}
    </div>
  );
}
