import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { Outlet, useNavigate, useLocation } from 'react-router-dom';
import { Layout, Menu, Button, Avatar, Dropdown, Drawer, Grid } from 'antd';
import {
  DashboardOutlined,
  TeamOutlined,
  HomeOutlined,
  SwapOutlined,
  DollarOutlined,
  FileTextOutlined,
  LogoutOutlined,
  UserOutlined,
  MenuFoldOutlined,
  MenuUnfoldOutlined,
  AppstoreOutlined,
  AuditOutlined,
  SettingOutlined,
  WalletOutlined,
  ReadOutlined,
  TagsOutlined,
  FileProtectOutlined,
  CalendarOutlined,
  SafetyOutlined,
  KeyOutlined,
  CheckCircleOutlined,
  LaptopOutlined,
  BellOutlined,
  TrophyOutlined,
  ApiOutlined,
  RobotOutlined,
} from '@ant-design/icons';
import { usePermission } from '../hooks/usePermission';
import api from '../api';
import { writePermissions } from '../auth/permission-store';
import NotificationBell from '../components/NotificationBell';
import RouteDock from '../components/RouteDock';
import { buildMenu, type AppMenuItem } from '../auth/menu-policy';

const { Header, Sider, Content } = Layout;

const iconMap: Record<string, React.ReactNode> = {
  dashboard: <DashboardOutlined />,
  calendar: <CalendarOutlined />,
  workspace: <LaptopOutlined />,
  attendance: <CheckCircleOutlined />,
  academic: <TeamOutlined />,
  students: <TeamOutlined />,
  classes: <TeamOutlined />,
  teachers: <UserOutlined />,
  exam: <TrophyOutlined />,
  home: <HomeOutlined />,
  overview: <AppstoreOutlined />,
  occupancy: <SwapOutlined />,
  expense: <DollarOutlined />,
  bill: <FileTextOutlined />,
  deposit: <WalletOutlined />,
  wallet: <WalletOutlined />,
  classroom: <ReadOutlined />,
  rental: <FileProtectOutlined />,
  organization: <TagsOutlined />,
  settings: <SettingOutlined />,
  users: <UserOutlined />,
  role: <SafetyOutlined />,
  permission: <KeyOutlined />,
  log: <AuditOutlined />,
  integration: <ApiOutlined />,
  ai: <RobotOutlined />,
  notification: <BellOutlined />,
};

