import {
  ActionIcon,
  Avatar,
  Box,
  CloseButton,
  Flex,
  Group,
  Input,
  Menu,
  Tabs,
  Text,
  Tooltip,
  UnstyledButton,
} from "@mantine/core";
import {
  DndContext,
  useSensor,
  useSensors,
  PointerSensor,
  closestCenter,
  type DragEndEvent,
} from "@dnd-kit/core";
import {
  arrayMove,
  SortableContext,
  useSortable,
  horizontalListSortingStrategy,
} from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
import { useEffect, useMemo, useState, type JSX } from "react";
import {
  IconChevronRight,
  IconEdit,
  IconLogout,
  IconSettingsPlus,
  IconUsersGroup,
} from "@tabler/icons-react";
import classes from "./Component.module.css";
import type { TStation, TUser } from "../untils/types";
import type { Socket } from "socket.io-client";

interface DraggableTabsProps {
  tabsData: TStation[];
  panels: JSX.Element[];
  storageKey?: string;
  onChange: (activeTabId: string | null) => void;
  w?: string | number;
  isStationSettings?: boolean;
  socket: Socket | null;
  usersConnecting: TUser[];
  setIsEditStation: (value: React.SetStateAction<boolean>) => void;
  setIsOpenAddStation: (value: React.SetStateAction<boolean>) => void;
  setStationEdit: (value: React.SetStateAction<TStation | undefined>) => void;
  active: string;
  setActive: (value: React.SetStateAction<string>) => void;
  onSendCommand: (value: string) => void;
}

function SortableTab({
  tab,
  active,
  onChange,
}: {
  tab: TStation;
  active: string | null;
  onChange: (id: string) => void;
  isStationSettings?: boolean;
}) {
  const { attributes, listeners, setNodeRef, transform, transition } =
    useSortable({ id: tab.id.toString() });

  return (
    <Tabs.Tab
      className={classes.tab}
      ref={setNodeRef}
      {...attributes}
      {...listeners}
      onPointerDown={(e) => {
        listeners?.onPointerDown?.(e);
        onChange(tab.id.toString());
      }}
      value={tab.id.toString()}
      style={{
        transform: CSS.Transform.toString(transform),
        transition,
        cursor: "grab",
        userSelect: "none",
      }}
      color={active === tab.id.toString() ? "green" : ""}
      fw={600}
      fz="md"
      c="#747474"
    >
      <Box className={classes.stationName}>
        <Text fw={600} fz="md" className={classes.stationText}>
          {tab.name}
        </Text>
      </Box>
    </Tabs.Tab>
  );
}

