/**
 * KRA - Normal Mode Layout
 * Standard sidebar layout with collapsible menu
 */
import React, { useState, useEffect, useMemo } from 'react';
import { Layout, Menu } from 'antd';
import type { MenuProps } from 'antd';
import { MenuFoldOutlined, MenuUnfoldOutlined } from '@ant-design/icons';
import { useModel, history, useLocation } from '@umijs/max';
import * as Icons from '@ant-design/icons';
import { useCollapsed, useConfig, useAsyncRouters, useAppStore } from '@/models';

const { Sider } = Layout;

interface MenuItem {
  name: string;
  path: string;
  hidden?: boolean;
  meta?: {
    title: string;
    icon?: string;
    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 NormalModeProps {
  /** Theme */
  theme?: 'light' | 'dark';
}

const NormalMode: React.FC<NormalModeProps> = ({ theme = 'dark' }) => {
  const location = useLocation();
  const collapsed = useCollapsed();
  const config = useConfig();
  const asyncRouters = useAsyncRouters();
  const { setCollapsed } = useAppStore();
  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;
    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;
    }

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

    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,
    });
  };

  const handleOpenChange = (keys: string[]) => {
    setOpenKeys(keys);
  };

  const toggleCollapse = () => {
    setCollapsed(!collapsed);
  };

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

  return (
    <Sider
      collapsible
      collapsed={collapsed}
      width={siderWidth}
      collapsedWidth={siderCollapsedWidth}
      theme={theme}
      trigger={null}
      style={{
        overflow: 'auto',
        height: '100%',
        position: 'relative',
      }}
    >
      <Menu
        theme={theme}
        mode="inline"
        selectedKeys={selectedKeys}
        openKeys={collapsed ? [] : openKeys}
        onOpenChange={handleOpenChange}
        onClick={handleMenuClick}
        items={menuItems}
        style={{ borderRight: 0, height: 'calc(100% - 48px)' }}
      />

      {/* Collapse Toggle Button */}
      <div
        onClick={toggleCollapse}
        style={{
          position: 'absolute',
          bottom: 16,
          left: '50%',
          transform: 'translateX(-50%)',
          width: 32,
          height: 32,
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
          backgroundColor: theme === 'dark' ? 'rgba(255,255,255,0.1)' : '#f5f5f5',
          borderRadius: 4,
          cursor: 'pointer',
          color: theme === 'dark' ? '#fff' : '#333',
        }}
      >
        {collapsed ? <MenuUnfoldOutlined /> : <MenuFoldOutlined />}
      </div>
    </Sider>
  );
};

export default NormalMode;
