import * as React from 'react';
import {
  DndContext,
  DragEndEvent,
  DragOverEvent,
  DragOverlay,
  DragStartEvent,
  KeyboardSensor,
  PointerSensor,
  useSensor,
  useSensors,
} from '@dnd-kit/core';
import { arrayMove, sortableKeyboardCoordinates } from '@dnd-kit/sortable';
import { Button, Typography, Box, Card, alpha } from '@mui/material';
import { Column, ColumnSelectorProps } from './types';
import CustomPopover, { usePopover } from '../custom-popover';
import { ColumnButton } from '../table/styles';
import SvgColor from '../svg-color';
import { ColumnContainer } from './column-container';
import { ControlButtons } from './control-buttons';

export function ColumnSelector({ sx,onConfirm, initialColumns = [] }: ColumnSelectorProps) {
  const [activeId, setActiveId] = React.useState<string | null>(null);
  const [selectedColumns, setSelectedColumns] = React.useState<Column[]>([]);
  const [availableColumns, setAvailableColumns] = React.useState<Column[]>(initialColumns);
  const [checkedSelected, setCheckedSelected] = React.useState<string[]>([]);
  const [checkedAvailable, setCheckedAvailable] = React.useState<string[]>([]);

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

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

  const handleDragOver = (event: DragOverEvent) => {
    const { active, over } = event;
    const overId = over
      ? over.id
      : selectedColumns.length === 0
        ? 'selected-columns'
        : 'available-columns';

    const activeColumn = [...selectedColumns, ...availableColumns].find(
      (col) => col.id === active.id
    );
    if (!activeColumn) return;

    const isOverContainer = overId === 'selected-columns' || overId === 'available-columns';
    const fromContainer = selectedColumns.some((col) => col.id === active.id)
      ? 'selected'
      : 'available';
    const toContainer = isOverContainer
      ? overId === 'selected-columns'
        ? 'selected'
        : 'available'
      : selectedColumns.some((col) => col.id === overId)
        ? 'selected'
        : 'available';

    if (fromContainer !== toContainer) {
      if (toContainer === 'selected') {
        setSelectedColumns((prev) => {
          const overIndex = isOverContainer
            ? prev.length
            : prev.findIndex((col) => col.id === overId);
          return [...prev.slice(0, overIndex), activeColumn, ...prev.slice(overIndex)];
        });
        setAvailableColumns((prev) => prev.filter((col) => col.id !== active.id));
      } else {
        setAvailableColumns((prev) => {
          const overIndex = isOverContainer
            ? prev.length
            : prev.findIndex((col) => col.id === overId);
          return [...prev.slice(0, overIndex), activeColumn, ...prev.slice(overIndex)];
        });
        setSelectedColumns((prev) => prev.filter((col) => col.id !== active.id));
      }
    }
  };

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

    const overId = over
      ? over.id
      : selectedColumns.length === 0
        ? 'selected-columns'
        : 'available-columns';

    const activeColumn = [...selectedColumns, ...availableColumns].find(
      (col) => col.id === active.id
    );
    if (!activeColumn) return;

    const isOverContainer = overId === 'selected-columns' || overId === 'available-columns';
    const fromContainer = selectedColumns.some((col) => col.id === active.id)
      ? 'selected'
      : 'available';
    const toContainer = isOverContainer
      ? overId === 'selected-columns'
        ? 'selected'
        : 'available'
      : selectedColumns.some((col) => col.id === overId)
        ? 'selected'
        : 'available';

    if (fromContainer === toContainer) {
      const reorderColumns = (columns: Column[]) => {
        const oldIndex = columns.findIndex((col) => col.id === active.id);
        const newIndex = isOverContainer
          ? columns.length - 1
          : columns.findIndex((col) => col.id === overId);
        return arrayMove(columns, oldIndex, newIndex);
      };

      if (toContainer === 'selected') {
        setSelectedColumns(reorderColumns);
      } else {
        setAvailableColumns(reorderColumns);
      }
    } else {
      if (toContainer === 'selected') {
        setSelectedColumns((prev) => [...prev, activeColumn]);
        setAvailableColumns((prev) => prev.filter((col) => col.id !== active.id));
      } else {
        setAvailableColumns((prev) => [...prev, activeColumn]);
        setSelectedColumns((prev) => prev.filter((col) => col.id !== active.id));
      }
    }
  };

  const handleCheckSelected = (columnId: string) => {
    setCheckedSelected((prev) =>
      prev.includes(columnId) ? prev.filter((id) => id !== columnId) : [...prev, columnId]
    );
  };

  const handleCheckAvailable = (columnId: string) => {
    setCheckedAvailable((prev) =>
      prev.includes(columnId) ? prev.filter((id) => id !== columnId) : [...prev, columnId]
    );
  };

  const moveToSelected = (columns: Column[]) => {
    setSelectedColumns((prev) => [...prev, ...columns]);
    setAvailableColumns((prev) => prev.filter((col) => !columns.includes(col)));
    setCheckedAvailable([]);
  };

  const moveToAvailable = (columns: Column[]) => {
    setAvailableColumns((prev) => [...prev, ...columns]);
    setSelectedColumns((prev) => prev.filter((col) => !columns.includes(col)));
    setCheckedSelected([]);
  };

  const popover = usePopover();
  const handleConfirm = () => {
    if (selectedColumns.length === 0) {
      onConfirm(availableColumns);
    } else {
      onConfirm(selectedColumns);
    }
    popover.onClose();
  };

  return (
    <div>
      <ColumnButton
        variant="contained"
        sx={{...sx}}
        onClick={popover.onOpen}
        endIcon={<SvgColor src="/assets/icons/ic_table.svg" sx={{width: '20px' }} />}
      >
        Colonnes
      </ColumnButton>

      <CustomPopover
        arrow="top-right"
        hiddenArrow={true}
        open={popover.open}
        onClose={popover.onClose}
        sx={{
          width: {
            xs: 600,
            s: 600,
            md: 600,
            lg: 650,
            xl: 750,
          },
          height: '77%',
          borderRadius: 4,
          mt: '0.6%',
          display: 'flex',
          flexDirection: 'column',
        }}
      >
        <DndContext
          sensors={sensors}
          onDragStart={handleDragStart}
          onDragOver={handleDragOver}
          onDragEnd={handleDragEnd}
        >
          <Box
            sx={{
              display: 'flex',
              gap: 1,
              py: 4,
              px: 3,
              borderRadius: 4,
              bgcolor: (theme) => alpha(theme.palette.primary.main, 0.1),
              flexGrow: 1,
              overflow: 'hidden',
            }}
          >
            <Card
              elevation={0}
              sx={{
                flex: 1,
                bgcolor: 'background.paper',
                borderRadius: 3,
                display: 'flex',
                flexDirection: 'column',
                minWidth: { xs: 250, lg: 250, xl: 300 },
                maxHeight: '100%',
                overflow: 'hidden',
              }}
            >
              <ColumnContainer
                columns={availableColumns}
                checkedColumns={checkedAvailable}
                onCheckChange={handleCheckAvailable}
                containerId="available-columns"
                title="Liste des colonnes disponible"
              />
            </Card>

            <ControlButtons
              onMoveAllToAvailable={() => moveToAvailable(selectedColumns)}
              onMoveSelectedToAvailable={() =>
                moveToAvailable(selectedColumns.filter((col) => checkedSelected.includes(col.id)))
              }
              onMoveAllToSelected={() => moveToSelected(availableColumns)}
              onMoveSelectedToSelected={() =>
                moveToSelected(availableColumns.filter((col) => checkedAvailable.includes(col.id)))
              }
            />

            <Card
              elevation={0}
              sx={{
                flex: 1,
                bgcolor: 'background.paper',
                borderRadius: 3,
                display: 'flex',
                flexDirection: 'column',
                minWidth: { xs: 250, lg: 250, xl: 300 },
                maxHeight: '100%',
                overflow: 'hidden',
              }}
            >
              <ColumnContainer
                columns={selectedColumns}
                checkedColumns={checkedSelected}
                onCheckChange={handleCheckSelected}
                containerId="selected-columns"
                title="Colonnes affichées dans cet ordre"
              />
              <Box
                sx={{
                  display: 'flex',
                  justifyContent: 'flex-end',
                  gap: 1,
                  px: 2,
                  pb: 1,
                }}
              >
                <Button
                  size="small"
                  variant="outlined"
                  color="primary"
                  sx={{ borderRadius: 2, width: { xl: '30%', sm: '35%' }, textTransform: 'none' }}
                  onClick={popover.onClose}
                >
                  Annuler
                </Button>
                <Button
                  size="small"
                  variant="contained"
                  
                  color="primary"
                  sx={{
                    boxShadow: 'none',
                    borderRadius: 2,
                    width: { xl: '30%', sm: '35%' },
                    textTransform: 'none',
                  }}
                  onClick={handleConfirm}
                >
                  Enregistrer
                </Button>
              </Box>
            </Card>
          </Box>

          <DragOverlay>
            {activeId ? (
              <Box
                sx={{
                  p: 1.5,
                  display: 'flex',
                  alignItems: 'center',
                  gap: 2,
                  bgcolor: 'primary.main',
                  color: 'primary.contrastText',
                  borderRadius: 1,
                  boxShadow: 2,
                }}
              >
                <Typography variant="body2">
                  {
                    [...selectedColumns, ...availableColumns].find((col) => col.id === activeId)
                      ?.label
                  }
                </Typography>
              </Box>
            ) : null}
          </DragOverlay>
        </DndContext>
      </CustomPopover>
    </div>
  );
}