export default function DraggableTabs({
  tabsData,
  panels,
  storageKey = "draggable-tabs-order",
  onChange,
  w,
  isStationSettings = false,
  socket,
  usersConnecting,
  setIsEditStation,
  setIsOpenAddStation,
  setStationEdit,
  active,
  setActive,
  onSendCommand,
}: DraggableTabsProps) {
  const user = useMemo(() => {
    return localStorage.getItem("user") &&
      typeof localStorage.getItem("user") === "string"
      ? JSON.parse(localStorage.getItem("user") || "")
      : null;
  }, []);
  const [tabs, setTabs] = useState<TStation[]>(tabsData);
  const [isChangeTab, setIsChangeTab] = useState<boolean>(false);
  const [isSetActive, setIsSetActive] = useState<boolean>(false);
  const [valueInput, setValueInput] = useState<string>("");
  // const [active, setActive] = useState<string | null>(
  //   tabsData?.length > 0 ? tabsData[0]?.id.toString() : null
  // );

  const sensors = useSensors(useSensor(PointerSensor));

  // Load saved order from localStorage
  useEffect(() => {
    if (isChangeTab) {
      setTabs((pre) =>
        pre
          .map((t) => {
            const updatedTab = tabsData.find((td) => td.id === t.id);
            return updatedTab ? updatedTab : t;
          })
          .filter((t) => (tabsData.find((td) => td.id === t.id) ? true : false))
      );
    } else {
      const saved = localStorage.getItem(storageKey);
      let tabSelected =
        tabsData?.length > 0 ? tabsData[0]?.id.toString() : null;
      if (saved) {
        try {
          const order = JSON.parse(saved) as { id: string; index: number }[];

          // Find the max index in saved order
          const maxIndex = Math.max(...order.map((o) => o.index), 0);

          const sorted = [...tabsData].sort((a, b) => {
            const aOrder = order.find(
              (o) => o.id.toString() === a.id.toString()
            )?.index;
            const bOrder = order.find(
              (o) => o.id.toString() === b.id.toString()
            )?.index;

            // If not found, assign index after all existing ones
            const aIndex = aOrder !== undefined ? aOrder : maxIndex + 1;
            const bIndex = bOrder !== undefined ? bOrder : maxIndex + 1;

            return aIndex - bIndex;
          });

          tabSelected = sorted?.length > 0 ? sorted[0]?.id.toString() : null;
          setTabs(sorted);
        } catch {
          setTabs(tabsData);
        }
      } else {
        setTabs(tabsData);
      }

      if (!isSetActive && tabSelected) {
        setActive(tabSelected);
        setTimeout(() => {
          onChange(tabSelected);
        }, 100);
        setIsSetActive(true);
      }
    }
  }, [tabsData, storageKey]);

  // Handle reorder
  const handleDragEnd = (event: DragEndEvent) => {
    const { active: dragActive, over } = event;
    if (dragActive.id !== over?.id && over?.id) {
      const oldIndex = tabs.findIndex(
        (t) => t.id.toString() === dragActive.id.toString()
      );
      const newIndex = tabs.findIndex(
        (t) => t.id.toString() === over?.id.toString()
      );
      const newTabs = arrayMove(tabs, oldIndex, newIndex);
      setTabs(newTabs);

      const order = newTabs.map((t, i) => ({ id: t.id, index: i }));
      localStorage.setItem(storageKey, JSON.stringify(order));
    }
  };

  // Clean up
  useEffect(() => {
    return () => {
      setIsChangeTab(false);
      setIsSetActive(false);
      setTabs([]);
      setActive("0");
    };
  }, []);

  return (
    <DndContext
      sensors={sensors}
      collisionDetection={closestCenter}
      onDragEnd={handleDragEnd}
    >
      <Tabs
        value={active}
        onChange={(val) => {
          setIsChangeTab(true);
          onChange(val);
          setActive(val || "0");
        }}
        w={w}
      >
        <Flex justify={"space-between"}>
          <Flex style={{ width: "300px" }} align={"center"}>
            <Input
              style={{
                width: "300px",
                boxShadow: "0px 0px 10px rgba(0, 0, 0, 0.1)",
              }}
              placeholder={"Chat to Port/All"}
              value={valueInput}
              onChange={(event) => {
                const newValue = event.currentTarget.value;
                setValueInput(newValue);
              }}
              onKeyDown={(event) => {
                if (event.key === "Enter") {
                  onSendCommand(valueInput);
                  setValueInput("");
                }
              }}
              rightSectionPointerEvents="all"
              rightSection={
                <CloseButton
                  aria-label="Clear input"
                  onClick={() => setValueInput("")}
                  style={{ display: valueInput ? undefined : "none" }}
                />
              }
            />
          </Flex>
          <Tabs.List className={classes.list}>
            <SortableContext
              items={tabs}
              strategy={horizontalListSortingStrategy}
            >
              {tabs.map((tab) => (
                <SortableTab
                  key={tab.id}
                  tab={tab}
                  active={active}
                  onChange={(id) => {
                    setIsChangeTab(true);
                    onChange(id);
                    setActive(id);
                  }}
                  isStationSettings={isStationSettings}
                />
              ))}
            </SortableContext>

            <Flex gap={"md"} ms={"xs"} align={"center"}>
              {Number(active) ? (
                <ActionIcon
                  title="Edit Station"
                  variant="outline"
                  onClick={() => {
                    setStationEdit(
                      tabsData.find((el) => el.id === Number(active))
                    );
                    setIsOpenAddStation(true);
                    setIsEditStation(true);
                  }}
                >
                  <IconEdit />
                </ActionIcon>
              ) : (
                ""
              )}
              <ActionIcon
                title="Add Station"
                variant="outline"
                color="green"
                onClick={() => {
                  setIsOpenAddStation(true);
                  setIsEditStation(false);
                  setStationEdit(undefined);
                }}
              >
                <IconSettingsPlus />
              </ActionIcon>
            </Flex>
          </Tabs.List>
          <Flex align={"center"}>
            <Tooltip
              withArrow
              label={usersConnecting.map((el) => (
                <Text key={el.userId}>{el.userName}</Text>
              ))}
            >
              <Avatar radius="xl" me={"sm"}>
                <IconUsersGroup color="green" />
              </Avatar>
            </Tooltip>
            <Menu withArrow>
              <Menu.Target>
                <UnstyledButton
                  style={{
                    padding: "var(--mantine-spacing-md)",
                    color: "var(--mantine-color-text)",
                    borderRadius: "var(--mantine-radius-sm)",
                  }}
                >
                  <Group>
                    <div style={{ flex: 1 }}>
                      <Text size="sm" fw={500}>
                        {user?.userName || user?.user_name || ""}
                      </Text>

                      <Text c="dimmed" size="xs">
                        {user?.email}
                      </Text>
                    </div>

                    <IconChevronRight size={16} />
                  </Group>
                </UnstyledButton>
              </Menu.Target>
              <Menu.Dropdown>
                <Menu.Item
                  style={{ width: "150px" }}
                  onClick={() => {
                    localStorage.removeItem("user");
                    window.location.href = "/";
                    socket?.disconnect();
                  }}
                  color="red"
                  leftSection={<IconLogout size={16} stroke={1.5} />}
                >
                  Logout
                </Menu.Item>
              </Menu.Dropdown>
            </Menu>
          </Flex>
        </Flex>

        {panels}
      </Tabs>
    </DndContext>
  );
}
