import React, { useEffect, useMemo } from 'react';
import {
  closestCenter,
  DndContext,
  PointerSensor,
  useSensor,
  useSensors,
  type DragEndEvent,
} from '@dnd-kit/core';
import {
  arrayMove,
  horizontalListSortingStrategy,
  SortableContext,
  useSortable,
} from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';
import { Button, Dropdown, Tabs, type TabsProps } from 'antd';
import { DownOutlined } from '@ant-design/icons';
import type { Location } from 'react-router';
import type { AppMenuItem } from '../../auth/menu-policy';
import { useAppStore } from '../../store';
import { upsertDockTab } from './dockTabs';

interface RouteDockProps {
  location: Location;
  menuItems: readonly AppMenuItem[];
  onNavigate: (path: string) => void;
  draggable: boolean;
}

interface DraggableTabNodeProps extends React.HTMLAttributes<HTMLDivElement> {
  'data-node-key': string;
}

function findMenuLabel(items: readonly AppMenuItem[], pathname: string): string | undefined {
  for (const item of items) {
    if (item.key === pathname) return item.label;
    if (item.children) {
      const label = findMenuLabel(item.children, pathname);
      if (label) return label;
    }
  }
  return undefined;
}

function getRouteLabel(items: readonly AppMenuItem[], pathname: string): string {
  const menuLabel = findMenuLabel(items, pathname);
  if (menuLabel) return menuLabel;
  if (/^\/students\/\d+\/profile$/.test(pathname)) return '学生档案';
  if (/^\/classes\/\d+$/.test(pathname)) return '班级详情';
  return pathname === '/' ? '首页' : '页面';
}

const DraggableTabNode: React.FC<Readonly<DraggableTabNodeProps>> = ({ ...props }) => {
  const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({
    id: props['data-node-key'],
  });
  const child = props.children as React.ReactElement<{ style?: React.CSSProperties }>;

  return React.cloneElement(child, {
    ref: setNodeRef,
    style: {
      ...child.props.style,
      transform: CSS.Translate.toString(transform),
      transition,
      cursor: isDragging ? 'grabbing' : 'grab',
      zIndex: isDragging ? 1 : undefined,
      opacity: isDragging ? 0.92 : undefined,
      boxShadow: isDragging ? '0 8px 20px rgba(29, 29, 31, 0.14)' : undefined,
    },
    ...attributes,
    ...listeners,
  } as React.HTMLAttributes<HTMLElement>);
};

const RouteDock: React.FC<RouteDockProps> = ({ location, menuItems, onNavigate, draggable }) => {
  // 与 RouteKeeper 缓存 key 保持一致：只按 pathname 建 tab，避免 query 变化产生重复页签。
  const activeKey = location.pathname;
  const tabs = useAppStore((state) => state.routeDockTabs);
  const setRouteDockTabs = useAppStore((state) => state.setRouteDockTabs);
  const sensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 8 } }));

  useEffect(() => {
    if (location.pathname === '/') return;
    const label = getRouteLabel(menuItems, location.pathname);
    setRouteDockTabs((currentTabs) => upsertDockTab(currentTabs, activeKey, label));
  }, [activeKey, location.pathname, menuItems, setRouteDockTabs]);

  const tabItems = useMemo<NonNullable<TabsProps['items']>>(
    () =>
      tabs.map((tab) => ({
        key: tab.key,
        label: tab.label,
        closable: tabs.length > 1,
      })),
    [tabs],
  );

  const closeTab = (targetKey: string) => {
    const targetIndex = tabs.findIndex((tab) => tab.key === targetKey);
    if (targetIndex < 0 || tabs.length === 1) return;
    const nextTabs = tabs.filter((tab) => tab.key !== targetKey);
    setRouteDockTabs(nextTabs);
    if (targetKey === activeKey) {
      const nextActiveTab = nextTabs[Math.min(targetIndex, nextTabs.length - 1)];
      if (nextActiveTab) onNavigate(nextActiveTab.key);
    }
  };

  const closeOthers = () => {
    setRouteDockTabs(tabs.filter((tab) => tab.key === activeKey));
  };

  const closeLeft = () => {
    const index = tabs.findIndex((tab) => tab.key === activeKey);
    if (index <= 0) return;
    setRouteDockTabs(tabs.filter((_, i) => i >= index));
  };

  const closeRight = () => {
    const index = tabs.findIndex((tab) => tab.key === activeKey);
    if (index < 0 || index === tabs.length - 1) return;
    setRouteDockTabs(tabs.filter((_, i) => i <= index));
  };

  const closeAll = () => {
    setRouteDockTabs([]);
    onNavigate('/dashboard');
  };

  const handleDragEnd = ({ active, over }: DragEndEvent) => {
    if (!over || active.id === over.id) return;
    setRouteDockTabs((currentTabs) => {
      const activeIndex = currentTabs.findIndex((tab) => tab.key === active.id);
      const overIndex = currentTabs.findIndex((tab) => tab.key === over.id);
      return activeIndex < 0 || overIndex < 0
        ? currentTabs
        : arrayMove(currentTabs, activeIndex, overIndex);
    });
  };

  const renderTabBar: TabsProps['renderTabBar'] = (tabBarProps, DefaultTabBar) => {
    const tabBar = (
      <DefaultTabBar {...tabBarProps}>
        {(node) => {
          if (!draggable) return node;
          return (
            <DraggableTabNode
              {...(node as React.ReactElement<DraggableTabNodeProps>).props}
              key={node.key}
            >
              {node}
            </DraggableTabNode>
          );
        }}
      </DefaultTabBar>
    );

    if (!draggable) return tabBar;
    return (
      <DndContext sensors={sensors} collisionDetection={closestCenter} onDragEnd={handleDragEnd}>
        <SortableContext
          items={tabs.map((tab) => tab.key)}
          strategy={horizontalListSortingStrategy}
        >
          {tabBar}
        </SortableContext>
      </DndContext>
    );
  };

  if (location.pathname === '/' || tabs.length === 0) return null;

  return (
    <nav className="route-dock" aria-label="已打开页面">
      <Tabs
        type="editable-card"
        size="small"
        hideAdd
        activeKey={activeKey}
        items={tabItems}
        animated={false}
        onChange={onNavigate}
        onEdit={(targetKey, action) => {
          if (action === 'remove') closeTab(String(targetKey));
        }}
        renderTabBar={renderTabBar}
        tabBarExtraContent={
          tabs.length > 1 ? (
            <Dropdown
              trigger={['click']}
              menu={{
                items: [
                  { key: 'close-others', label: '关闭其他' },
                  { key: 'close-left', label: '关闭左侧' },
                  { key: 'close-right', label: '关闭右侧' },
                  { type: 'divider' },
                  { key: 'close-all', label: '关闭全部' },
                ],
                onClick: ({ key }) => {
                  if (key === 'close-others') closeOthers();
                  else if (key === 'close-left') closeLeft();
                  else if (key === 'close-right') closeRight();
                  else if (key === 'close-all') closeAll();
                },
              }}
            >
              <Button type="text" size="small" icon={<DownOutlined />} aria-label="更多页签操作">
                更多
              </Button>
            </Dropdown>
          ) : undefined
        }
      />
    </nav>
  );
};

export default RouteDock;
