import { useEffect, useMemo, useRef, useState, type FormEvent } from 'react';
import type {
  BaseModelCatalogItem,
  CatalogProvider,
  FileStorageChannel,
  FileStorageSettings,
  FileStorageSettingsUpdateRequest,
  FileStorageChannelUpsertRequest,
  GatewayAccessRuleBatchRequest,
  GatewayAccessRule,
  GatewayAccessRuleUpsertRequest,
  GatewayApiKey,
  GatewayAuditLog,
  GatewayNetworkProxyConfig,
  GatewayRunnerPolicy,
  GatewayTenantUpsertRequest,
  GatewayTask,
  GatewayUserUpsertRequest,
  GatewayTenant,
  GatewayUser,
  GatewayWalletAccount,
  GatewayWalletTransaction,
  IntegrationPlatform,
  ModelCatalogResponse,
  ModelRateLimitStatus,
  PlatformDynamicPriorityUpdateRequest,
  PlatformModel,
  PricingRule,
  PricingRuleSet,
  RateLimitWindow,
  RuntimePolicySet,
  UserGroupUpsertRequest,
  UserGroup,
  WalletBalanceAdjustmentRequest,
} from '@easyai-ai-gateway/contracts';
import {
  batchAccessRules,
  batchApiKeyAccessRules,
  createAccessRule,
  createApiKey,
  createFileStorageChannel,
  createGatewayUser,
  createPlatform,
  createTenant,
  createUserGroup,
  deleteAccessRule,
  deleteApiKey,
  deleteFileStorageChannel,
  deleteGatewayUser,
  deletePlatform,
  deleteTenant,
  deleteUserGroup,
  getHealth,
  listFileStorageChannels,
  getFileStorageSettings,
  getNetworkProxyConfig,
  getRunnerPolicy,
  getWalletSummary,
  listAccessRules,
  listAuditLogs,
  listApiKeyAccessRules,
  listApiKeys,
  listBaseModels,
  listCatalogProviders,
  listModelCatalog,
  listModelRateLimitStatuses,
  listModels,
  listPlayableApiKeys,
  listPlayableModels,
  listPlatforms,
  listPricingRules,
  listPricingRuleSets,
  listPublicBaseModels,
  listPublicCatalogProviders,
  listRuntimePolicySets,
  listTasks,
  listWalletTransactions,
  listRateLimitWindows,
  listTenants,
  listUserGroups,
  listUsers,
  loginLocalAccount,
  pollTaskUntilSettled,
  registerLocalAccount,
  replacePlatformModels,
  setUserWalletBalance,
  type HealthResponse,
  updateAccessRule,
  updateFileStorageChannel,
  updateFileStorageSettings,
  updateGatewayUser,
  updatePlatform,
  updatePlatformDynamicPriority,
  updateTenant,
  updateUserGroup,
} from './api';
import type { ConsoleData, StatItem } from './app-state';
import { AppShell } from './components/layout/AppShell';
import { LoginRequiredPanel } from './components/LoginRequiredPanel';
import { useCatalogOperations } from './hooks/useCatalogOperations';
import { usePricingRuleSetOperations } from './hooks/usePricingRuleSetOperations';
import { useRuntimePolicySetOperations } from './hooks/useRuntimePolicySetOperations';
import { persistAccessToken, readStoredAccessToken } from './lib/auth-storage';
import { runTask } from './lib/run-task';
import { AdminPage } from './pages/AdminPage';
import { ApiDocsPage } from './pages/ApiDocsPage';
import { HomePage } from './pages/HomePage';
import { ModelsPage } from './pages/ModelsPage';
import { PlaygroundPage } from './pages/PlaygroundPage';
import { WorkspacePage } from './pages/WorkspacePage';
import {
  parseAppRoute,
  pathForAdminSection,
  pathForApiDocSection,
  pathForPage,
  pathForPlaygroundMode,
  pathForWorkspaceSection,
  pathForWorkspaceTaskQuery,
  workspaceTaskQueryKey,
  type AppRouteState,
} from './routing';
import type {
  AdminSection,
  ApiDocSection,
  ApiKeyForm,
  AuthMode,
  LoadState,
  LoginForm,
  PageKey,
  PlaygroundMode,
  PlatformCreateInput,
  PlatformModelBindingInput,
  PlatformWithModelsInput,
  RegisterForm,
  TaskForm,
  WorkspaceTaskQuery,
  WorkspaceTransactionQuery,
  WorkspaceSection,
} from './types';

type DataKey =
  | 'health'
  | 'publicCatalog'
  | 'playgroundApiKeys'
  | 'playgroundModels'
  | 'modelCatalog'
  | 'networkProxyConfig'
  | 'fileStorageChannels'
  | 'fileStorageSettings'
  | 'platforms'
  | 'models'
  | 'providers'
  | 'baseModels'
  | 'pricingRules'
  | 'pricingRuleSets'
  | 'runnerPolicy'
  | 'runtimePolicySets'
  | 'rateLimitWindows'
  | 'modelRateLimits'
  | 'tenants'
  | 'users'
  | 'userGroups'
  | 'tasks'
  | 'wallet'
  | 'walletTransactions'
  | 'accessRules'
  | 'auditLogs'
  | 'apiKeys';