const MainLayout: React.FC = () => {
  const [collapsed, setCollapsed] = useState(false);
  const [drawerOpen, setDrawerOpen] = useState(false);
  const [openKeys, setOpenKeys] = useState<string[]>([]);
  const prevPathname = useRef('');
  const navigate = useNavigate();
  const location = useLocation();
  const [user, setUser] = useState<{ name?: string; username?: string; roles?: string[] }>(() =>
    JSON.parse(localStorage.getItem('user') || '{}'),
  );
  const { permissions, hasPermission } = usePermission();

  useEffect(() => {
    let cancelled = false;
    api
      .get<{ id: number; username: string; permissions: string[]; roles?: string[] }>(
        '/auth/profile',
      )
      .then((profile) => {
        if (cancelled) return;
        writePermissions(profile.permissions || []);
        const cachedUser = JSON.parse(localStorage.getItem('user') || '{}');
        const nextUser = { ...cachedUser, ...profile };
        localStorage.setItem('user', JSON.stringify(nextUser));
        setUser(nextUser);
      })
      .catch(() => {
        // The API interceptor handles expired/invalid sessions.
      });
    return () => {
      cancelled = true;
    };
  }, []);

  const screens = Grid.useBreakpoint();
  const isMobile = !screens.sm; // < 576px (仅 xs)
  const isTablet = (screens.sm || screens.md) && !screens.lg; // 576-991px
  const isDesktop = !!screens.lg; // >= 992px
  const usesDrawer = !isDesktop;

  const menuItems = useMemo(
    () => buildMenu(user.roles ?? [], permissions),
    [user.roles, permissions],
  );

  const handleLogout = useCallback(() => {
    localStorage.removeItem('token');
    localStorage.removeItem('user');
    localStorage.removeItem('permissions');
    navigate('/login');
  }, [navigate]);

  const handleMenuClick = useCallback(
    (key: string) => {
      navigate(key);
      if (usesDrawer) setDrawerOpen(false);
    },
    [navigate, usesDrawer],
  );

  const findSelectedKeys = (items: AppMenuItem[], pathname: string): string[] => {
    for (const item of items) {
      if (item.key === pathname) return [item.key];
      if (item.children) {
        const found = findSelectedKeys(item.children, pathname);
        if (found.length > 0) return found;
      }
    }
    return [pathname];
  };

  const findOpenKeys = (items: AppMenuItem[], pathname: string): string[] => {
    for (const item of items) {
      if (item.children) {
        if (
          item.children.some(
            (c) =>
              c.key === pathname || (c.children && c.children.some((gc) => gc.key === pathname)),
          )
        ) {
          return [item.key];
        }
      }
    }
    return [];
  };

  const selectedKeys = useMemo(
    () => findSelectedKeys(menuItems, location.pathname),
    [menuItems, location.pathname],
  );
  // 路径变化时同步展开的菜单（不干扰用户手动展开/收起）
  useEffect(() => {
    if (location.pathname !== prevPathname.current) {
      prevPathname.current = location.pathname;
      const routeOpenKeys = findOpenKeys(menuItems, location.pathname);
      setOpenKeys((currentKeys) => [...new Set([...currentKeys, ...routeOpenKeys])]);
    }
  }, [location.pathname, menuItems]);

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

  const transformToMenuItems = (items: AppMenuItem[]): any[] => {
    return items.map((item) => ({
      key: item.key,
      icon: item.icon ? iconMap[item.icon] : undefined,
      label: item.label,
      children: item.children ? transformToMenuItems(item.children) : undefined,
    }));
  };
  const menuContent = useMemo(
    () => (
      <Menu
        theme="light"
        mode="inline"
        selectedKeys={selectedKeys}
        openKeys={openKeys}
        onOpenChange={handleOpenChange}
        items={transformToMenuItems(menuItems)}
        onClick={({ key }) => handleMenuClick(key)}
        style={{ border: 'none' }}
      />
    ),
    [selectedKeys, openKeys, menuItems, handleMenuClick],
  );

  return (
    <Layout className="app-shell" style={{ minHeight: '100vh' }}>
      {isDesktop && (
        <Sider
          trigger={null}
          collapsible
          collapsed={collapsed}
          theme="light"
          className="app-sidebar"
          style={{ background: '#fff', borderRight: '1px solid #e5e5e7' }}
        >
          <div
            style={{
              height: 64,
              display: 'flex',
              alignItems: 'center',
              justifyContent: 'center',
              color: '#1d1d1f',
              fontSize: collapsed ? 16 : 17,
              fontWeight: 600,
              borderBottom: '1px solid #e5e5e7',
            }}
          >
            {collapsed ? '学' : '学生管理系统'}
          </div>
          {menuContent}
        </Sider>
      )}
      {usesDrawer && (
        <Drawer
          placement="left"
          open={drawerOpen}
          onClose={() => setDrawerOpen(false)}
          size={240}
          styles={{ body: { padding: 0 } }}
          className="app-navigation-drawer"
          title="学生管理系统"
        >
          {menuContent}
        </Drawer>
      )}
      <Layout className="app-main" style={{ background: '#f5f5f7' }}>
        <Header
          className="app-header"
          style={{
            padding: '0 16px',
            background: '#fff',
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'space-between',
            borderBottom: '1px solid #e5e5e7',
            boxShadow: 'none',
          }}
        >
          <Button
            type="text"
            aria-label={usesDrawer ? '打开菜单' : collapsed ? '展开侧边栏' : '收起侧边栏'}
            icon={
              usesDrawer ? (
                <MenuUnfoldOutlined />
              ) : collapsed ? (
                <MenuUnfoldOutlined />
              ) : (
                <MenuFoldOutlined />
              )
            }
            onClick={() => (usesDrawer ? setDrawerOpen(true) : setCollapsed(!collapsed))}
          />
          <div style={{ display: 'flex', alignItems: 'center', gap: 16 }}>
            {hasPermission('notification:view') && <NotificationBell />}
            <Dropdown
              menu={{
                items: [
                  {
                    key: 'logout',
                    icon: <LogoutOutlined />,
                    label: '退出登录',
                    onClick: handleLogout,
                  },
                ],
              }}
            >
              <div
                role="button"
                tabIndex={0}
                aria-label="用户菜单"
                style={{ cursor: 'pointer', display: 'flex', alignItems: 'center', gap: 8 }}
              >
                <Avatar icon={<UserOutlined />} />
                {isDesktop && <span>{user.name || user.username || '用户'}</span>}
              </div>
            </Dropdown>
          </div>
        </Header>
        <RouteDock
          location={location}
          menuItems={menuItems}
          onNavigate={navigate}
          draggable={isDesktop}
        />
        <Content
          className="app-content"
          style={{
            margin: isMobile ? 8 : isTablet ? 16 : 24,
            padding: isMobile ? 12 : isTablet ? 16 : 24,
            background: '#fff',
            borderRadius: 12,
          }}
        >
          <Outlet />
        </Content>
      </Layout>
    </Layout>
  );
};

export default MainLayout;
