import { useEffect, useLayoutEffect, useRef, useState, type MouseEvent } from 'react';
import { Link, useLocation } from 'react-router-dom';
import { Bot, ChevronLeft, ChevronRight } from 'lucide-react';
import { appNavItems } from './navigation';

const DRAWER_ANIMATION_DURATION_MS = 300;

function getChildDrawerMaxHeight(childCount: number) {
  return childCount * 44 + Math.max(0, childCount - 1) * 4 + 8;
}

function doesSearchMatch(search: string | undefined, currentSearchParams: URLSearchParams) {
  if (!search) {
    return false;
  }

  const expectedSearchParams = new URLSearchParams(search);

  for (const [key, value] of expectedSearchParams.entries()) {
    if (currentSearchParams.get(key) !== value) {
      return false;
    }
  }

  return true;
}

function doesDefaultChildMatch(search: string | undefined, currentSearchParams: URLSearchParams) {
  return !search && Array.from(currentSearchParams.keys()).length === 0;
}

function resolveActiveNavId(pathname: string, search: string) {
  const currentSearchParams = new URLSearchParams(search);

  for (const item of appNavItems) {
    if (!item.children?.length) {
      continue;
    }

    const matchedChild = item.children.find((child) => (
      child.path === pathname
      && (doesSearchMatch(child.search, currentSearchParams) || doesDefaultChildMatch(child.search, currentSearchParams))
    ));

    if (matchedChild) {
      return matchedChild.id;
    }
  }

  for (const item of appNavItems) {
    if (!item.children?.length || item.path !== pathname) {
      continue;
    }

    const defaultChild = item.children.find((child) => !child.search && child.path === pathname);
    return defaultChild?.id ?? item.id;
  }

  return pathname;
}

function resolveExpandedParentId(pathname: string, search: string) {
  const activeNavId = resolveActiveNavId(pathname, search);
  const parentItem = appNavItems.find((item) => item.children?.some((child) => child.id === activeNavId));

  return parentItem?.id ?? null;
}