export function App() {
  const initialRoute = parseAppRoute();
  const [activePage, setActivePage] = useState<PageKey>(initialRoute.activePage);
  const [adminSection, setAdminSection] = useState<AdminSection>(initialRoute.adminSection);
  const [workspaceSection, setWorkspaceSection] = useState<WorkspaceSection>(initialRoute.workspaceSection);
  const [workspaceTaskQuery, setWorkspaceTaskQuery] = useState<WorkspaceTaskQuery>(initialRoute.workspaceTaskQuery);
  const [workspaceTransactionQuery, setWorkspaceTransactionQuery] = useState<WorkspaceTransactionQuery>(() => defaultWorkspaceTransactionQuery());
  const [apiDocSection, setApiDocSection] = useState<ApiDocSection>(initialRoute.apiDocSection);
  const [playgroundMode, setPlaygroundMode] = useState<PlaygroundMode>(initialRoute.playgroundMode);
  const [token, setToken] = useState(readStoredAccessToken);
  const [externalToken, setExternalToken] = useState('');
  const [authMode, setAuthMode] = useState<AuthMode>('login');
  const [loginForm, setLoginForm] = useState<LoginForm>({ account: '', password: '' });
  const [registerForm, setRegisterForm] = useState<RegisterForm>({ username: '', email: '', password: '', displayName: '', invitationCode: '' });
  const [health, setHealth] = useState<HealthResponse | null>(null);
  const [platforms, setPlatforms] = useState<IntegrationPlatform[]>([]);
  const [models, setModels] = useState<PlatformModel[]>([]);
  const [modelCatalog, setModelCatalog] = useState<ModelCatalogResponse>({
    items: [],
    filters: { capabilities: [], providers: [] },
    summary: { modelCount: 0, sourceCount: 0 },
  });
  const [playgroundModels, setPlaygroundModels] = useState<PlatformModel[]>([]);
  const [networkProxyConfig, setNetworkProxyConfig] = useState<GatewayNetworkProxyConfig | null>(null);
  const [fileStorageChannels, setFileStorageChannels] = useState<FileStorageChannel[]>([]);
  const [fileStorageSettings, setFileStorageSettings] = useState<FileStorageSettings | null>(null);
  const [providers, setProviders] = useState<CatalogProvider[]>([]);
  const [baseModels, setBaseModels] = useState<BaseModelCatalogItem[]>([]);
  const [pricingRules, setPricingRules] = useState<PricingRule[]>([]);
  const [pricingRuleSets, setPricingRuleSets] = useState<PricingRuleSet[]>([]);
  const [runnerPolicy, setRunnerPolicy] = useState<GatewayRunnerPolicy | null>(null);
  const [runtimePolicySets, setRuntimePolicySets] = useState<RuntimePolicySet[]>([]);
  const [accessRules, setAccessRules] = useState<GatewayAccessRule[]>([]);
  const [auditLogs, setAuditLogs] = useState<GatewayAuditLog[]>([]);
  const [rateLimitWindows, setRateLimitWindows] = useState<RateLimitWindow[]>([]);
  const [modelRateLimits, setModelRateLimits] = useState<ModelRateLimitStatus[]>([]);
  const [modelRateLimitsUpdatedAt, setModelRateLimitsUpdatedAt] = useState<number | null>(null);
  const [tenants, setTenants] = useState<GatewayTenant[]>([]);
  const [users, setUsers] = useState<GatewayUser[]>([]);
  const [userGroups, setUserGroups] = useState<UserGroup[]>([]);
  const [apiKeys, setApiKeys] = useState<GatewayApiKey[]>([]);
  const [apiKeyForm, setApiKeyForm] = useState<ApiKeyForm>({ name: 'Local smoke key', expiresAt: '' });
  const [apiKeySecret, setApiKeySecret] = useState('');
  const [apiKeySecretsById, setApiKeySecretsById] = useState<Record<string, string>>({});
  const [selectedPlaygroundApiKeyId, setSelectedPlaygroundApiKeyId] = useState('');
  const [taskForm, setTaskForm] = useState<TaskForm>({ kind: 'chat.completions', model: 'gpt-4o-mini', prompt: '用一句话确认 AI Gateway simulation 链路正常。' });
  const [taskResult, setTaskResult] = useState<GatewayTask | null>(null);
  const [tasks, setTasks] = useState<GatewayTask[]>([]);
  const [taskTotal, setTaskTotal] = useState(0);
  const [walletAccounts, setWalletAccounts] = useState<GatewayWalletAccount[]>([]);
  const [walletTransactions, setWalletTransactions] = useState<GatewayWalletTransaction[]>([]);
  const [walletTransactionTotal, setWalletTransactionTotal] = useState(0);
  const [coreState, setCoreState] = useState<LoadState>('idle');
  const [coreMessage, setCoreMessage] = useState('');
  const [state, setState] = useState<LoadState>('idle');
  const [error, setError] = useState('');
  const loadedDataKeysRef = useRef(new Set<DataKey>());
  const loadingDataKeysRef = useRef(new Set<DataKey>());
  const loadedTaskQueryKeyRef = useRef('');
  const currentTaskQueryKeyRef = useRef('');
  const loadedTransactionQueryKeyRef = useRef('');
  const currentTransactionQueryKeyRef = useRef('');
  const { removeBaseModel, removeProvider, resetAllBaseModelsToDefault, resetBaseModelToDefault, saveBaseModel, saveProvider } = useCatalogOperations({
    setBaseModels,
    setCoreMessage,
    setCoreState,
    setProviders,
    token,
  });
  const { removePricingRuleSet, savePricingRuleSet } = usePricingRuleSetOperations({
    setCoreMessage,
    setCoreState,
    setPricingRuleSets,
    token,
  });
  const { removeRuntimePolicySet, saveRunnerPolicy, saveRuntimePolicySet } = useRuntimePolicySetOperations({
    setCoreMessage,
    setCoreState,
    setRunnerPolicy,
    setRuntimePolicySets,
    token,
  });
  const taskListRequestKey = workspaceTaskQueryKey(workspaceTaskQuery);
  const transactionListRequestKey = workspaceTransactionQueryKey(workspaceTransactionQuery);
  currentTaskQueryKeyRef.current = taskListRequestKey;
  currentTransactionQueryKeyRef.current = transactionListRequestKey;

  useEffect(() => {
    void ensureData(['health']);
  }, []);
  useEffect(() => {
    void ensureRouteData(token);
  }, [activePage, adminSection, taskListRequestKey, transactionListRequestKey, workspaceSection, token]);
  useEffect(() => {
    if (!token || activePage !== 'admin' || adminSection !== 'realtimeLoad') return undefined;
    const timer = window.setInterval(() => {
      void Promise.all([listModelRateLimitStatuses(token), listPlatforms(token)])
        .then(([rateLimitResponse, platformResponse]) => {
          setModelRateLimits(rateLimitResponse.items);
          setModelRateLimitsUpdatedAt(Date.now());
          setPlatforms(platformResponse.items);
          loadedDataKeysRef.current.add('modelRateLimits');
          loadedDataKeysRef.current.add('platforms');
        })
        .catch(() => {
          loadedDataKeysRef.current.delete('modelRateLimits');
          loadedDataKeysRef.current.delete('platforms');
        });
    }, 3000);
    return () => window.clearInterval(timer);
  }, [activePage, adminSection, token]);
  useEffect(() => {
    function handlePopState() {
      applyRoute(parseAppRoute());
    }
    window.addEventListener('popstate', handlePopState);
    return () => window.removeEventListener('popstate', handlePopState);
  }, []);
  const stats = useMemo<StatItem[]>(() => {
    const enabledPlatforms = platforms.filter((item) => item.status === 'enabled').length;
    const enabledModels = models.filter((item) => item.enabled).length;
    const activeProviders = providers.filter((item) => item.status === 'active').length;
    const activeRateWindows = rateLimitWindows.filter((item) => item.resetAt >= new Date().toISOString()).length;
    return [
      { label: '租户', value: tenants.length, tone: 'cyan' },
      { label: '用户', value: users.length, tone: 'green' },
      { label: '用户组', value: userGroups.length, tone: 'blue' },
      { label: '平台', value: platforms.length, tone: 'blue' },
      { label: '启用平台', value: enabledPlatforms, tone: 'green' },
      { label: '平台模型', value: enabledModels, tone: 'violet' },
      { label: 'Provider', value: activeProviders || providers.length, tone: 'amber' },
      { label: '定价规则', value: pricingRules.length, tone: 'cyan' },
      { label: '运行策略', value: runtimePolicySets.length, tone: 'slate' },
      { label: '访问规则', value: accessRules.length, tone: 'amber' },
      { label: '限流窗口', value: activeRateWindows, tone: 'rose' },
    ];
  }, [accessRules.length, models, platforms, pricingRules.length, providers, rateLimitWindows, runtimePolicySets.length, tenants.length, userGroups.length, users.length]);

  const data = useMemo<ConsoleData>(() => ({
    accessRules,
    auditLogs,
    apiKeys,
    baseModels,
    fileStorageChannels,
    fileStorageSettings,
    modelCatalog,
    models,
    networkProxyConfig,
    runnerPolicy,
    platforms,
    pricingRules,
    pricingRuleSets,
    providers,
    rateLimitWindows,
    modelRateLimits,
    modelRateLimitsUpdatedAt,
    runtimePolicySets,
    taskResult,
    tasks,
    tenants,
    userGroups,
    users,
    walletAccounts,
    walletTransactions,
  }), [accessRules, apiKeys, auditLogs, baseModels, fileStorageChannels, fileStorageSettings, modelCatalog, modelRateLimits, modelRateLimitsUpdatedAt, models, networkProxyConfig, platforms, pricingRuleSets, pricingRules, providers, rateLimitWindows, runnerPolicy, runtimePolicySets, taskResult, tasks, tenants, userGroups, users, walletAccounts, walletTransactions]);

  async function refresh(nextToken = token) {
    await ensureRouteData(nextToken, true);
  }

  function invalidateDataKeys(...keys: DataKey[]) {
    keys.forEach((key) => loadedDataKeysRef.current.delete(key));
  }

  async function ensureRouteData(nextToken = token, force = false) {
    if (activePage === 'workspace' && workspaceSection === 'tasks' && loadedTaskQueryKeyRef.current !== taskListRequestKey) {
      loadedDataKeysRef.current.delete('tasks');
      loadingDataKeysRef.current.delete('tasks');
    }
    if (activePage === 'workspace' && workspaceSection === 'transactions' && loadedTransactionQueryKeyRef.current !== transactionListRequestKey) {
      loadedDataKeysRef.current.delete('walletTransactions');
      loadingDataKeysRef.current.delete('walletTransactions');
    }
    await ensureData(dataKeysForRoute(activePage, adminSection, workspaceSection, Boolean(nextToken)), nextToken, force);
  }

  async function ensureData(keys: DataKey[], nextToken = token, force = false) {
    const uniqueKeys = Array.from(new Set(keys));
    const requestKeys = uniqueKeys.filter((key) => {
      if (!force && loadedDataKeysRef.current.has(key)) return false;
      if (loadingDataKeysRef.current.has(key)) return false;
      return key === 'health' || key === 'publicCatalog' || Boolean(nextToken);
    });
    if (requestKeys.length === 0) return;

    requestKeys.forEach((key) => loadingDataKeysRef.current.add(key));
    setState('loading');
    setError('');
    try {
      await Promise.all(requestKeys.map((key) => loadDataKey(key, nextToken)));
      requestKeys.forEach((key) => loadedDataKeysRef.current.add(key));
      setState('ready');
    } catch (err) {
      setState('error');
      setError(err instanceof Error ? err.message : '加载失败');
    } finally {
      requestKeys.forEach((key) => loadingDataKeysRef.current.delete(key));
    }
  }

  async function loadDataKey(key: DataKey, nextToken: string) {
    switch (key) {
      case 'health': {
        setHealth(await getHealth());
        return;
      }
      case 'publicCatalog': {
        const [providersResult, baseModelsResult] = await Promise.all([
          listPublicCatalogProviders(),
          listPublicBaseModels(),
        ]);
        setProviders(providersResult.items);
        setBaseModels(baseModelsResult.items);
        return;
      }
      case 'platforms':
        setPlatforms((await listPlatforms(nextToken)).items);
        return;
      case 'models':
        setModels((await listModels(nextToken)).items);
        return;
      case 'modelCatalog':
        setModelCatalog(await listModelCatalog(nextToken));
        return;
      case 'networkProxyConfig':
        setNetworkProxyConfig(await getNetworkProxyConfig(nextToken));
        return;
      case 'fileStorageChannels':
        setFileStorageChannels((await listFileStorageChannels(nextToken)).items);
        return;
      case 'fileStorageSettings':
        setFileStorageSettings(await getFileStorageSettings(nextToken));
        return;
      case 'playgroundModels':
        setPlaygroundModels((await listPlayableModels(nextToken)).items);
        return;
      case 'playgroundApiKeys': {
        const response = await listPlayableApiKeys(nextToken);
        setApiKeys(response.items);
        setApiKeySecretsById(Object.fromEntries(response.items.map((item) => [item.id, item.secret])));
        setSelectedPlaygroundApiKeyId((current) => current && response.items.some((item) => item.id === current) ? current : response.items[0]?.id ?? '');
        return;
      }
      case 'providers':
        setProviders((await listCatalogProviders(nextToken)).items);
        return;
      case 'baseModels':
        setBaseModels((await listBaseModels(nextToken)).items);
        return;
      case 'pricingRules':
        setPricingRules((await listPricingRules(nextToken)).items);
        return;
      case 'pricingRuleSets':
        setPricingRuleSets((await listPricingRuleSets(nextToken)).items);
        return;
      case 'runnerPolicy':
        setRunnerPolicy(await getRunnerPolicy(nextToken));
        return;
      case 'runtimePolicySets':
        setRuntimePolicySets((await listRuntimePolicySets(nextToken)).items);
        return;
      case 'rateLimitWindows':
        setRateLimitWindows((await listRateLimitWindows(nextToken)).items);
        return;
      case 'modelRateLimits':
        {
          const response = await listModelRateLimitStatuses(nextToken);
          setModelRateLimits(response.items);
          setModelRateLimitsUpdatedAt(Date.now());
        }
        return;
      case 'tenants':
        setTenants((await listTenants(nextToken)).items);
        return;
      case 'users':
        setUsers((await listUsers(nextToken)).items);
        return;
      case 'userGroups':
        setUserGroups((await listUserGroups(nextToken)).items);
        return;
      case 'tasks':
        {
          const requestKey = taskListRequestKey;
          const response = await listTasks(nextToken, workspaceTaskQuery);
          if (requestKey !== currentTaskQueryKeyRef.current) return;
          setTasks(response.items);
          setTaskTotal(response.total ?? response.items.length);
          loadedTaskQueryKeyRef.current = requestKey;
        }
        return;
      case 'wallet': {
        const response = await getWalletSummary(nextToken);
        setWalletAccounts(response.accounts);
        return;
      }
      case 'walletTransactions': {
        const requestKey = transactionListRequestKey;
        const response = await listWalletTransactions(nextToken, { ...normalizeWorkspaceTransactionQuery(workspaceTransactionQuery), direction: 'debit' });
        if (requestKey !== currentTransactionQueryKeyRef.current) return;
        setWalletTransactions(response.items);
        setWalletTransactionTotal(response.total ?? response.items.length);
        loadedTransactionQueryKeyRef.current = requestKey;
        return;
      }
      case 'accessRules':
        setAccessRules((await (activePage === 'workspace' && workspaceSection === 'apiKeys'
          ? listApiKeyAccessRules(nextToken)
          : listAccessRules(nextToken))).items);
        return;
      case 'auditLogs':
        setAuditLogs((await listAuditLogs(nextToken)).items);
        return;
      case 'apiKeys':
        setApiKeys((await listApiKeys(nextToken)).items);
    }
  }

  async function submitLogin(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    await authenticate(() => loginLocalAccount(loginForm), '登录失败');
  }

  async function submitRegister(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    await authenticate(() => registerLocalAccount(registerForm), '注册失败');
  }

  async function submitExternalToken(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    const nextToken = externalToken.trim();
    if (!nextToken) {
      setError('请填写 access token');
      return;
    }
    persistAccessToken(nextToken);
    setToken(nextToken);
    await ensureRouteData(nextToken, true);
  }

  async function authenticate(request: () => Promise<{ accessToken: string }>, fallback: string) {
    setState('loading');
    setError('');
    try {
      const response = await request();
      persistAccessToken(response.accessToken);
      setToken(response.accessToken);
      await ensureRouteData(response.accessToken, true);
    } catch (err) {
      setState('error');
      setError(err instanceof Error ? err.message : fallback);
    }
  }

  async function submitAPIKey(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    setCoreState('loading');
    setCoreMessage('');
    try {
      const response = await createApiKey(token, {
        name: apiKeyForm.name,
        scopes: ['chat', 'image', 'video'],
        expiresAt: apiKeyForm.expiresAt ? new Date(apiKeyForm.expiresAt).toISOString() : undefined,
      });
      setApiKeySecret(response.secret);
      setApiKeySecretsById((current) => ({ ...current, [response.apiKey.id]: response.secret }));
      setSelectedPlaygroundApiKeyId(response.apiKey.id);
      setApiKeys((current) => [response.apiKey, ...current.filter((item) => item.id !== response.apiKey.id)]);
      setApiKeyForm({ name: '', expiresAt: '' });
      setCoreState('ready');
      setCoreMessage('API Key 已创建，secret 仅展示一次。');
    } catch (err) {
      setCoreState('error');
      setCoreMessage(err instanceof Error ? err.message : '创建 API Key 失败');
      throw err;
    }
  }

  async function savePlatformWithModels(input: PlatformWithModelsInput) {
    setCoreState('loading');
    setCoreMessage('');
    try {
      const platform = input.platformId
        ? await updatePlatform(token, input.platformId, input.platform)
        : await createPlatform(token, input.platform);
      const platformForState = withCredentialPreviewFallback(
        platform,
        input.platform,
        input.platformId ? platforms.find((item) => item.id === input.platformId) : undefined,
      );
      const modelBindings = input.models.map((modelInput) => mergeExistingPlatformModelInput(modelInput, models, platform.id));
      const modelsResponse = await replacePlatformModels(token, platform.id, modelBindings);
      setPlatforms((current) => [platformForState, ...current.filter((item) => item.id !== platform.id)]);
      setModels((current) => [...current.filter((model) => model.platformId !== platform.id), ...modelsResponse.items]);
      invalidateDataKeys('modelCatalog', 'modelRateLimits');
      setCoreState('ready');
      setCoreMessage(input.platformId
        ? `平台已更新，当前绑定 ${input.models.length} 个模型。`
        : `平台已创建，已绑定 ${input.models.length} 个模型。`);
    } catch (err) {
      setCoreState('error');
      setCoreMessage(err instanceof Error ? err.message : input.platformId ? '更新平台失败' : '创建平台失败');
      throw err;
    }
  }

  async function savePlatformStatus(platform: IntegrationPlatform, status: 'enabled' | 'disabled') {
    setCoreState('loading');
    setCoreMessage('');
    try {
      const input = platformStatusUpdatePayload(platform, status);
      const updated = await updatePlatform(token, platform.id, input);
      const platformForState = withCredentialPreviewFallback(updated, input, platform);
      setPlatforms((current) => current.map((item) => item.id === platform.id ? platformForState : item));
      invalidateDataKeys('modelCatalog', 'modelRateLimits', 'playgroundModels');
      setCoreState('ready');
      setCoreMessage(status === 'enabled' ? '平台已启用。' : '平台已禁用。');
    } catch (err) {
      setCoreState('error');
      setCoreMessage(err instanceof Error ? err.message : '切换平台状态失败');
      throw err;
    }
  }

  async function savePlatformDynamicPriority(platformId: string, input: PlatformDynamicPriorityUpdateRequest) {
    setCoreState('loading');
    setCoreMessage('');
    try {
      const state = await updatePlatformDynamicPriority(token, platformId, input);
      setPlatforms((current) => current.map((platform) => platform.id === platformId
        ? {
            ...platform,
            dynamicPriority: state.dynamicPriority,
            effectivePriority: state.effectivePriority,
            priority: state.priority,
            updatedAt: state.updatedAt,
          }
        : platform));
      setModelRateLimits((current) => current.map((status) => status.platformId === platformId
        ? {
            ...status,
            platformDynamicPriority: state.dynamicPriority,
            platformEffectivePriority: state.effectivePriority,
            platformPriority: state.priority,
          }
        : status));
      invalidateDataKeys('modelCatalog', 'modelRateLimits', 'platforms', 'playgroundModels');
      setCoreState('ready');
      setCoreMessage(input.reset ? '平台动态优先级已重置。' : '平台动态优先级已更新。');
    } catch (err) {
      setCoreState('error');
      setCoreMessage(err instanceof Error ? err.message : '更新平台动态优先级失败');
      throw err;
    }
  }

  async function removePlatform(platformId: string) {
    setCoreState('loading');
    setCoreMessage('');
    try {
      await deletePlatform(token, platformId);
      setPlatforms((current) => current.filter((item) => item.id !== platformId));
      setModels((current) => current.filter((item) => item.platformId !== platformId));
      invalidateDataKeys('modelCatalog', 'modelRateLimits');
      setCoreState('ready');
      setCoreMessage('平台已删除。');
    } catch (err) {
      setCoreState('error');
      setCoreMessage(err instanceof Error ? err.message : '删除平台失败');
      throw err;
    }
  }

  async function saveTenant(input: GatewayTenantUpsertRequest, tenantId?: string) {
    setCoreState('loading');
    setCoreMessage('');
    try {
      const item = tenantId ? await updateTenant(token, tenantId, input) : await createTenant(token, input);
      setTenants((current) => [item, ...current.filter((tenant) => tenant.id !== item.id)]);
      setCoreState('ready');
      setCoreMessage(tenantId ? '租户已更新。' : '租户已创建。');
    } catch (err) {
      setCoreState('error');
      setCoreMessage(err instanceof Error ? err.message : tenantId ? '更新租户失败' : '创建租户失败');
      throw err;
    }
  }

  async function removeTenant(tenantId: string) {
    setCoreState('loading');
    setCoreMessage('');
    try {
      await deleteTenant(token, tenantId);
      setTenants((current) => current.filter((tenant) => tenant.id !== tenantId));
      setCoreState('ready');
      setCoreMessage('租户已删除。');
    } catch (err) {
      setCoreState('error');
      setCoreMessage(err instanceof Error ? err.message : '删除租户失败');
      throw err;
    }
  }

  async function saveUser(input: GatewayUserUpsertRequest, userId?: string) {
    setCoreState('loading');
    setCoreMessage('');
    try {
      const item = userId ? await updateGatewayUser(token, userId, input) : await createGatewayUser(token, input);
      setUsers((current) => [item, ...current.filter((user) => user.id !== item.id)]);
      invalidateDataKeys('playgroundModels');
      setCoreState('ready');
      setCoreMessage(userId ? '用户已更新。' : '用户已创建。');
    } catch (err) {
      setCoreState('error');
      setCoreMessage(err instanceof Error ? err.message : userId ? '更新用户失败' : '创建用户失败');
      throw err;
    }
  }

  async function saveUserWalletBalance(userId: string, input: WalletBalanceAdjustmentRequest) {
    setCoreState('loading');
    setCoreMessage('');
    try {
      const response = await setUserWalletBalance(token, userId, input);
      setUsers((current) => current.map((user) => user.id === userId
        ? {
            ...user,
            walletAccounts: [
              response.account,
              ...(user.walletAccounts ?? []).filter((account) => account.id !== response.account.id),
            ],
          }
        : user));
      setAuditLogs((current) => [response.auditLog, ...current.filter((item) => item.id !== response.auditLog.id)]);
      invalidateDataKeys('auditLogs');
      setCoreState('ready');
      setCoreMessage('用户余额已更新，审计日志已记录。');
    } catch (err) {
      setCoreState('error');
      setCoreMessage(err instanceof Error ? err.message : '更新用户余额失败');
      throw err;
    }
  }

  async function removeUser(userId: string) {
    setCoreState('loading');
    setCoreMessage('');
    try {
      await deleteGatewayUser(token, userId);
      setUsers((current) => current.filter((user) => user.id !== userId));
      setCoreState('ready');
      setCoreMessage('用户已删除。');
    } catch (err) {
      setCoreState('error');
      setCoreMessage(err instanceof Error ? err.message : '删除用户失败');
      throw err;
    }
  }

  async function saveUserGroup(input: UserGroupUpsertRequest, groupId?: string) {
    setCoreState('loading');
    setCoreMessage('');
    try {
      const item = groupId ? await updateUserGroup(token, groupId, input) : await createUserGroup(token, input);
      setUserGroups((current) => [item, ...current.filter((group) => group.id !== item.id)]);
      invalidateDataKeys('modelCatalog');
      setCoreState('ready');
      setCoreMessage(groupId ? '用户组已更新。' : '用户组已创建。');
    } catch (err) {
      setCoreState('error');
      setCoreMessage(err instanceof Error ? err.message : groupId ? '更新用户组失败' : '创建用户组失败');
      throw err;
    }
  }

  async function removeUserGroup(groupId: string) {
    setCoreState('loading');
    setCoreMessage('');
    try {
      await deleteUserGroup(token, groupId);
      setUserGroups((current) => current.filter((group) => group.id !== groupId));
      setTenants((current) => current.map((tenant) => tenant.defaultUserGroupId === groupId ? { ...tenant, defaultUserGroupId: undefined } : tenant));
      setUsers((current) => current.map((user) => user.defaultUserGroupId === groupId ? { ...user, defaultUserGroupId: undefined } : user));
      invalidateDataKeys('modelCatalog');
      invalidateDataKeys('playgroundModels');
      setCoreState('ready');
      setCoreMessage('用户组已删除。');
    } catch (err) {
      setCoreState('error');
      setCoreMessage(err instanceof Error ? err.message : '删除用户组失败');
      throw err;
    }
  }

  async function removeAPIKey(apiKeyId: string) {
    setCoreState('loading');
    setCoreMessage('');
    try {
      await deleteApiKey(token, apiKeyId);
      setApiKeys((current) => current.filter((item) => item.id !== apiKeyId));
      setAccessRules((current) => current.filter((rule) => !(rule.subjectType === 'api_key' && rule.subjectId === apiKeyId)));
      setApiKeySecretsById((current) => {
        const next = { ...current };
        delete next[apiKeyId];
        return next;
      });
      if (selectedPlaygroundApiKeyId === apiKeyId) setSelectedPlaygroundApiKeyId('');
      setCoreState('ready');
      setCoreMessage('API Key 已删除，对应权限策略已同步清理。');
    } catch (err) {
      setCoreState('error');
      setCoreMessage(err instanceof Error ? err.message : '删除 API Key 失败');
      throw err;
    }
  }

  async function saveAccessRule(input: GatewayAccessRuleUpsertRequest, ruleId?: string) {
    setCoreState('loading');
    setCoreMessage('');
    try {
      const item = ruleId ? await updateAccessRule(token, ruleId, input) : await createAccessRule(token, input);
      setAccessRules((current) => [item, ...current.filter((rule) => rule.id !== item.id)]);
      invalidateDataKeys('playgroundModels', 'modelCatalog');
      setCoreState('ready');
      setCoreMessage(ruleId ? '访问权限规则已更新。' : '访问权限规则已创建。');
    } catch (err) {
      setCoreState('error');
      setCoreMessage(err instanceof Error ? err.message : ruleId ? '更新访问权限失败' : '创建访问权限失败');
      throw err;
    }
  }

  async function removeAccessRule(ruleId: string) {
    setCoreState('loading');
    setCoreMessage('');
    try {
      await deleteAccessRule(token, ruleId);
      setAccessRules((current) => current.filter((rule) => rule.id !== ruleId));
      invalidateDataKeys('playgroundModels', 'modelCatalog');
      setCoreState('ready');
      setCoreMessage('访问权限规则已删除。');
    } catch (err) {
      setCoreState('error');
      setCoreMessage(err instanceof Error ? err.message : '删除访问权限失败');
      throw err;
    }
  }

  async function batchSaveAccessRules(input: GatewayAccessRuleBatchRequest) {
    setCoreState('loading');
    setCoreMessage('');
    try {
      const response = await batchAccessRules(token, input);
      setAccessRules(response.items);
      invalidateDataKeys('playgroundModels', 'modelCatalog');
      setCoreState('ready');
      setCoreMessage('访问权限已更新。');
    } catch (err) {
      setCoreState('error');
      setCoreMessage(err instanceof Error ? err.message : '批量更新访问权限失败');
      throw err;
    }
  }

  async function saveFileStorageChannel(input: FileStorageChannelUpsertRequest, channelId?: string) {
    setCoreState('loading');
    setCoreMessage('');
    try {
      const item = channelId
        ? await updateFileStorageChannel(token, channelId, input)
        : await createFileStorageChannel(token, input);
      setFileStorageChannels((current) => [item, ...current.filter((channel) => channel.id !== item.id)]);
      setCoreState('ready');
      setCoreMessage(channelId ? '文件存储渠道已更新。' : '文件存储渠道已新增。');
    } catch (err) {
      setCoreState('error');
      setCoreMessage(err instanceof Error ? err.message : channelId ? '更新文件存储渠道失败' : '新增文件存储渠道失败');
      throw err;
    }
  }

  async function saveFileStorageSettings(input: FileStorageSettingsUpdateRequest) {
    setCoreState('loading');
    setCoreMessage('');
    try {
      const settings = await updateFileStorageSettings(token, input);
      setFileStorageSettings(settings);
      setCoreState('ready');
      setCoreMessage('文件存储全局策略已更新。');
    } catch (err) {
      setCoreState('error');
      setCoreMessage(err instanceof Error ? err.message : '更新文件存储全局策略失败');
      throw err;
    }
  }

  async function removeFileStorageChannel(channelId: string) {
    setCoreState('loading');
    setCoreMessage('');
    try {
      await deleteFileStorageChannel(token, channelId);
      setFileStorageChannels((current) => current.filter((channel) => channel.id !== channelId));
      setCoreState('ready');
      setCoreMessage('文件存储渠道已删除。');
    } catch (err) {
      setCoreState('error');
      setCoreMessage(err instanceof Error ? err.message : '删除文件存储渠道失败');
      throw err;
    }
  }

  async function batchSaveAPIKeyAccessRules(input: GatewayAccessRuleBatchRequest) {
    setCoreState('loading');
    setCoreMessage('');
    try {
      const response = await batchApiKeyAccessRules(token, input);
      setAccessRules(response.items);
      setCoreState('ready');
      setCoreMessage('API Key 权限已更新。');
    } catch (err) {
      setCoreState('error');
      setCoreMessage(err instanceof Error ? err.message : '批量更新 API Key 权限失败');
      throw err;
    }
  }

  async function submitTask(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    const credential = apiKeySecret || token;
    setCoreState('loading');
    setCoreMessage('');
    try {
      const response = await runTask(credential, taskForm);
      const syncTask = (detail: GatewayTask) => {
        setTaskResult(detail);
        setTasks((current) => [detail, ...current.filter((item) => item.id !== detail.id)]);
      };
      const detail = await pollTaskUntilSettled(credential, response.task, { onUpdate: syncTask });
      setTaskResult(detail);
      setTasks((current) => [detail, ...current.filter((item) => item.id !== detail.id)]);
      invalidateDataKeys('tasks', 'wallet', 'walletTransactions');
      setCoreState('ready');
      setCoreMessage(`${taskForm.kind} 已通过 ${apiKeySecret ? '本地 API Key' : '当前 Access Token'} 完成 simulation。`);
    } catch (err) {
      setCoreState('error');
      setCoreMessage(err instanceof Error ? err.message : '测试任务失败');
    }
  }

  function signOut() {
    persistAccessToken('');
    setToken('');
    loadedDataKeysRef.current = new Set(health ? ['health'] : []);
    loadingDataKeysRef.current.clear();
    setState('idle');
    setPlatforms([]);
    setModels([]);
    setModelCatalog({ items: [], filters: { capabilities: [], providers: [] }, summary: { modelCount: 0, sourceCount: 0 } });
    setPlaygroundModels([]);
    setNetworkProxyConfig(null);
    setFileStorageChannels([]);
    setProviders([]);
    setBaseModels([]);
    setPricingRules([]);
    setPricingRuleSets([]);
    setRunnerPolicy(null);
    setRuntimePolicySets([]);
    setAccessRules([]);
    setAuditLogs([]);
    setRateLimitWindows([]);
    setModelRateLimits([]);
    setTenants([]);
    setUsers([]);
    setUserGroups([]);
    setApiKeys([]);
    setApiKeySecret('');
    setApiKeySecretsById({});
    setSelectedPlaygroundApiKeyId('');
    setTaskResult(null);
    setTasks([]);
    setTaskTotal(0);
    setWalletAccounts([]);
    setWalletTransactions([]);
    setWalletTransactionTotal(0);
    setWorkspaceTransactionQuery(defaultWorkspaceTransactionQuery());
    setCoreMessage('');
    navigatePath('/');
  }

  function showLogin() {
    setAuthMode('login');
    navigatePath(pathForWorkspaceSection('overview'));
  }

  function currentRouteState(): AppRouteState {
    return { activePage, adminSection, apiDocSection, playgroundMode, workspaceSection, workspaceTaskQuery };
  }

  function applyRoute(route: AppRouteState) {
    setActivePage(route.activePage);
    setAdminSection(route.adminSection);
    setApiDocSection(route.apiDocSection);
    setPlaygroundMode(route.playgroundMode);
    setWorkspaceSection(route.workspaceSection);
    setWorkspaceTaskQuery(route.workspaceTaskQuery);
  }

  function navigatePath(path: string) {
    if (`${window.location.pathname}${window.location.search}` !== path) {
      window.history.pushState(null, '', path);
    }
    applyRoute(parseAppRoute(path));
  }

  function navigatePage(page: PageKey) {
    navigatePath(pathForPage(page, currentRouteState()));
  }

  function navigateAdminSection(section: AdminSection) {
    navigatePath(pathForAdminSection(section));
  }

  function navigateWorkspaceSection(section: WorkspaceSection) {
    navigatePath(pathForWorkspaceSection(section));
  }

  function navigateWorkspaceTaskQuery(query: WorkspaceTaskQuery) {
    navigatePath(pathForWorkspaceTaskQuery(query));
  }

  function navigateApiDocSection(section: ApiDocSection) {
    navigatePath(pathForApiDocSection(section));
  }

  function navigatePlaygroundMode(mode: PlaygroundMode) {
    navigatePath(pathForPlaygroundMode(mode));
  }

  function openApiKeyCreation() {
    navigatePath(pathForWorkspaceSection('apiKeys'));
  }

  function useApiKeyForPlayground(apiKeyId?: string) {
    if (apiKeyId) setSelectedPlaygroundApiKeyId(apiKeyId);
    navigatePath(pathForPlaygroundMode('chat'));
  }

  const isAuthenticated = Boolean(token);

  return (
    <AppShell
      activePage={activePage}
      health={health}
      isAuthenticated={isAuthenticated}
      state={state}
      onNavigate={navigatePage}
      onLogin={showLogin}
      onRefresh={() => void refresh()}
      onSignOut={signOut}
    >
      {error && <div className="notice">{error}</div>}
      {activePage === 'home' && <HomePage onNavigate={navigatePage} onPlaygroundMode={navigatePlaygroundMode} />}
      {activePage === 'playground' && (
        <PlaygroundPage
          apiKeySecretsById={apiKeySecretsById}
          apiKeys={apiKeys}
          mode={playgroundMode}
          models={playgroundModels}
          selectedApiKeyId={selectedPlaygroundApiKeyId}
          token={token}
          onApiKeyChange={setSelectedPlaygroundApiKeyId}
          onCreateApiKey={openApiKeyCreation}
          onLogin={showLogin}
          onModeChange={navigatePlaygroundMode}
        />
      )}
      {activePage === 'models' && <ModelsPage data={data} />}
      {activePage === 'workspace' && (
        isAuthenticated ? (
          <WorkspacePage
            apiKeyForm={apiKeyForm}
            apiKeySecret={apiKeySecret}
            apiKeySecretsById={apiKeySecretsById}
            apiKeyPolicyModels={playgroundModels}
            data={data}
            message={coreMessage}
            section={workspaceSection}
            state={coreState}
            token={token}
            taskQuery={workspaceTaskQuery}
            taskTotal={taskTotal}
            transactionQuery={workspaceTransactionQuery}
            transactionTotal={walletTransactionTotal}
            onBatchAccessRules={batchSaveAPIKeyAccessRules}
            onDeleteApiKey={removeAPIKey}
            onApiKeyFormChange={setApiKeyForm}
            onSectionChange={navigateWorkspaceSection}
            onSubmitApiKey={submitAPIKey}
            onTaskQueryChange={navigateWorkspaceTaskQuery}
            onTransactionQueryChange={setWorkspaceTransactionQuery}
            onUseApiKeyForPlayground={useApiKeyForPlayground}
          />
        ) : (
          <LoginRequiredPanel
            authMode={authMode}
            externalToken={externalToken}
            loginForm={loginForm}
            registerForm={registerForm}
            state={state}
            onAuthModeChange={setAuthMode}
            onExternalTokenChange={setExternalToken}
            onLoginChange={setLoginForm}
            onRegisterChange={setRegisterForm}
            onSubmitExternalToken={submitExternalToken}
            onSubmitLogin={submitLogin}
            onSubmitRegister={submitRegister}
          />
        )
      )}
      {activePage === 'admin' && (
        isAuthenticated ? (
          <AdminPage
            data={data}
            operationMessage={coreMessage}
            section={adminSection}
            stats={stats}
            state={coreState}
            onDeleteBaseModel={removeBaseModel}
            onDeletePlatform={removePlatform}
            onDeleteProvider={removeProvider}
            onDeletePricingRuleSet={removePricingRuleSet}
            onDeleteRuntimePolicySet={removeRuntimePolicySet}
            onDeleteAccessRule={removeAccessRule}
            onDeleteFileStorageChannel={removeFileStorageChannel}
            onDeleteTenant={removeTenant}
            onDeleteUser={removeUser}
            onDeleteUserGroup={removeUserGroup}
            onSaveBaseModel={saveBaseModel}
            onResetAllBaseModels={resetAllBaseModelsToDefault}
            onResetBaseModel={resetBaseModelToDefault}
            onSavePlatform={savePlatformWithModels}
            onSavePlatformDynamicPriority={savePlatformDynamicPriority}
            onTogglePlatformStatus={savePlatformStatus}
            onSaveProvider={saveProvider}
            onSavePricingRuleSet={savePricingRuleSet}
            onSaveRunnerPolicy={saveRunnerPolicy}
            onSaveRuntimePolicySet={saveRuntimePolicySet}
            onBatchAccessRules={batchSaveAccessRules}
            onSaveAccessRule={saveAccessRule}
            onSaveFileStorageChannel={saveFileStorageChannel}
            onSaveFileStorageSettings={saveFileStorageSettings}
            onSaveTenant={saveTenant}
            onSaveUser={saveUser}
            onSetUserWalletBalance={saveUserWalletBalance}
            onSaveUserGroup={saveUserGroup}
            onClearOperationMessage={() => setCoreMessage('')}
            onSectionChange={navigateAdminSection}
          />
        ) : (
          <LoginRequiredPanel
            authMode={authMode}
            externalToken={externalToken}
            loginForm={loginForm}
            registerForm={registerForm}
            state={state}
            onAuthModeChange={setAuthMode}
            onExternalTokenChange={setExternalToken}
            onLoginChange={setLoginForm}
            onRegisterChange={setRegisterForm}
            onSubmitExternalToken={submitExternalToken}
            onSubmitLogin={submitLogin}
            onSubmitRegister={submitRegister}
          />
        )
      )}
      {activePage === 'docs' && (
        <ApiDocsPage
          activeDocSection={apiDocSection}
          apiKeySecret={apiKeySecret}
          canRun={isAuthenticated}
          coreMessage={coreMessage}
          coreState={coreState}
          taskForm={taskForm}
          taskResult={taskResult}
          onDocSectionChange={navigateApiDocSection}
          onLogin={showLogin}
          onSubmitTask={submitTask}
          onTaskFormChange={setTaskForm}
        />
      )}
    </AppShell>
  );
}

