/**
 * KRA - Router Model (Zustand Store)
 * Dynamic route and menu management
 */
import { create } from 'zustand';
import { asyncRouterHandle, RouteConfig, MenuItem } from '@/utils/asyncRouter';

export interface TabItem {
  path: string;
  name: string;
  title: string;
  icon?: string;
  closable?: boolean;
}

interface RouterState {
  asyncRouters: RouteConfig[];
  routeMap: Record<string, RouteConfig>;
  keepAliveRouters: string[];
  asyncRouterFlag: number;
  topMenu: MenuItem[];
  leftMenu: MenuItem[];
  topActive: string;
  tabs: TabItem[];
  activeTab: string;
}

interface RouterActions {
  setAsyncRouters: (menus: MenuItem[]) => void;
  setTopActive: (name: string) => void;
  setLeftMenu: (name: string) => MenuItem[] | undefined;
  addKeepAlive: (name: string) => void;
  removeKeepAlive: (name: string) => void;
  setKeepAliveRouters: (tabs: TabItem[]) => void;
  addTab: (tab: TabItem) => void;
  removeTab: (path: string) => void;
  removeOtherTabs: (path: string) => void;
  removeAllTabs: () => void;
  setActiveTab: (path: string) => void;
  clearRoutes: () => void;
}

const formatRouter = (
  routes: MenuItem[],
  routeMap: Record<string, RouteConfig>,
  parent?: MenuItem
) => {
  routes?.forEach((item) => {
    const route: RouteConfig = {
      path: item.path,
      name: item.name,
      component: item.component,
      redirect: item.redirect,
      hideInMenu: item.hidden,
      meta: {
        title: item.meta?.title || item.name,
        icon: item.meta?.icon,
        keepAlive: item.meta?.keepAlive,
        defaultMenu: item.meta?.defaultMenu,
        closeTab: item.meta?.closeTab,
        parent: parent?.name,
      },
    };
    routeMap[item.name] = route;

    if (item.children && item.children.length > 0) {
      formatRouter(item.children, routeMap, item);
    }
  });
};

const extractKeepAlive = (routes: MenuItem[]): string[] => {
  const result: string[] = [];

  const traverse = (items: MenuItem[]) => {
    items?.forEach((item) => {
      if (item.meta?.keepAlive || item.children?.some((ch) => ch.meta?.keepAlive)) {
        result.push(item.name);
      }
      if (item.children && item.children.length > 0) {
        traverse(item.children);
      }
    });
  };

  traverse(routes);
  return result;
};

export const useRouterStore = create<RouterState & RouterActions>((set, get) => ({
  asyncRouters: [],
  routeMap: {},
  keepAliveRouters: [],
  asyncRouterFlag: 0,
  topMenu: [],
  leftMenu: [],
  topActive: '',
  tabs: [],
  activeTab: '',

  setAsyncRouters: (menus) => {
    const routeMap: Record<string, RouteConfig> = {};
    const menuMap: Record<string, MenuItem> = {};

    // Add reload route
    const asyncRouter = [
      ...menus,
      {
        path: 'reload',
        name: 'Reload',
        hidden: true,
        meta: { title: '', closeTab: true },
        component: 'pages/error/reload',
      },
    ];

    formatRouter(asyncRouter, routeMap);

    // Build base router structure
    const baseRouter: RouteConfig[] = [
      {
        path: '/',
        name: 'layout',
        component: 'layouts/BasicLayout',
        meta: { title: 'KRA Admin' },
        routes: asyncRouterHandle(asyncRouter),
      },
    ];

    // Extract top menu
    const topMenu: MenuItem[] = [];
    asyncRouter.forEach((item) => {
      if (!item.hidden) {
        menuMap[item.name] = item;
        topMenu.push({ ...item, children: [] });
      }
    });

    // Extract keep alive routes
    const keepAliveRouters = extractKeepAlive(asyncRouter);

    set({
      asyncRouters: baseRouter,
      routeMap,
      topMenu,
      keepAliveRouters,
      asyncRouterFlag: get().asyncRouterFlag + 1,
    });

    // Set initial left menu
    if (topMenu.length > 0) {
      const savedTopActive = sessionStorage.getItem('topActive');
      const initialTop = savedTopActive && menuMap[savedTopActive] ? savedTopActive : topMenu[0].name;
      get().setLeftMenu(initialTop);
    }
  },

  setTopActive: (name) => {
    sessionStorage.setItem('topActive', name);
    set({ topActive: name });
  },

  setLeftMenu: (name) => {
    const { topMenu } = get();
    const menuItem = topMenu.find((item) => item.name === name);

    sessionStorage.setItem('topActive', name);
    set({
      topActive: name,
      leftMenu: menuItem?.children || [],
    });

    return menuItem?.children;
  },

  addKeepAlive: (name) => {
    set((state) => {
      if (!state.keepAliveRouters.includes(name)) {
        return { keepAliveRouters: [...state.keepAliveRouters, name] };
      }
      return state;
    });
  },

  removeKeepAlive: (name) => {
    set((state) => ({
      keepAliveRouters: state.keepAliveRouters.filter((n) => n !== name),
    }));
  },

  setKeepAliveRouters: (tabs) => {
    const { routeMap, keepAliveRouters } = get();
    const keepArrTemp = [...keepAliveRouters];

    tabs.forEach((tab) => {
      const routeInfo = routeMap[tab.name];
      if (routeInfo?.meta?.keepAlive && !keepArrTemp.includes(tab.name)) {
        keepArrTemp.push(tab.name);
      }
    });

    set({ keepAliveRouters: [...new Set(keepArrTemp)] });
  },

  addTab: (tab) => {
    set((state) => {
      const exists = state.tabs.find((t) => t.path === tab.path);
      if (exists) {
        return { activeTab: tab.path };
      }
      return {
        tabs: [...state.tabs, tab],
        activeTab: tab.path,
      };
    });
  },

  removeTab: (path) => {
    set((state) => {
      const newTabs = state.tabs.filter((t) => t.path !== path);
      let newActiveTab = state.activeTab;

      if (state.activeTab === path && newTabs.length > 0) {
        const index = state.tabs.findIndex((t) => t.path === path);
        newActiveTab = newTabs[Math.min(index, newTabs.length - 1)]?.path || '';
      }

      return { tabs: newTabs, activeTab: newActiveTab };
    });
  },

  removeOtherTabs: (path) => {
    set((state) => ({
      tabs: state.tabs.filter((t) => t.path === path || !t.closable),
      activeTab: path,
    }));
  },

  removeAllTabs: () => {
    set((state) => ({
      tabs: state.tabs.filter((t) => !t.closable),
      activeTab: state.tabs.find((t) => !t.closable)?.path || '',
    }));
  },

  setActiveTab: (path) => {
    set({ activeTab: path });
  },

  clearRoutes: () => {
    set({
      asyncRouters: [],
      routeMap: {},
      keepAliveRouters: [],
      topMenu: [],
      leftMenu: [],
      topActive: '',
      tabs: [],
      activeTab: '',
    });
  },
}));

// Helper hooks
export const useAsyncRouters = () => useRouterStore((state) => state.asyncRouters);
export const useTabs = () => useRouterStore((state) => state.tabs);
export const useActiveTab = () => useRouterStore((state) => state.activeTab);
export const useTopMenu = () => useRouterStore((state) => state.topMenu);
export const useLeftMenu = () => useRouterStore((state) => state.leftMenu);

export default useRouterStore;