export function AppSidebar() {
  const location = useLocation();
  const navRootRef = useRef<HTMLDivElement | null>(null);
  const itemRefs = useRef<Record<string, HTMLAnchorElement | null>>({});
  const routeExpandedParentIdRef = useRef<string | null>(null);
  const [indicatorStyle, setIndicatorStyle] = useState({ top: 0, height: 0, opacity: 0 });
  const [collapsed, setCollapsed] = useState(false);
  const activeNavId = resolveActiveNavId(location.pathname, location.search);
  const routeExpandedParentId = collapsed ? null : resolveExpandedParentId(location.pathname, location.search);
  const [openParentId, setOpenParentId] = useState<string | null>(routeExpandedParentId);
  const indicatorTargetId = openParentId === routeExpandedParentId
    ? activeNavId
    : routeExpandedParentId ?? activeNavId;

  useEffect(() => {
    if (collapsed) {
      setOpenParentId(null);
      routeExpandedParentIdRef.current = null;
      return;
    }

    if (routeExpandedParentIdRef.current !== routeExpandedParentId) {
      setOpenParentId(routeExpandedParentId);
      routeExpandedParentIdRef.current = routeExpandedParentId;
    }
  }, [collapsed, routeExpandedParentId]);

  const handleParentItemClick = (
    event: MouseEvent<HTMLAnchorElement>,
    itemPath: string,
    itemId: string,
    hasChildren: boolean,
    expanded: boolean,
  ) => {
    if (!hasChildren || collapsed) {
      return;
    }

    if (expanded) {
      event.preventDefault();
      setOpenParentId(null);
      return;
    }

    setOpenParentId(itemId);

    if (location.pathname === itemPath) {
      event.preventDefault();
    }
  };

  const syncIndicator = () => {
    const activeItem = itemRefs.current[indicatorTargetId] ?? itemRefs.current[location.pathname];
    const navRoot = navRootRef.current;

    if (!activeItem || !navRoot) {
      setIndicatorStyle((current) => (current.opacity === 0 ? current : { ...current, opacity: 0 }));
      return;
    }

    const navRootRect = navRoot.getBoundingClientRect();
    const activeRect = activeItem.getBoundingClientRect();
    const height = 20;
    const top = activeRect.top - navRootRect.top + (activeRect.height - height) / 2;

    setIndicatorStyle((current) => {
      if (current.top === top && current.height === height && current.opacity === 1) {
        return current;
      }

      return { top, height, opacity: 1 };
    });
  };

  useLayoutEffect(() => {
    syncIndicator();
    const rafId = window.requestAnimationFrame(() => {
      syncIndicator();
    });
    const timeoutId = window.setTimeout(() => {
      syncIndicator();
    }, DRAWER_ANIMATION_DURATION_MS);
    window.addEventListener('resize', syncIndicator);

    return () => {
      window.cancelAnimationFrame(rafId);
      window.clearTimeout(timeoutId);
      window.removeEventListener('resize', syncIndicator);
    };
  }, [collapsed, indicatorTargetId, location.pathname, openParentId]);

  return (
    <aside
      className={[
        'm-4 mr-0 flex shrink-0 self-stretch flex-col rounded-[24px] border border-slate-200/70 bg-white/95 shadow-xl backdrop-blur-md dark:border-white/5 dark:bg-slate-900/95 transition-[width] duration-300 ease-in-out overflow-hidden',
        collapsed ? 'w-[72px]' : 'w-[208px]',
      ].join(' ')}
    >
      {/* Logo */}
      <div
        className={[
          'shrink-0 border-b border-slate-200/80 pb-4 pt-5 dark:border-white/10',
          collapsed ? 'flex justify-center px-2' : 'px-5',
        ].join(' ')}
      >
        <div className="flex items-center gap-3">
          <div className="ai-bot-border relative flex h-11 w-11 shrink-0 items-center justify-center rounded-full p-[2px] shadow-[0_14px_30px_-18px_rgba(59,130,246,0.95)]">
            <div className="flex h-full w-full items-center justify-center rounded-full bg-[radial-gradient(circle_at_50%_45%,rgba(96,165,250,0.95)_0%,rgba(29,78,216,0.72)_28%,rgba(15,23,42,0.98)_70%,rgba(2,6,23,1)_100%)] text-white">
              <Bot className="h-[18px] w-[18px]" strokeWidth={1.9} />
            </div>
          </div>
          <div
            className="flex h-11 items-center min-w-0 overflow-hidden whitespace-nowrap transition-all duration-300 ease-out"
            style={{
              maxWidth: collapsed ? 0 : '132px',
              opacity: collapsed ? 0 : 1,
              transform: collapsed ? 'translateX(-8px)' : 'translateX(0)',
              transitionDelay: collapsed ? '0ms' : '80ms',
            }}
          >
            <span className="block text-lg font-semibold leading-tight tracking-tight text-slate-800 dark:text-white">
              AI智采系统
            </span>
          </div>
        </div>
      </div>

      {/* Navigation */}
      <nav className="flex-1 overflow-y-auto overflow-x-hidden px-3 py-4">
        <div ref={navRootRef} className="relative">
          <span
            aria-hidden="true"
            className="pointer-events-none absolute left-1 w-[3px] rounded-full bg-blue-600 transition-all duration-300 ease-out dark:bg-white"
            style={{
              top: `${indicatorStyle.top}px`,
              height: `${indicatorStyle.height}px`,
              opacity: indicatorStyle.opacity,
            }}
          />

          <div className="space-y-1">
            {appNavItems.map(item => {
              const active = location.pathname === item.path;
              const hasChildren = Boolean(item.children?.length);
              const hasActiveChild = item.children?.some(child => child.id === activeNavId) ?? false;
              const expanded = hasChildren && openParentId === item.id;
              const topLevelActiveClassName = hasChildren
                ? hasActiveChild
                  ? 'bg-slate-100 text-slate-900 font-medium dark:bg-white/10 dark:text-white'
                  : 'text-slate-400 hover:bg-slate-100 hover:text-slate-900 dark:text-slate-400 dark:hover:bg-white/5 dark:hover:text-white'
                : active
                  ? 'bg-slate-100 text-slate-900 font-medium dark:bg-white/10 dark:text-white dark:font-medium'
                  : 'text-slate-400 hover:bg-slate-100 hover:text-slate-900 dark:text-slate-400 dark:hover:bg-white/5 dark:hover:text-white';
              const childDrawerMaxHeight = getChildDrawerMaxHeight(item.children?.length ?? 0);

              return (
                <div key={item.id} className="space-y-1">
                  <Link
                    to={item.path}
                    ref={node => {
                      itemRefs.current[item.id] = node;
                    }}
                    onClick={(event) => handleParentItemClick(event, item.path, item.id, hasChildren, expanded)}
                    title={collapsed ? item.label : undefined}
                    aria-expanded={hasChildren ? expanded : undefined}
                    className={[
                      'group relative flex items-center rounded-xl py-3 text-sm transition-all duration-200',
                      collapsed ? 'justify-center px-2' : 'gap-3 px-3.5',
                      topLevelActiveClassName,
                    ].join(' ')}
                  >
                    <item.icon className={[
                      'h-4 w-4 shrink-0 transition-colors duration-200',
                      active || hasActiveChild
                        ? 'text-blue-600 dark:text-white'
                        : 'text-slate-400 group-hover:text-slate-700 dark:text-slate-400 dark:group-hover:text-white',
                    ].join(' ')} />
                    <span
                      className="overflow-hidden whitespace-nowrap transition-all duration-300 ease-out"
                      style={{
                        maxWidth: collapsed ? 0 : hasChildren ? '108px' : '140px',
                        opacity: collapsed ? 0 : 1,
                        transform: collapsed ? 'translateX(-6px)' : 'translateX(0)',
                        transitionDelay: collapsed ? '0ms' : '80ms',
                      }}
                    >
                      {item.label}
                    </span>
                    {hasChildren && !collapsed && (
                      <ChevronRight className={[
                        'ml-auto h-4 w-4 shrink-0 text-slate-400 transition-all duration-300 ease-out group-hover:text-slate-700 dark:text-slate-400 dark:group-hover:text-white',
                        expanded ? 'rotate-90 text-blue-600 dark:text-white' : '',
                      ].join(' ')} />
                    )}
                  </Link>

                  {hasChildren && !collapsed && (
                    <div
                      aria-hidden={!expanded}
                      className="overflow-hidden transition-all duration-300 ease-out"
                      style={{
                        maxHeight: expanded ? `${childDrawerMaxHeight}px` : '0px',
                        opacity: expanded ? 1 : 0,
                        transform: expanded ? 'translateY(0)' : 'translateY(-8px)',
                        pointerEvents: expanded ? 'auto' : 'none',
                      }}
                    >
                      <div
                        className="space-y-1 pl-10 pb-1"
                        style={{
                          opacity: expanded ? 1 : 0,
                          transform: expanded ? 'translateX(0)' : 'translateX(-6px)',
                          transition: 'opacity 300ms ease-out, transform 300ms ease-out',
                          transitionDelay: expanded ? '80ms' : '0ms',
                        }}
                      >
                        {item.children?.map(child => {
                          const childActive = child.id === activeNavId;

                          return (
                            <Link
                              key={child.id}
                              to={{ pathname: child.path, search: child.search }}
                              tabIndex={expanded ? 0 : -1}
                              ref={node => {
                                itemRefs.current[child.id] = node;
                              }}
                              className={[
                                'group flex min-h-9 items-center rounded-lg px-3 text-[13px] transition-all duration-200',
                                childActive
                                  ? 'bg-blue-50 text-blue-700 font-medium dark:bg-white/10 dark:text-white'
                                  : hasActiveChild
                                    ? 'text-slate-500 hover:bg-slate-100 hover:text-slate-900 dark:text-slate-400 dark:hover:bg-white/5 dark:hover:text-white'
                                    : 'text-slate-400 hover:bg-slate-100 hover:text-slate-900 dark:text-slate-400 dark:hover:bg-white/5 dark:hover:text-white',
                              ].join(' ')}
                            >
                              <span
                                className="truncate overflow-hidden whitespace-nowrap transition-all duration-300 ease-out"
                                style={{
                                  maxWidth: expanded ? '116px' : 0,
                                  opacity: expanded ? 1 : 0,
                                  transform: expanded ? 'translateX(0)' : 'translateX(-6px)',
                                  transitionDelay: expanded ? '100ms' : '0ms',
                                }}
                              >
                                {child.label}
                              </span>
                            </Link>
                          );
                        })}
                      </div>
                    </div>
                  )}
                </div>
              );
            })}
          </div>
        </div>
      </nav>

      {/* Collapse toggle */}
      <div className="shrink-0 border-t border-slate-200/80 p-3 dark:border-white/10 flex justify-center">
        <button
          onClick={() => setCollapsed(prev => !prev)}
          className="flex h-8 w-8 items-center justify-center rounded-lg text-slate-400 hover:bg-slate-100 hover:text-slate-700 transition-colors dark:hover:bg-white/10 dark:hover:text-white"
          title={collapsed ? '展开侧边栏' : '收起侧边栏'}
        >
          {collapsed
            ? <ChevronRight className="h-4 w-4" />
            : <ChevronLeft className="h-4 w-4" />}
        </button>
      </div>
    </aside>
  );
}