function platformModelIsSelected(model: PlatformModel, selectedModels: PlatformModelBindingInput[]) {
  return selectedModels.some((selected) => {
    if (selected.baseModelId && model.baseModelId) return selected.baseModelId === model.baseModelId;
    return selected.modelName === model.modelName && sameModelTypes(selected.modelType, model.modelType);
  });
}

function sameModelTypes(left: string[], right: string[]) {
  if (left.length !== right.length) return false;
  const rightSet = new Set(right);
  return left.every((type) => rightSet.has(type));
}

function mergeExistingPlatformModelInput(input: PlatformModelBindingInput, currentModels: PlatformModel[], platformId: string): PlatformModelBindingInput {
  const existing = currentModels.find((model) => model.platformId === platformId && platformModelIsSelected(model, [input]));
  if (!existing) return input;
  return {
    ...input,
    providerModelName: input.providerModelName ?? existing.providerModelName,
    discountFactor: (input.discountFactor ?? existing.discountFactor) || undefined,
    pricingRuleSetId: input.pricingRuleSetId ?? existing.pricingRuleSetId,
    rateLimitPolicy: input.rateLimitPolicy ?? existing.rateLimitPolicy,
    retryPolicy: input.retryPolicy ?? existing.retryPolicy,
    runtimePolicyOverride: input.runtimePolicyOverride ?? (existing.runtimePolicyOverride as Record<string, unknown> | undefined),
    runtimePolicySetId: input.runtimePolicySetId ?? existing.runtimePolicySetId,
  };
}

