import { h } from 'vue';
import store from '@/store';
import website from '@/config/website';
import { isURL } from './router';
import { formatPath } from './avue-router';

/**
 * 标签页键控体系
 *
 * 三档键控语义：
 * 1. 默认：以含参数的完整地址为键，地址不同（含参数不同）即独立标签、独立缓存
 * 2. meta.tabKey = 'path'：以纯路径为键，同路径不同参数复用同一标签，参数原位刷新，
 *    页面通过监听 $route.query 感知变化；菜单地址追加保留参数 _single=1 即启用
 * 3. meta.isTab = false：不纳入标签体系，视图原样透传，由容器页自行管理
 */

/**
 * 单标签模式的保留参数，仅作配置开关，不进入业务 query
 */
const SINGLE_TAB_PARAM = '_single';

/**
 * 拆分地址中的参数部分
 */
export function parsePathQuery(fullPath) {
  const splitIndex = fullPath.indexOf('?');
  if (splitIndex === -1) return { path: fullPath, query: {} };
  const query = {};
  new URLSearchParams(fullPath.slice(splitIndex + 1)).forEach((value, key) => {
    query[key] = value;
  });
  return { path: fullPath.slice(0, splitIndex), query };
}

/**
 * 菜单树归一化：把配置在地址中的参数拆入 query 字段
 * 组件解析与路由注册都依赖纯路径，须在 formatPath 之前执行
 */
export function normalizeMenu(menuList = []) {
  const props = website.menu;
  menuList.forEach(item => {
    const rawPath = item[props.path];
    if (rawPath && !isURL(rawPath) && rawPath.includes('?')) {
      const { path, query } = parsePathQuery(rawPath);
      item[props.path] = path;
      item[props.query] = { ...query, ...(item[props.query] || {}) };
    }
    if (item[props.children] && item[props.children].length) {
      normalizeMenu(item[props.children]);
    }
  });
}

/**
 * 标签键控元数据落位：识别保留参数并写入 meta
 * formatPath 会重建菜单的 meta 对象，须在其之后执行
 */
export function applyTabMeta(menuList = []) {
  const props = website.menu;
  menuList.forEach(item => {
    const query = item[props.query];
    if (query && query[SINGLE_TAB_PARAM] !== undefined) {
      delete query[SINGLE_TAB_PARAM];
      item.meta = item.meta || {};
      item.meta.tabKey = 'path';
    }
    if (item[props.children] && item[props.children].length) {
      applyTabMeta(item[props.children]);
    }
  });
}

/**
 * 菜单格式化入口：归一化 → 框架格式化 → 键控元数据落位
 */
export function formatMenu(menuList = []) {
  normalizeMenu(menuList);
  menuList.forEach(ele => formatPath(ele, true));
  applyTabMeta(menuList);
}

/**
 * 路由的标签键：决定标签归属与缓存粒度，不纳入标签体系时返回 null
 */
export function tabKeyOf(route) {
  const meta = route.meta || {};
  if (meta.isTab === false) return null;
  return meta.tabKey === 'path' ? route.path : route.fullPath;
}

/**
 * 视图代理组件池：以标签键命名代理组件，使 keep-alive 的缓存实例与
 * include 白名单都按标签粒度精确控制，同一页面组件开多个标签互不共享实例
 */
const wrapperMap = new Map();

let cleanupWatched = false;

/**
 * 标签关闭后回收对应代理组件，避免长期驻留
 */
function watchTagCleanup() {
  if (cleanupWatched) return;
  cleanupWatched = true;
  store.subscribe(mutation => {
    if (['DEL_TAG', 'DEL_ALL_TAG', 'DEL_TAG_OTHER'].includes(mutation.type)) {
      const alive = new Set(store.getters.tagList.map(tag => tag.fullPath));
      wrapperMap.forEach((wrapper, key) => {
        if (!alive.has(key)) wrapperMap.delete(key);
      });
    }
  });
}

/**
 * 主布局 router-view 的渲染入口
 */
export function tabView(route, Component) {
  if (!Component) return Component;
  const tabKey = tabKeyOf(route);
  if (!tabKey) return Component;
  watchTagCleanup();
  let wrapper = wrapperMap.get(tabKey);
  if (!wrapper) {
    wrapper = {
      name: tabKey,
      render: () => h(Component),
    };
    wrapperMap.set(tabKey, wrapper);
  }
  return h(wrapper);
}
