/**
 * KRA - Sidebar Component
 * Collapsible sidebar menu with multi-level navigation
 */
import React, { useState, useEffect, useMemo } from 'react';
import { Menu, Layout } from 'antd';
import type { MenuProps } from 'antd';
import { useModel, history, useLocation } from '@umijs/max';
import * as Icons from '@ant-design/icons';
import { useCollapsed, useConfig, useAsyncRouters } from '@/models';

const { Sider } = Layout;

interface MenuItem {
  ID?: number;
  name: string;
  path: string;
  hidden?: boolean;
  component?: string;
  meta?: {
    title: string;
    icon?: string;
    keepAlive?: boolean;
    defaultMenu?: boolean;
    closeTab?: boolean;
    activeName?: string;
  };
  children?: MenuItem[];
  parameters?: Array<{ type: string; key: string; value: string }>;
}

// Get icon component by name
const getIcon = (iconName?: string): React.ReactNode => {
  if (!iconName) return null;
  const IconComponent = (Icons as any)[iconName] || (Icons as any)[`${iconName}Outlined`];
  return IconComponent ? <IconComponent /> : null;
};

// Convert menu data to Ant Design menu items
const convertToMenuItems = (menus: MenuItem[]): MenuProps['items'] => {
  return menus
    .filter((item) => !item.hidden)
    .map((item) => {
      const hasChildren = item.children && item.children.filter((c) => !c.hidden).length > 0;

      if (hasChildren) {
        return {
          key: item.name,
          icon: getIcon(item.meta?.icon),
          label: item.meta?.title || item.name,
          children: convertToMenuItems(item.children!),
        };
      }

      return {
        key: item.name,
        icon: getIcon(item.meta?.icon),
        label: item.meta?.title || item.name,
      };
    });
};

interface SidebarProps {
  /** Custom width */
  width?: number;
  /** Collapsed width */
  collapsedWidth?: number;
  /** Theme */
  theme?: 'light' | 'dark';
  /** Show logo */
  showLogo?: boolean;
}

const Sidebar: React.FC<SidebarProps> = ({
  width,
  collapsedWidth,
  theme = 'dark',
  showLogo = true,
}) => {
  const location = useLocation();
  const collapsed = useCollapsed();
  const config = useConfig();
  const asyncRouters = useAsyncRouters();
  const { routeMap } = useModel('router');

  const [selectedKeys, setSelectedKeys] = useState<string[]>([]);
  const [openKeys, setOpenKeys] = useState<string[]>([]);

  // Get menu items from async routers
  const menuItems = useMemo(() => {
    const rootMenu = asyncRouters?.[0];
    if (!rootMenu?.children) return [];
    return convertToMenuItems(rootMenu.children);
  }, [asyncRouters]);

  // Find parent keys for a menu item
  const findParentKeys = (name: string, menus: MenuItem[], parents: string[] = []): string[] => {
    for (const menu of menus) {
      if (menu.name === name) {
        return parents;
      }
      if (menu.children) {
        const found = findParentKeys(name, menu.children, [...parents, menu.name]);
        if (found.length > 0 || menu.children.some((c) => c.name === name)) {
          return found.length > 0 ? found : [...parents, menu.name];
        }
      }
    }
    return [];
  };

  // Update selected keys based on current route
  useEffect(() => {
    const pathname = location.pathname;
    // Find the menu item that matches the current path
    const findMenuByPath = (menus: MenuItem[]): MenuItem | null => {
      for (const menu of menus) {
        if (menu.path === pathname || `/${menu.path}` === pathname) {
          return menu;
        }
        if (menu.children) {
          const found = findMenuByPath(menu.children);
          if (found) return found;
        }
      }
      return null;
    };

    const rootMenu = asyncRouters?.[0];
    if (rootMenu?.children) {
      const currentMenu = findMenuByPath(rootMenu.children);
      if (currentMenu) {
        setSelectedKeys([currentMenu.name]);
        const parentKeys = findParentKeys(currentMenu.name, rootMenu.children);
        if (parentKeys.length > 0 && !collapsed) {
          setOpenKeys(parentKeys);
        }
      }
    }
  }, [location.pathname, asyncRouters, collapsed]);

  // Handle menu click
  const handleMenuClick: MenuProps['onClick'] = ({ key }) => {
    const menuItem = routeMap?.[key];
    if (!menuItem) {
      history.push(`/${key}`);
      return;
    }

    // Handle external links
    if (key.startsWith('http://') || key.startsWith('https://')) {
      window.open(key, '_blank');
      return;
    }

    // Build query and params from menu parameters
    const query: Record<string, string> = {};
    const params: Record<string, string> = {};
    menuItem.parameters?.forEach((param: any) => {
      if (param.type === 'query') {
        query[param.key] = param.value;
      } else {
        params[param.key] = param.value;
      }
    });

    history.push({
      pathname: menuItem.path?.startsWith('/') ? menuItem.path : `/${menuItem.path}`,
      query,
    });
  };

  // Handle open keys change
  const handleOpenChange = (keys: string[]) => {
    setOpenKeys(keys);
  };

  const siderWidth = width || config?.sideWidth || 256;
  const siderCollapsedWidth = collapsedWidth || config?.sideCollapsedWidth || 80;

  return (
    <Sider
      collapsible
      collapsed={collapsed}
      width={siderWidth}
      collapsedWidth={siderCollapsedWidth}
      theme={theme}
      trigger={null}
      style={{
        overflow: 'auto',
        height: '100vh',
        position: 'fixed',
        left: 0,
        top: 0,
        bottom: 0,
      }}
    >
      {showLogo && (
        <div
          style={{
            height: 64,
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'center',
            padding: collapsed ? '0 8px' : '0 16px',
            borderBottom: '1px solid rgba(255,255,255,0.1)',
          }}
        >
          <img
            src="/logo.svg"
            alt="KRA"
            style={{ height: 32, marginRight: collapsed ? 0 : 8 }}
          />
          {!collapsed && (
            <span
              style={{
                color: '#fff',
                fontSize: 18,
                fontWeight: 600,
                whiteSpace: 'nowrap',
              }}
            >
              Kratos Admin
            </span>
          )}
        </div>
      )}

      <Menu
        theme={theme}
        mode="inline"
        selectedKeys={selectedKeys}
        openKeys={collapsed ? [] : openKeys}
        onOpenChange={handleOpenChange}
        onClick={handleMenuClick}
        items={menuItems}
        style={{ borderRight: 0 }}
      />
    </Sider>
  );
};

export default Sidebar;