function platformStatusUpdatePayload(platform: IntegrationPlatform, status: 'enabled' | 'disabled'): PlatformCreateInput {
  return {
    provider: platform.provider,
    platformKey: platform.platformKey,
    name: platform.name,
    internalName: platform.internalName,
    baseUrl: platform.baseUrl,
    authType: platform.authType,
    config: platform.config ?? {},
    retryPolicy: platform.retryPolicy ?? {},
    rateLimitPolicy: platform.rateLimitPolicy ?? {},
    defaultPricingMode: platform.defaultPricingMode,
    defaultDiscountFactor: platform.defaultDiscountFactor,
    pricingRuleSetId: platform.pricingRuleSetId,
    priority: platform.priority,
    status,
  };
}

function withCredentialPreviewFallback(
  platform: IntegrationPlatform,
  input: PlatformCreateInput,
  existing?: IntegrationPlatform,
): IntegrationPlatform {
  const responsePreview = nonEmptyRecord(platform.credentialsPreview);
  if (responsePreview) return platform;
  if (input.credentials !== undefined) {
    const inputPreview = maskCredentialsPreview(input.credentials);
    return { ...platform, credentialsPreview: inputPreview ?? {} };
  }
  const existingPreview = nonEmptyRecord(existing?.credentialsPreview);
  return existingPreview ? { ...platform, credentialsPreview: existingPreview } : platform;
}

