import { useMemo, useState } from 'react';
import {
  useReactTable,
  getCoreRowModel,
  flexRender,
} from '@tanstack/react-table';
import {
  DndContext,
  closestCenter,
  KeyboardSensor,
  PointerSensor,
  useSensor,
  useSensors,
  DragOverlay,
} from '@dnd-kit/core';
import type { DragEndEvent, DragStartEvent } from '@dnd-kit/core';
import {
  SortableContext,
  sortableKeyboardCoordinates,
  verticalListSortingStrategy,
} from '@dnd-kit/sortable';
import { restrictToVerticalAxis } from '@dnd-kit/modifiers';
import {
  Table,
  TableBody,
  TableCell,
  TableContainer,
  TableHead,
  TableRow,
  Paper,
  TableSortLabel,
  Skeleton,
  Box,
  Typography,
  TablePagination,
} from '@mui/material';
import { Inbox } from '@mui/icons-material';
import {
  useIdeasQuery,
  useDeleteIdea,
  useReorderIdeas,
} from '../../hooks/useIdeas';
import { useIdeasStore } from '../../store/ideas';
import { createColumns } from './columns';
import { DraggableRow } from './DraggableRow';

const SKELETON_COLUMNS_COUNT = 8;

export function IdeasTable() {
  const { data, isLoading, isError } = useIdeasQuery();
  const deleteIdea = useDeleteIdea();
  const reorderIdeas = useReorderIdeas();
  const { sorting, setSorting, pagination, setPage, setLimit } =
    useIdeasStore();

  // ID активно перетаскиваемого элемента
  const [activeId, setActiveId] = useState<string | null>(null);

  const columns = useMemo(
    () => createColumns((id) => deleteIdea.mutate(id)),
    [deleteIdea],
  );

  // eslint-disable-next-line react-hooks/incompatible-library
  const table = useReactTable({
    data: data?.data ?? [],
    columns,
    getCoreRowModel: getCoreRowModel(),
    manualSorting: true,
    manualPagination: true,
    getRowId: (row) => row.id,
  });

  const sensors = useSensors(
    useSensor(PointerSensor, {
      activationConstraint: {
        distance: 8,
      },
    }),
    useSensor(KeyboardSensor, {
      coordinateGetter: sortableKeyboardCoordinates,
    }),
  );

  const handleDragStart = (event: DragStartEvent) => {
    setActiveId(event.active.id as string);
  };

  const handleDragEnd = (event: DragEndEvent) => {
    const { active, over } = event;
    setActiveId(null);

    if (over && active.id !== over.id && data?.data) {
      const oldIndex = data.data.findIndex((item) => item.id === active.id);
      const newIndex = data.data.findIndex((item) => item.id === over.id);

      if (oldIndex !== -1 && newIndex !== -1) {
        // Создаём новый порядок
        const items = [...data.data];
        const [movedItem] = items.splice(oldIndex, 1);
        items.splice(newIndex, 0, movedItem);

        // Отправляем на сервер новый порядок
        const reorderItems = items.map((item, index) => ({
          id: item.id,
          order: index,
        }));

        reorderIdeas.mutate(reorderItems);
      }
    }
  };

  const handleSort = (columnId: string) => {
    setSorting(columnId);
  };

  const handleChangePage = (_: unknown, newPage: number) => {
    setPage(newPage + 1);
  };

  const handleChangeRowsPerPage = (
    event: React.ChangeEvent<HTMLInputElement>,
  ) => {
    setLimit(parseInt(event.target.value, 10));
  };

  if (isError) {
    return (
      <Box sx={{ p: 4, textAlign: 'center' }}>
        <Typography color="error">Не удалось загрузить идеи</Typography>
      </Box>
    );
  }

  const rows = table.getRowModel().rows;
  const rowIds = rows.map((row) => row.original.id);
  const activeRow = activeId
    ? rows.find((row) => row.original.id === activeId)
    : null;

  return (
    <Paper sx={{ width: '100%', overflow: 'hidden' }}>
      <DndContext
        sensors={sensors}
        collisionDetection={closestCenter}
        modifiers={[restrictToVerticalAxis]}
        onDragStart={handleDragStart}
        onDragEnd={handleDragEnd}
      >
        <TableContainer>
          <Table stickyHeader size="small">
            <TableHead>
              {table.getHeaderGroups().map((headerGroup) => (
                <TableRow key={headerGroup.id}>
                  {headerGroup.headers.map((header) => (
                    <TableCell
                      key={header.id}
                      sx={{
                        fontWeight: 600,
                        backgroundColor: 'grey.100',
                        width: header.getSize(),
                      }}
                    >
                      {header.column.getCanSort() ? (
                        <TableSortLabel
                          active={sorting.sortBy === header.id}
                          direction={
                            sorting.sortBy === header.id
                              ? (sorting.sortOrder.toLowerCase() as
                                  | 'asc'
                                  | 'desc')
                              : 'asc'
                          }
                          onClick={() => handleSort(header.id)}
                        >
                          {flexRender(
                            header.column.columnDef.header,
                            header.getContext(),
                          )}
                        </TableSortLabel>
                      ) : (
                        flexRender(
                          header.column.columnDef.header,
                          header.getContext(),
                        )
                      )}
                    </TableCell>
                  ))}
                </TableRow>
              ))}
            </TableHead>
            <TableBody>
              {isLoading ? (
                Array.from({ length: 5 }).map((_, index) => (
                  <TableRow key={index}>
                    {Array.from({ length: SKELETON_COLUMNS_COUNT }).map(
                      (_, colIndex) => (
                        <TableCell key={colIndex}>
                          <Skeleton variant="text" />
                        </TableCell>
                      ),
                    )}
                  </TableRow>
                ))
              ) : rows.length === 0 ? (
                <TableRow>
                  <TableCell colSpan={SKELETON_COLUMNS_COUNT}>
                    <Box
                      sx={{
                        py: 8,
                        display: 'flex',
                        flexDirection: 'column',
                        alignItems: 'center',
                        color: 'text.secondary',
                      }}
                    >
                      <Inbox sx={{ fontSize: 48, mb: 2, opacity: 0.5 }} />
                      <Typography variant="h6">Идей пока нет</Typography>
                      <Typography variant="body2">
                        Создайте первую идею, чтобы начать
                      </Typography>
                    </Box>
                  </TableCell>
                </TableRow>
              ) : (
                <SortableContext
                  items={rowIds}
                  strategy={verticalListSortingStrategy}
                >
                  {rows.map((row) => (
                    <DraggableRow key={row.id} row={row} />
                  ))}
                </SortableContext>
              )}
            </TableBody>
          </Table>
        </TableContainer>
        <DragOverlay dropAnimation={null}>
          {activeRow ? (
            <Table
              size="small"
              sx={{
                backgroundColor: 'background.paper',
                boxShadow: 6,
                borderRadius: 1,
                '& td': {
                  backgroundColor: activeRow.original.color
                    ? `${activeRow.original.color}30`
                    : 'action.selected',
                },
              }}
            >
              <TableBody>
                <TableRow>
                  {activeRow.getVisibleCells().map((cell) => (
                    <TableCell
                      key={cell.id}
                      sx={{ width: cell.column.getSize() }}
                    >
                      {flexRender(
                        cell.column.columnDef.cell,
                        cell.getContext(),
                      )}
                    </TableCell>
                  ))}
                </TableRow>
              </TableBody>
            </Table>
          ) : null}
        </DragOverlay>
      </DndContext>
      {data && (
        <TablePagination
          component="div"
          count={data.meta.total}
          page={pagination.page - 1}
          rowsPerPage={pagination.limit}
          onPageChange={handleChangePage}
          onRowsPerPageChange={handleChangeRowsPerPage}
          rowsPerPageOptions={[10, 20, 50, 100]}
        />
      )}
    </Paper>
  );
}
