export interface UniDeskTabDefinition {
  id: string;
  label: string;
  routeSegment?: string;
}

export interface UniDeskModuleDefinition {
  id: string;
  label: string;
  code: string;
  routeSegment?: string;
  tabs: UniDeskTabDefinition[];
}

export interface UniDeskRouteTarget {
  moduleId: string;
  tabId: string;
}

export interface UniDeskRoutedTabDefinition extends UniDeskTabDefinition {
  routeSegment: string;
  canonicalPath: string;
  aliases: string[];
}

export interface UniDeskRoutedModuleDefinition extends UniDeskModuleDefinition {
  routeSegment: string;
  canonicalPath: string;
  tabs: UniDeskRoutedTabDefinition[];
}

export interface UniDeskRouteRegistry {
  modules: UniDeskRoutedModuleDefinition[];
  moduleById: Record<string, UniDeskRoutedModuleDefinition>;
  defaultActiveTabs: Record<string, string>;
  routeMap: Record<string, UniDeskRouteTarget>;
  canonicalPathByTarget: Record<string, string>;
  fallbackTarget: UniDeskRouteTarget;
}

export const MODULES: UniDeskModuleDefinition[] = [
  { id: "ops", label: "运行总览", code: "OPS", tabs: [
    { id: "status", label: "态势总览" },
    { id: "performance", label: "性能面板" },
    { id: "events", label: "事件摘要" },
    { id: "logs", label: "服务日志" },
  ] },
  { id: "nodes", label: "资源节点", code: "NODE", tabs: [
    { id: "list", label: "节点清单" },
    { id: "monitor", label: "资源监控" },
    { id: "docker", label: "Docker 状态" },
    { id: "gateway", label: "网关版本" },
    { id: "labels", label: "资源标签" },
    { id: "heartbeats", label: "心跳状态" },
  ] },
  { id: "tasks", label: "任务调度", code: "TASK", tabs: [
    { id: "dispatch", label: "下发任务" },
    { id: "scheduled", label: "定时任务" },
    { id: "pending", label: "待处理任务" },
    { id: "history", label: "任务历史" },
    { id: "results", label: "执行结果" },
  ] },
  { id: "apps", label: "用户服务", code: "APP", routeSegment: "app", tabs: [
    { id: "catalog", label: "服务目录" },
    { id: "hwlab", label: "HWLAB" },
    { id: "todo-note", label: "Todo Note" },
    { id: "findjob", label: "FindJob" },
    { id: "pipeline", label: "Pipeline" },
    { id: "met-nonlinear", label: "MET Nonlinear" },
    { id: "claudeqq", label: "ClaudeQQ" },
    { id: "baidu-netdisk", label: "Baidu Netdisk" },
    { id: "filebrowser", label: "File Browser" },
    { id: "oa-event-flow", label: "OA Event Flow" },
    { id: "k3sctl", label: "k3s Control" },
    { id: "code-queue", label: "Code Queue" },
    { id: "mdtodo", label: "MDTODO" },
    { id: "decision-center", label: "Decision Center" },
    { id: "project-manager", label: "Project Manager" },
  ] },
  { id: "config", label: "系统配置", code: "CFG", tabs: [
    { id: "topology", label: "连接拓扑" },
    { id: "auth", label: "认证策略" },
    { id: "security", label: "安全边界" },
  ] },
];

export const DEFAULT_ACTIVE_TABS: Record<string, string> = Object.fromEntries(
  MODULES.map((module) => [module.id, module.tabs[0]?.id ?? ""]),
);

function normalizeDecodedSegment(segment: string): string {
  const trimmed = String(segment || "").trim();
  if (!trimmed) return "";
  try {
    return decodeURIComponent(trimmed);
  } catch {
    return trimmed;
  }
}