function maskCredentialsPreview(credentials: Record<string, unknown> | undefined) {
  if (!credentials || Object.keys(credentials).length === 0) return undefined;
  return Object.fromEntries(Object.entries(credentials).map(([key, value]) => [key, maskCredentialValue(value)]));
}

function maskCredentialValue(value: unknown): unknown {
  if (typeof value === 'string') return maskSecret(value);
  if (Array.isArray(value)) return value.map(maskCredentialValue);
  if (value && typeof value === 'object') {
    return Object.fromEntries(Object.entries(value as Record<string, unknown>).map(([key, nested]) => [key, maskCredentialValue(nested)]));
  }
  return value;
}

function maskSecret(value: string) {
  const trimmed = value.trim();
  if (!trimmed) return '';
  if (trimmed.length <= 6) return '*'.repeat(trimmed.length);
  return `${trimmed.slice(0, 3)}${'*'.repeat(trimmed.length - 6)}${trimmed.slice(-3)}`;
}

function nonEmptyRecord(value: Record<string, unknown> | undefined) {
  return value && Object.keys(value).length > 0 ? value : undefined;
}

function defaultWorkspaceTransactionQuery(): WorkspaceTransactionQuery {
  return {
    query: '',
    createdFrom: '',
    createdTo: '',
    page: 1,
    pageSize: 10,
  };
}

function normalizeWorkspaceTransactionQuery(query: WorkspaceTransactionQuery): WorkspaceTransactionQuery {
  return {
    query: query.query.trim(),
    createdFrom: query.createdFrom.trim(),
    createdTo: query.createdTo.trim(),
    page: positiveInt(query.page, 1),
    pageSize: clampTransactionPageSize(query.pageSize),
  };
}

function workspaceTransactionQueryKey(query: WorkspaceTransactionQuery) {
  return JSON.stringify(normalizeWorkspaceTransactionQuery(query));
}

function positiveInt(value: number, fallback: number) {
  return Number.isFinite(value) && value > 0 ? Math.floor(value) : fallback;
}

function clampTransactionPageSize(value: number) {
  const normalized = positiveInt(value, 10);
  return Math.min(100, Math.max(1, normalized));
}

function dataKeysForRoute(
  activePage: PageKey,
  adminSection: AdminSection,
  workspaceSection: WorkspaceSection,
  isAuthenticated: boolean,
): DataKey[] {
  if (activePage === 'playground') return isAuthenticated ? ['playgroundModels', 'playgroundApiKeys'] : [];
  if (activePage === 'models') {
    return isAuthenticated
      ? ['modelCatalog']
      : ['publicCatalog'];
  }
  if (activePage === 'home' || activePage === 'docs') return [];
  if (!isAuthenticated) return [];

  if (activePage === 'workspace') {
    if (workspaceSection === 'overview') return ['users', 'userGroups', 'apiKeys'];
    if (workspaceSection === 'billing') return ['wallet'];
    if (workspaceSection === 'apiKeys') return ['apiKeys', 'accessRules', 'playgroundModels'];
    if (workspaceSection === 'tasks') return ['tasks'];
    if (workspaceSection === 'transactions') return ['wallet', 'walletTransactions'];
    return [];
  }

  if (activePage !== 'admin') return [];
  switch (adminSection) {
    case 'overview':
      return ['platforms', 'models', 'providers', 'pricingRules', 'runtimePolicySets', 'rateLimitWindows', 'modelRateLimits', 'tenants', 'users', 'userGroups', 'accessRules'];
    case 'globalModels':
      return ['providers'];
    case 'pricing':
      return ['pricingRuleSets'];
    case 'runtime':
      return ['runtimePolicySets', 'runnerPolicy'];
    case 'baseModels':
      return ['baseModels', 'providers', 'pricingRuleSets', 'runtimePolicySets'];
    case 'platforms':
      return ['platforms', 'models', 'providers', 'baseModels', 'pricingRuleSets', 'networkProxyConfig'];
    case 'realtimeLoad':
      return ['platforms', 'modelRateLimits'];
    case 'tenants':
      return ['tenants', 'userGroups'];
    case 'users':
      return ['users', 'tenants', 'userGroups'];
    case 'userGroups':
      return ['userGroups'];
    case 'auditLogs':
      return ['auditLogs'];
    case 'accessRules':
      return ['accessRules', 'userGroups', 'platforms', 'models'];
    case 'systemSettings':
      return ['fileStorageSettings', 'fileStorageChannels'];
    default:
      return [];
  }
}