function normalizeRoutePath(pathname: string): string {
  const raw = String(pathname || "/");
  const [pathOnly] = raw.split(/[?#]/u, 1);
  if (pathOnly === "/") return "/";
  const segments = pathOnly.split("/").map(normalizeDecodedSegment).filter(Boolean);
  const joined = `/${segments.join("/")}`;
  return joined.endsWith("/") ? joined : `${joined}/`;
}

function hashText(value: string): string {
  let hash = 2166136261;
  for (const char of value) {
    hash ^= char.charCodeAt(0);
    hash = Math.imul(hash, 16777619);
  }
  return Math.abs(hash >>> 0).toString(36);
}

function asciiSlug(value: string): string {
  return String(value || "")
    .normalize("NFKD")
    .replace(/[\u0300-\u036f]/gu, "")
    .toLowerCase()
    .replace(/[^a-z0-9]+/gu, "-")
    .replace(/^-+|-+$/gu, "");
}

function unicodeSlug(value: string): string {
  return String(value || "")
    .trim()
    .toLowerCase()
    .replace(/[\s/\\?#%]+/gu, "-")
    .replace(/-+/gu, "-")
    .replace(/^-+|-+$/gu, "");
}

function routeSegmentFor(definition: { id?: string; label?: string; routeSegment?: string }): string {
  const explicit = asciiSlug(definition.routeSegment || "") || unicodeSlug(definition.routeSegment || "");
  if (explicit) return explicit;
  const stableId = asciiSlug(definition.id || "");
  if (stableId) return stableId;
  const readableLabel = asciiSlug(definition.label || "") || unicodeSlug(definition.label || "");
  if (readableLabel) return readableLabel;
  return `route-${hashText(JSON.stringify(definition))}`;
}

function targetKey(moduleId: string, tabId: string): string {
  return `${moduleId}:${tabId}`;
}

export function createRouteRegistry(definitions: UniDeskModuleDefinition[]): UniDeskRouteRegistry {
  const prebuiltModules = definitions.map((module) => {
    const routeSegment = routeSegmentFor(module);
    return {
      ...module,
      routeSegment,
      tabs: module.tabs.map((tab) => ({ ...tab, routeSegment: routeSegmentFor(tab) })),
    };
  });

  const routeMap: Record<string, UniDeskRouteTarget> = {};
  const canonicalPathByTarget: Record<string, string> = {};
  const defaultActiveTabs: Record<string, string> = {};
  const routedModules: UniDeskRoutedModuleDefinition[] = prebuiltModules.map((module) => {
    const defaultTabId = module.tabs[0]?.id ?? "";
    defaultActiveTabs[module.id] = defaultTabId;
    const routedTabs: UniDeskRoutedTabDefinition[] = module.tabs.map((tab) => {
      const canonicalPath = `/${module.routeSegment}/${tab.routeSegment}/`;
      const aliases = [canonicalPath];
      const target = { moduleId: module.id, tabId: tab.id };
      for (const alias of aliases) routeMap[normalizeRoutePath(alias)] = target;
      canonicalPathByTarget[targetKey(module.id, tab.id)] = canonicalPath;
      return { ...tab, canonicalPath, aliases };
    });
    const moduleCanonical = `/${module.routeSegment}/`;
    const defaultTarget = { moduleId: module.id, tabId: defaultTabId };
    routeMap[normalizeRoutePath(moduleCanonical)] = defaultTarget;
    return {
      ...module,
      routeSegment: module.routeSegment,
      canonicalPath: moduleCanonical,
      tabs: routedTabs,
    };
  });

  const fallbackModule = routedModules[0];
  const fallbackTarget = {
    moduleId: fallbackModule?.id || "",
    tabId: fallbackModule?.tabs[0]?.id || "",
  };

  routeMap["/"] = fallbackTarget;

  return {
    modules: routedModules,
    moduleById: Object.fromEntries(routedModules.map((module) => [module.id, module])),
    defaultActiveTabs,
    routeMap,
    canonicalPathByTarget,
    fallbackTarget,
  };
}

export function resolveRouteTarget(registry: UniDeskRouteRegistry, pathname: string): UniDeskRouteTarget {
  return registry.routeMap[normalizeRoutePath(pathname)] || registry.fallbackTarget;
}

export function pathForTarget(registry: UniDeskRouteRegistry, moduleId: string, tabId: string): string {
  return registry.canonicalPathByTarget[targetKey(moduleId, tabId)]
    || registry.canonicalPathByTarget[targetKey(registry.fallbackTarget.moduleId, registry.fallbackTarget.tabId)]
    || "/";
}

export function canonicalizeKnownRoute(registry: UniDeskRouteRegistry, pathname: string): string | null {
  const target = registry.routeMap[normalizeRoutePath(pathname)];
  if (!target) return null;
  return pathForTarget(registry, target.moduleId, target.tabId);
}
