(() => {
  const defaults = {
    mode: 'mock',
    apiBaseUrl: '',
    fallbackToMock: true,
    timeoutMs: 10000,
    getAccessToken: null,
  };
  const runtime = { ...defaults, ...(window.GONGXUE_PLATFORM_RUNTIME_CONFIG || {}) };
  const operationCatalog = Object.fromEntries(
    (window.GONGXUE_PLATFORM_SPEC?.operations || []).map(operation => [operation.operationId, operation]),
  );
  const trace = [];

  class PlatformApiError extends Error {
    constructor(message, options = {}) {
      super(message);
      this.name = 'PlatformApiError';
      this.status = Number(options.status || 0);
      this.code = options.code || 'PLATFORM_API_ERROR';
      this.requestId = options.requestId || '';
      this.operationId = options.operationId || '';
      this.details = options.details;
    }
  }

  function normalizeBaseUrl(value) {
    return String(value || '').trim().replace(/\/+$/, '');
  }

  function isEnabled() {
    return runtime.mode === 'api' || (runtime.mode === 'auto' && Boolean(normalizeBaseUrl(runtime.apiBaseUrl)));
  }

  function publicConfig() {
    return {
      mode: runtime.mode,
      apiBaseUrl: normalizeBaseUrl(runtime.apiBaseUrl),
      fallbackToMock: runtime.fallbackToMock !== false,
      timeoutMs: Number(runtime.timeoutMs) || defaults.timeoutMs,
      configured: isEnabled(),
    };
  }

  async function accessToken() {
    const provider = typeof runtime.getAccessToken === 'function'
      ? runtime.getAccessToken
      : typeof window.GONGXUE_PLATFORM_ACCESS_TOKEN_PROVIDER === 'function'
        ? window.GONGXUE_PLATFORM_ACCESS_TOKEN_PROVIDER
        : null;
    const token = provider ? await provider() : '';
    return String(token || '').trim();
  }

  function buildUrl(path, query = {}) {
    const baseUrl = normalizeBaseUrl(runtime.apiBaseUrl);
    const url = new URL(`${baseUrl}${path.startsWith('/') ? path : `/${path}`}`, window.location.href);
    Object.entries(query).forEach(([key, value]) => {
      if (value === undefined || value === null || value === '') return;
      url.searchParams.set(key, Array.isArray(value) ? value.join(',') : String(value));
    });
    return url.toString();
  }

  function responseRequestId(payload, response) {
    return String(
      payload?.meta?.requestId
      || payload?.requestId
      || response?.headers?.get?.('x-request-id')
      || '',
    );
  }

  async function request(operationId, options = {}) {
    const operation = operationCatalog[operationId];
    if (!operation) {
      throw new PlatformApiError(`未知平台接口：${operationId}`, {
        code: 'PLATFORM_OPERATION_UNKNOWN',
        operationId,
      });
    }
    if (!isEnabled()) {
      throw new PlatformApiError('平台 API 未启用', {
        code: 'PLATFORM_API_DISABLED',
        operationId,
      });
    }
    const token = await accessToken();
    if (!token) {
      throw new PlatformApiError('缺少平台管理员 access token', {
        status: 401,
        code: 'PLATFORM_ACCESS_TOKEN_MISSING',
        operationId,
      });
    }
    const extraHeaders = Object.fromEntries(Object.entries(options.headers || {}).map(([key, value]) => [key, String(value)]));
    const forbiddenHeader = Object.keys(extraHeaders).find((key) => {
      const normalized = key.toLowerCase();
      return ['authorization', 'x-user-id', 'x-platform-admin-key'].includes(normalized)
        || normalized.startsWith('x-tenant-');
    });
    if (forbiddenHeader) {
      throw new PlatformApiError(`禁止页面覆盖身份头：${forbiddenHeader}`, {
        code: 'PLATFORM_IDENTITY_HEADER_FORBIDDEN',
        operationId,
      });
    }

    const controller = new AbortController();
    const timeout = setTimeout(() => controller.abort(), Number(runtime.timeoutMs) || defaults.timeoutMs);
    const startedAt = Date.now();
    if (options.signal) {
      if (options.signal.aborted) controller.abort();
      else options.signal.addEventListener('abort', () => controller.abort(), { once: true });
    }
    try {
      const response = await fetch(buildUrl(operation.path, options.query), {
        method: operation.method,
        headers: {
          ...extraHeaders,
          Accept: 'application/json',
          Authorization: `Bearer ${token}`,
          ...(operation.method === 'GET' ? {} : { 'Content-Type': 'application/json' }),
        },
        body: operation.method === 'GET' || options.body === undefined
          ? undefined
          : JSON.stringify(options.body),
        credentials: 'omit',
        signal: controller.signal,
      });
      const text = await response.text();
      let payload = {};
      if (text) {
        try {
          payload = JSON.parse(text);
        } catch {
          payload = { error: text.slice(0, 500) };
        }
      }
      const requestId = responseRequestId(payload, response);
      trace.push({
        operationId,
        method: operation.method,
        path: operation.path,
        status: response.status,
        requestId,
        durationMs: Date.now() - startedAt,
        at: new Date().toISOString(),
      });
      if (trace.length > 120) trace.splice(0, trace.length - 120);
      if (!response.ok) {
        throw new PlatformApiError(
          String(payload.message || payload.error || `请求失败（HTTP ${response.status}）`),
          {
            status: response.status,
            code: String(payload.code || 'PLATFORM_API_REQUEST_FAILED'),
            requestId,
            operationId,
            details: payload,
          },
        );
      }
      return payload;
    } catch (error) {
      if (error instanceof PlatformApiError) throw error;
      const aborted = error?.name === 'AbortError';
      throw new PlatformApiError(aborted ? '平台接口请求超时' : (error?.message || '平台接口请求失败'), {
        code: aborted ? 'PLATFORM_API_TIMEOUT' : 'PLATFORM_API_NETWORK_ERROR',
        operationId,
        details: error,
      });
    } finally {
      clearTimeout(timeout);
    }
  }

  const dictionaries = {
    tenantStatusToApi: { 待配置: 'draft', 试用: 'active', 正常: 'active', 暂停: 'suspended', 已归档: 'archived' },
    tenantStatusFromApi: { draft: '待配置', active: '正常', suspended: '暂停', archived: '已归档' },
    billingStatusToApi: { 试用: 'trial', 正常: 'active', 待付款: 'active', 逾期: 'past_due', 暂停: 'suspended', 已取消: 'cancelled' },
    billingStatusFromApi: { trial: '试用', active: '正常', past_due: '逾期', suspended: '暂停', cancelled: '已取消' },
    subscriptionStatusToApi: { 试用中: 'trial', 活跃: 'active', 暂停: 'suspended', 已取消: 'cancelled', 已到期: 'expired' },
    subscriptionStatusFromApi: { trial: '试用中', active: '活跃', suspended: '暂停', cancelled: '已取消', expired: '已到期' },
    invoiceStatusFromApi: { draft: '草稿', issued: '待付款', paid: '已支付', void: '已作废', overdue: '已逾期' },
    invoiceTypeToApi: { 订阅服务费: 'subscription', 用量超额费: 'usage', 人工调整: 'adjustment', 首期服务费: 'manual' },
    invoiceTypeFromApi: { subscription: '订阅服务费', usage: '用量超额费', usage_overage: '用量超额费', manual: '人工账单', adjustment: '人工调整' },
    severityToApi: { 低: 'low', 中: 'medium', 高: 'high', 严重: 'critical' },
    severityFromApi: { low: '低', medium: '中', high: '高', critical: '严重' },
    grantScopeToApi: { 全部活跃租户: 'all_active_tenants', 指定套餐: 'plans', 指定租户: 'tenants', '套餐 + 租户': 'mixed' },
    grantScopeFromApi: { all_active_tenants: '全部活跃租户', plans: '指定套餐', tenants: '指定租户', mixed: '套餐 + 租户' },
    grantStatusFromApi: { active: '启用', disabled: '已禁用', expired: '已过期' },
    providerToApi: { Webhook: 'generic', SMTP: 'generic', 邮件: 'generic', 短信: 'generic', 钉钉: 'dingtalk', 飞书: 'feishu', 企微: 'wecom' },
    providerFromApi: { generic: 'Webhook', dingtalk: '钉钉', feishu: '飞书', wecom: '企微' },
    eventStatusFromApi: { pending: '待处理', processing: '发送中', sent: '成功', retrying: '重试中', failed: '失败', discarded: '已丢弃' },
  };

  function mapValue(map, value, fallback = value) {
    return Object.prototype.hasOwnProperty.call(map, value) ? map[value] : fallback;
  }

  function centsToYuan(value) {
    const number = Number(value || 0);
    return Number.isFinite(number) ? number / 100 : 0;
  }

  function yuanToCents(value) {
    const number = Number(value || 0);
    return Number.isFinite(number) ? Math.round(number * 100) : 0;
  }

  function dateOnly(value) {
    return value ? String(value).slice(0, 10) : '';
  }

  function monthOnly(value) {
    return value ? String(value).slice(0, 7) : '';
  }

  function dateTime(value) {
    if (!value) return '-';
    const parsed = new Date(value);
    if (Number.isNaN(parsed.getTime())) return String(value);
    return new Intl.DateTimeFormat('zh-CN', {
      timeZone: 'Asia/Shanghai',
      year: 'numeric',
      month: '2-digit',
      day: '2-digit',
      hour: '2-digit',
      minute: '2-digit',
      second: '2-digit',
      hour12: false,
    }).format(parsed).replaceAll('/', '-');
  }

  function isoStartOfDay(value) {
    if (!value) return undefined;
    return `${String(value).slice(0, 10)}T00:00:00+08:00`;
  }

  function splitList(value) {
    if (Array.isArray(value)) return value.map(String).map(item => item.trim()).filter(Boolean);
    return String(value || '').split(/[、,，]/).map(item => item.trim()).filter(Boolean);
  }

  function periodBounds(period) {
    const match = String(period || '').match(/^(\d{4})-(\d{2})$/);
    if (!match) return { periodStart: '', periodEnd: '' };
    const year = Number(match[1]);
    const month = Number(match[2]);
    const lastDay = new Date(Date.UTC(year, month, 0)).getUTCDate();
    return {
      periodStart: `${match[1]}-${match[2]}-01`,
      periodEnd: `${match[1]}-${match[2]}-${String(lastDay).padStart(2, '0')}`,
    };
  }

  function invoicePeriodBounds(label) {
    const match = String(label || '').match(/^(\d{4})年(\d{1,2})月$/);
    return match ? periodBounds(`${match[1]}-${String(match[2]).padStart(2, '0')}`) : {};
  }

  const bodyBuilders = {
    PlatformAdminTenantsController_create(input) {
      return {
        slug: input.slug,
        name: input.name,
        legalName: input.legalName || undefined,
        brandName: input.brandName || undefined,
        shortName: input.shortName || undefined,
        primaryHost: input.primaryHost || undefined,
        planCode: input.planCode || undefined,
        status: mapValue(dictionaries.tenantStatusToApi, input.status, input.status),
        billingStatus: mapValue(dictionaries.billingStatusToApi, input.billingStatus, input.billingStatus),
        amountCents: yuanToCents(input.amount),
      };
    },
    PlatformAdminTenantsController_status(input) {
      return {
        tenantId: input.tenantId,
        status: mapValue(dictionaries.tenantStatusToApi, input.status, input.status),
        billingStatus: mapValue(dictionaries.billingStatusToApi, input.billingStatus, input.billingStatus),
        reason: input.reason,
      };
    },
    PlatformAdminTenantsController_billingProfile(input) {
      return {
        tenantId: input.tenantId,
        billingName: input.billingName || undefined,
        taxId: input.taxId || undefined,
        contactName: input.contactName || undefined,
        contactPhone: input.phone || input.contactPhone || undefined,
        contactEmail: input.email || input.contactEmail || undefined,
        billingAddress: input.billingAddress || undefined,
        invoiceTitle: input.invoiceTitle || undefined,
        invoiceType: ({ 增值税专用发票: 'special_vat', 增值税普通发票: 'normal_vat', 不开票: 'none' })[input.type || input.invoiceType] || input.invoiceType || 'none',
        bankName: input.bankName || undefined,
        bankAccountMasked: input.bankAccountMasked || undefined,
      };
    },
    PlatformAdminBillingController_createSubscription(input) {
      return {
        tenantId: input.tenantId,
        planCode: input.planCode,
        status: mapValue(dictionaries.subscriptionStatusToApi, input.status, input.status || 'active'),
        billingCycle: ({ 年度: 'yearly', 月度: 'monthly', 试用: 'trial' })[input.cycle] || input.billingCycle,
        amountCents: yuanToCents(input.amount),
        startsAt: isoStartOfDay(input.start || input.startsAt),
        expiresAt: isoStartOfDay(input.expires || input.expiresAt),
        metadata: { autoRenew: Boolean(input.autoRenew), source: 'static-platform-console' },
      };
    },
    PlatformAdminBillingController_createInvoice(input) {
      const bounds = invoicePeriodBounds(input.period);
      return {
        tenantId: input.tenantId,
        invoiceType: mapValue(dictionaries.invoiceTypeToApi, input.type, input.invoiceType || 'manual'),
        status: input.status || 'draft',
        dueDate: input.due || input.dueDate,
        billingPeriodStart: input.billingPeriodStart || bounds.periodStart,
        billingPeriodEnd: input.billingPeriodEnd || bounds.periodEnd,
        items: input.items || [{
          itemType: mapValue(dictionaries.invoiceTypeToApi, input.type, 'manual'),
          description: input.note || input.type || '平台手工账单',
          quantity: 1,
          unitAmountCents: yuanToCents(input.amount),
          metadata: { periodLabel: input.period || '' },
        }],
        note: input.note || undefined,
      };
    },
    PlatformAdminBillingController_fromSubscription(input) {
      return {
        tenantId: input.tenantId,
        subscriptionId: input.subscriptionId || undefined,
        status: input.status || 'issued',
        dueDate: input.dueDate || undefined,
        note: input.note || undefined,
      };
    },
    PlatformAdminBillingController_fromSubscriptionsBatch(input) {
      return {
        tenantIds: input.tenantIds || undefined,
        subscriptionIds: input.subscriptionIds || undefined,
        daysAhead: input.daysAhead ?? 45,
        status: input.status || 'issued',
        dueDate: input.dueDate || undefined,
        note: input.note || undefined,
        dryRun: Boolean(input.dryRun),
      };
    },
    PlatformAdminBillingController_fromUsage(input) {
      const bounds = input.periodStart && input.periodEnd ? input : { ...input, ...periodBounds(input.period) };
      return {
        tenantIds: bounds.tenantIds || undefined,
        periodStart: bounds.periodStart,
        periodEnd: bounds.periodEnd,
        dueDate: bounds.dueDate || undefined,
        note: bounds.note || undefined,
        status: bounds.status || 'issued',
        dryRun: Boolean(bounds.dryRun),
      };
    },
    PlatformAdminBillingController_processOverdue(input) {
      return { dryRun: Boolean(input.dryRun), channel: input.channel || 'internal', limit: Number(input.limit || 100) };
    },
    PlatformAdminBillingController_confirmPayment(input) {
      return {
        tenantId: input.tenantId,
        invoiceId: input.invoiceId,
        amountCents: yuanToCents(input.amount),
        paymentNo: input.paymentNo || undefined,
        provider: input.provider || 'manual',
        method: input.method || 'manual',
        paidAt: input.paidAt ? new Date(input.paidAt).toISOString() : undefined,
        providerTradeNo: input.tradeNo || input.providerTradeNo || undefined,
      };
    },
    PlatformAdminBillingController_recordUsage(input) {
      const bounds = input.periodStart && input.periodEnd ? input : { ...input, ...periodBounds(input.period) };
      return {
        tenantId: bounds.tenantId,
        metricKey: bounds.metricKey,
        metricValue: Number(bounds.metricValue || 0),
        periodStart: bounds.periodStart,
        periodEnd: bounds.periodEnd,
        metadata: { source: 'platform_console_manual' },
      };
    },
    PlatformAdminQuestionBanksController_upsertGrant(input) {
      return {
        id: input.id || undefined,
        sourceQuestionBankId: input.bankId || input.sourceQuestionBankId,
        grantScope: mapValue(dictionaries.grantScopeToApi, input.scope, input.grantScope),
        allowedPlanCodes: input.allowedPlanCodes || (input.planCode ? [input.planCode] : []),
        allowedTenantIds: input.allowedTenantIds || (input.tenantId ? [input.tenantId] : []),
        allowedRegionIds: input.allowedRegionIds || splitList(input.regionIds),
        allowedSubjectIds: input.allowedSubjectIds || splitList(input.subjectIds),
        status: input.status === '已禁用' || input.status === 'disabled'
          ? 'disabled'
          : input.status === '已过期' || input.status === 'expired'
            ? 'expired'
            : 'active',
        startsAt: isoStartOfDay(input.startsAt),
        expiresAt: isoStartOfDay(input.expiresAt),
        metadata: { localEdit: Boolean(input.localEdit) },
      };
    },
    PlatformAdminOverviewController_upsertStaff(input) {
      const permissionList = input.permissions || [];
      return {
        id: input.id || undefined,
        authUserId: input.authUserId,
        username: input.username,
        email: input.email || undefined,
        phone: input.phone || undefined,
        name: input.name,
        status: input.status === '已停用' ? 'disabled' : 'active',
        platformPermissions: Object.fromEntries(permissionList.map(permission => [permission, true])),
        metadata: { displayRole: input.role || '平台管理员' },
      };
    },
    PlatformAdminOverviewController_updateStaffStatus(input) {
      return {
        staffId: input.staffId,
        status: input.status === '正常' || input.status === 'active' ? 'active' : 'disabled',
        reason: input.reason || undefined,
        revokeSessions: input.revokeSessions !== false,
      };
    },
    PlatformAdminAuditController_updateAlert(input) {
      return {
        alertId: input.alertId,
        status: input.status,
        note: input.note || undefined,
      };
    },
  };

  function notificationBody(input) {
    const maxAttempts = Number(input.maxAttempts || input.retry || 3);
    return {
      id: input.id || undefined,
      channelCode: input.code || input.channelCode,
      name: input.name,
      enabled: input.enabled !== false,
      provider: mapValue(dictionaries.providerToApi, input.provider, input.provider || 'generic'),
      webhookUrl: input.endpoint || input.webhookUrl,
      secret: input.secret || undefined,
      secretRef: input.secretRef || undefined,
      minSeverity: mapValue(dictionaries.severityToApi, input.minSeverity, input.minSeverity || 'medium'),
      statusFilter: splitList(input.statusFilter || 'open,acknowledged'),
      timeoutSec: Number(input.timeout || input.timeoutSec || 10),
      maxAttempts,
      metadata: { ...(input.metadata || {}), maxAttempts },
    };
  }
  bodyBuilders.PlatformAdminAuditController_upsertChannel = notificationBody;
  bodyBuilders.PlatformAdminDunningChannelsController_upsertChannel = input => ({
    ...notificationBody(input),
    minReminderLevel: Number(input.minReminderLevel || 1),
    reminderTypes: input.reminderTypes || ['overdue', 'final_notice'],
    reminderChannels: input.reminderChannels || ['internal'],
  });

  function buildBody(operationId, input = {}) {
    const builder = bodyBuilders[operationId];
    return builder ? builder(input) : input;
  }

  function jsonSummary(value) {
    if (!value) return '';
    if (typeof value === 'string') return value;
    try {
      return JSON.stringify(value);
    } catch {
      return String(value);
    }
  }

  function safeEndpoint(item) {
    if (!item?.webhook) return '';
    const protocol = item.webhook.protocol ? `${item.webhook.protocol}://` : '';
    return `${protocol}${item.webhook.host || ''}${item.webhook.pathname || ''}`;
  }

  function currentById(items, id) {
    return (items || []).find(item => item.id === id) || {};
  }

  const adapters = {
    plan(item, current = {}) {
      const quotas = item.includedQuotas && typeof item.includedQuotas === 'object'
        ? Object.entries(item.includedQuotas).map(([key, value]) => `${key}: ${value}`)
        : current.quotas || [];
      return {
        ...current,
        code: item.code,
        name: item.name,
        description: item.description || '',
        cycle: ({ yearly: '年度', monthly: '月度' })[item.billingCycle] || item.billingCycle || '-',
        amount: centsToYuan(item.baseAmountCents),
        quotas,
        tenantCount: Number(current.tenantCount || 0),
        status: item.status,
      };
    },
    tenant(item, current = {}, planMap = {}) {
      const plan = planMap[item.planCode];
      return {
        students: 0,
        questions: 0,
        storageGB: 0,
        trafficTB: 0,
        balance: 0,
        host: '-',
        owner: '待配置',
        ownerPhone: '-',
        ...current,
        id: item.id,
        slug: item.slug,
        name: item.name,
        legal: item.legalName || current.legal || item.name,
        brand: item.brandName || current.brand || item.name,
        planCode: item.planCode || '',
        plan: plan?.name || current.plan || item.planCode || '未订阅',
        status: mapValue(dictionaries.tenantStatusFromApi, item.status, item.status || '-'),
        billing: mapValue(dictionaries.billingStatusFromApi, item.billingStatus, item.billingStatus || '-'),
        mode: item.mode === 'saas' ? '正式' : item.mode || current.mode || '-',
        expires: dateOnly(item.subscriptionExpiresAt),
        balance: centsToYuan(item.openBalanceCents),
        createdAt: dateTime(item.createdAt),
      };
    },
    subscription(item) {
      return {
        id: item.subscriptionId || item.id,
        tenantId: item.tenantId,
        planCode: item.planCode || '',
        status: mapValue(dictionaries.subscriptionStatusFromApi, item.status, item.status || '-'),
        cycle: ({ yearly: '年度', monthly: '月度', trial: '试用' })[item.billingCycle] || item.billingCycle || '-',
        amount: centsToYuan(item.amountCents),
        start: dateOnly(item.startsAt),
        expires: dateOnly(item.expiresAt),
        autoRenew: Boolean(item.metadata?.autoRenew),
      };
    },
    invoice(item) {
      return {
        id: item.invoiceNo || item.id,
        backendId: item.id,
        tenantId: item.tenantId,
        type: mapValue(dictionaries.invoiceTypeFromApi, item.invoiceType, item.invoiceType || '-'),
        period: item.billingPeriodStart ? monthOnly(item.billingPeriodStart) : monthOnly(item.issuedAt || item.dueDate),
        total: centsToYuan(item.totalCents),
        paid: centsToYuan(item.paidCents),
        balance: centsToYuan(item.balanceCents),
        due: dateOnly(item.dueDate),
        status: mapValue(dictionaries.invoiceStatusFromApi, item.status, item.status || '-'),
        note: item.note || '',
      };
    },
    reminder(item) {
      return {
        id: item.id,
        invoiceId: item.invoiceNo || item.invoiceId,
        backendInvoiceId: item.invoiceId,
        tenantId: item.tenantId,
        level: Number(item.reminderLevel || 1),
        channel: item.channel || '-',
        status: mapValue(dictionaries.eventStatusFromApi, item.status, item.status || '-'),
        date: dateTime(item.reminderDate || item.createdAt),
        message: item.message || '',
      };
    },
    bank(item, current = {}) {
      return {
        ...current,
        id: item.id,
        name: item.name,
        catalog: item.regionName || item.tenantName || '公共题库',
        source: item.sourceScope === 'platform' ? '平台公共题库' : '租户自建',
        questions: Number(item.questionCount || 0),
        version: item.metadata?.version || item.metadata?.contentVersion || '-',
        status: item.status === 'active' ? '稳定版' : item.status || '-',
      };
    },
    grant(item) {
      return {
        id: item.id,
        bankId: item.sourceQuestionBankId,
        scope: mapValue(dictionaries.grantScopeFromApi, item.grantScope, item.grantScope || '-'),
        allowedPlanCodes: item.allowedPlanCodes || [],
        allowedTenantIds: item.allowedTenantIds || [],
        allowedRegionIds: item.allowedRegionIds || [],
        allowedSubjectIds: item.allowedSubjectIds || [],
        status: mapValue(dictionaries.grantStatusFromApi, item.status, item.status || '-'),
        startsAt: dateOnly(item.startsAt),
        expiresAt: dateOnly(item.expiresAt),
        localEdit: Boolean(item.metadata?.localEdit),
      };
    },
    sync(item) {
      const progress = item.syncStatus === 'synced'
        ? 100
        : Number(item.metadata?.lastSync?.progress || item.lastSyncCounts?.progress || 0);
      return {
        tenantId: item.tenantId,
        bankId: item.sourceQuestionBankId,
        current: item.metadata?.lastSync?.sourceVersion || '-',
        target: item.metadata?.lastSync?.targetVersion || '-',
        progress,
        conflicts: Number(item.conflictCount || 0),
        status: ({ pending: '同步中', synced: '已完成', failed: '同步失败' })[item.syncStatus] || item.syncStatus || item.status || '-',
      };
    },
    staff(item) {
      const permissions = item.roleCodes?.includes('platform_super_admin') ? ['*'] : [];
      return {
        id: item.userId || item.id,
        authUserId: item.userId || item.authUserId || '',
        username: item.email || '',
        name: item.name || item.email || '平台员工',
        email: item.email || '',
        phone: item.phoneMasked || item.phone || '-',
        role: permissions.includes('*') ? '超级管理员' : item.rawProfile?.displayRole || '平台管理员',
        permissions,
        status: item.status === 'active' ? '正常' : '已停用',
        lastActive: dateTime(item.updatedAt),
      };
    },
    audit(item) {
      const details = jsonSummary(item.details);
      return {
        id: item.id,
        time: `${dateTime(item.createdAt)} CST`,
        actor: item.actorName || item.actorUsername || item.actorUserId || 'system',
        role: item.actorUserId ? '平台管理员' : '系统任务',
        action: item.action || '-',
        targetType: item.targetType || '-',
        targetId: item.targetId || '',
        target: item.tenantName || item.targetId || item.targetType || '-',
        severity: mapValue(dictionaries.severityFromApi, item.details?.severity, item.details?.severity || '中'),
        result: item.details?.result === 'failed' ? '失败' : '成功',
        ip: item.ipAddress || '-',
        details,
      };
    },
    alert(item) {
      const evidence = Array.isArray(item.details?.evidence)
        ? item.details.evidence.map(String)
        : Object.entries(item.details || {}).slice(0, 8).map(([key, value]) => `${key}: ${jsonSummary(value)}`);
      return {
        id: item.id,
        title: item.title || item.ruleName || '平台审计告警',
        summary: item.summary || item.action || '',
        severity: mapValue(dictionaries.severityFromApi, item.severity, item.severity || '-'),
        status: item.status || 'open',
        owner: item.acknowledgedByName || item.resolvedByName || item.tenantName || item.ruleName || '待认领',
        targetType: item.targetType || '-',
        targetId: item.targetId || '',
        evidence,
        updatedAt: dateTime(item.updatedAt || item.createdAt),
        note: item.resolutionNote || '',
      };
    },
    rule(item) {
      return {
        id: item.id,
        code: item.code,
        name: item.name,
        severity: mapValue(dictionaries.severityFromApi, item.severity, item.severity || '-'),
        enabled: item.enabled !== false,
        window: item.conditions?.window || item.metadata?.window || '-',
        threshold: item.conditions?.threshold || item.metadata?.threshold || '-',
        target: item.description || (item.targetTypes || []).join('、') || '-',
      };
    },
    channel(item) {
      return {
        id: item.id,
        code: item.channelCode,
        name: item.name,
        provider: mapValue(dictionaries.providerFromApi, item.provider, item.provider || 'Webhook'),
        endpoint: safeEndpoint(item),
        enabled: item.enabled !== false,
        retry: Number(item.maxAttempts || item.metadata?.maxAttempts || 3),
        minSeverity: mapValue(dictionaries.severityFromApi, item.minSeverity, item.minSeverity || '中'),
        statusFilter: (item.statusFilter || []).join(','),
        timeout: Number(item.timeoutSec || 10),
        maxAttempts: Number(item.maxAttempts || item.metadata?.maxAttempts || 3),
        lastStatus: '正常',
        secretRef: item.secretRef || '',
        endpointRedacted: true,
        reminderTypes: item.reminderTypes || [],
        reminderChannels: item.reminderChannels || [],
        minReminderLevel: Number(item.minReminderLevel || 1),
      };
    },
    event(item, type = 'audit') {
      return {
        id: item.id,
        channelId: item.channelId,
        subject: type === 'dunning'
          ? item.reminderMessage || item.invoiceNo || '催缴通知'
          : item.alertTitle || item.alertAction || '审计告警通知',
        status: mapValue(dictionaries.eventStatusFromApi, item.status, item.status || '-'),
        attempts: Number(item.attempts || 0),
        updatedAt: dateTime(item.updatedAt || item.sentAt || item.createdAt),
        error: item.lastError || '',
      };
    },
  };

  function aggregateUsage(items) {
    const records = new Map();
    items.forEach(item => {
      const period = monthOnly(item.periodStart || item.periodEnd);
      const key = `${item.tenantId}:${period}`;
      const record = records.get(key) || {
        tenantId: item.tenantId,
        period,
        source: item.metadata?.source === 'platform_usage_worker' ? 'Worker 自动采集' : '人工补录',
        students: 0,
        questions: 0,
        storageGB: 0,
        trafficTB: 0,
        overage: [],
        estimated: 0,
      };
      const metricMap = {
        students: 'students',
        questions: 'questions',
        storage_gb: 'storageGB',
        traffic_tb: 'trafficTB',
      };
      const field = metricMap[item.metricKey];
      if (field) record[field] = Number(item.metricValue || 0);
      records.set(key, record);
    });
    return Array.from(records.values());
  }

  function currentPeriod() {
    const parts = new Intl.DateTimeFormat('en-US', {
      timeZone: 'Asia/Shanghai',
      year: 'numeric',
      month: '2-digit',
    }).formatToParts(new Date());
    const values = Object.fromEntries(parts.map(part => [part.type, part.value]));
    return `${values.year}-${values.month}`;
  }

  const bootstrapDescriptors = [
    ['overview', 'PlatformAdminOverviewController_overview', {}],
    ['plans', 'PlatformAdminOverviewController_plans', { query: { includeArchived: false } }],
    ['tenants', 'PlatformAdminTenantsController_list', { query: { limit: 200 } }],
    ['staff', 'PlatformAdminOverviewController_staff', { query: { limit: 200 } }],
    ['dunningChannels', 'PlatformAdminDunningChannelsController_channels', { query: { limit: 100 } }],
    ['dunningEvents', 'PlatformAdminDunningEventsController_events', { query: { limit: 100 } }],
    ['auditLogs', 'PlatformAdminAuditController_logs', { query: { limit: 200 } }],
    ['alerts', 'PlatformAdminAuditController_alerts', { query: { limit: 100 } }],
  ];

  async function bootstrap(options = {}) {
    const descriptors = bootstrapDescriptors.map(([key, operationId, requestOptions]) => {
      const nextOptions = { ...requestOptions, query: { ...(requestOptions.query || {}) } };
      if (key === 'banks') nextOptions.query.includeTenantBanks = Boolean(options.includeTenantBanks);
      return [key, operationId, nextOptions];
    });
    const results = await Promise.allSettled(
      descriptors.map(([, operationId, requestOptions]) => request(operationId, requestOptions)),
    );
    const payloads = {};
    const errors = {};
    results.forEach((result, index) => {
      const [key] = descriptors[index];
      if (result.status === 'fulfilled') payloads[key] = result.value;
      else errors[key] = result.reason;
    });
    return { payloads, errors, requested: descriptors.length };
  }

  function adaptBootstrap(payloads, currentData = {}) {
    const patch = {};
    if (payloads.overview) patch.apiOverview = payloads.overview.item || payloads.overview;
    if (payloads.permissions?.item) patch.apiPermissions = payloads.permissions.item;
    if (Array.isArray(payloads.plans?.items)) {
      patch.plans = payloads.plans.items.map(item => adapters.plan(item, currentById(currentData.plans, item.code)));
    }
    const planItems = patch.plans || currentData.plans || [];
    const planMap = Object.fromEntries(planItems.map(item => [item.code, item]));
    if (Array.isArray(payloads.tenants?.items)) {
      patch.tenants = payloads.tenants.items.map(item => adapters.tenant(item, currentById(currentData.tenants, item.id), planMap));
    }
    if (Array.isArray(payloads.staff?.items)) patch.staff = payloads.staff.items.map(adapters.staff);
    if (Array.isArray(payloads.invoices?.items)) patch.invoices = payloads.invoices.items.map(adapters.invoice);
    if (Array.isArray(payloads.subscriptions?.items)) {
      patch.subscriptions = payloads.subscriptions.items
        .filter(item => item.subscriptionId)
        .map(adapters.subscription);
    }
    if (Array.isArray(payloads.usage?.items)) patch.usage = aggregateUsage(payloads.usage.items);
    if (Array.isArray(payloads.usageCandidates?.items) && patch.usage) {
      const usageByKey = new Map(patch.usage.map(item => [`${item.tenantId}:${item.period}`, item]));
      payloads.usageCandidates.items.forEach(candidate => {
        const record = usageByKey.get(`${candidate.tenantId}:${monthOnly(candidate.periodStart)}`);
        if (!record) return;
        record.estimated = centsToYuan(candidate.totalCents);
        record.overage = (candidate.items || []).map(item => item.description || item.itemType).filter(Boolean);
      });
    }
    if (Array.isArray(payloads.reminders?.items)) patch.reminders = payloads.reminders.items.map(adapters.reminder);
    if (Array.isArray(payloads.dunningChannels?.items)) patch.dunningChannels = payloads.dunningChannels.items.map(adapters.channel);
    if (Array.isArray(payloads.dunningEvents?.items)) patch.dunningEvents = payloads.dunningEvents.items.map(item => adapters.event(item, 'dunning'));
    if (Array.isArray(payloads.banks?.items)) {
      patch.banks = payloads.banks.items.map(item => adapters.bank(item, currentById(currentData.banks, item.id)));
    }
    if (Array.isArray(payloads.grants?.items)) patch.grants = payloads.grants.items.map(adapters.grant);
    if (Array.isArray(payloads.bankSync?.items)) patch.bankSync = payloads.bankSync.items.map(adapters.sync);
    if (Array.isArray(payloads.auditLogs?.items)) patch.auditLogs = payloads.auditLogs.items.map(adapters.audit);
    if (Array.isArray(payloads.alertRules?.items)) patch.alertRules = payloads.alertRules.items.map(adapters.rule);
    if (Array.isArray(payloads.alerts?.items)) patch.alerts = payloads.alerts.items.map(adapters.alert);
    if (Array.isArray(payloads.auditChannels?.items)) patch.auditChannels = payloads.auditChannels.items.map(adapters.channel);
    if (Array.isArray(payloads.notificationEvents?.items)) {
      patch.notificationEvents = payloads.notificationEvents.items.map(item => adapters.event(item, 'audit'));
    }
    return patch;
  }

  async function tenantDetail(tenantId) {
    const payload = await request('PlatformAdminTenantsController_detail', { query: { tenantId } });
    const item = payload.item || {};
    return {
      tenant: item.tenant || null,
      domains: item.domains || [],
      subscriptions: (item.subscriptions || []).map(adapters.subscription),
      invoices: (item.invoices || []).map(adapters.invoice),
      usage: aggregateUsage(item.usage || []),
      billingProfile: item.tenant ? {
        billingName: item.tenant.billingName || '',
        taxId: item.tenant.taxId || '',
        contactName: item.tenant.contactName || '',
        phone: item.tenant.contactPhone || '',
        email: item.tenant.contactEmail || '',
        billingAddress: item.tenant.billingAddress || '',
        invoiceTitle: item.tenant.invoiceTitle || '',
        type: ({ special_vat: '增值税专用发票', normal_vat: '增值税普通发票', none: '不开票' })[item.tenant.invoiceType] || item.tenant.invoiceType || '',
        bankName: item.tenant.bankName || '',
        bankAccountMasked: item.tenant.bankAccountMasked || '',
      } : null,
    };
  }

  function downloadExport(payload) {
    const item = payload?.item;
    if (!item?.contentBase64) {
      throw new PlatformApiError('审计导出响应缺少文件内容', { code: 'AUDIT_EXPORT_INVALID' });
    }
    const bytes = Uint8Array.from(atob(item.contentBase64), character => character.charCodeAt(0));
    const blob = new Blob([bytes], { type: item.mimeType || 'application/octet-stream' });
    const url = URL.createObjectURL(blob);
    const anchor = document.createElement('a');
    anchor.href = url;
    anchor.download = item.filename || `platform-audit.${item.format || 'csv'}`;
    anchor.click();
    setTimeout(() => URL.revokeObjectURL(url), 1000);
    return item;
  }

  window.GongxuePlatformApi = Object.freeze({
    PlatformApiError,
    adapters,
    adaptBootstrap,
    bootstrap,
    buildBody,
    dictionaries,
    downloadExport,
    isEnabled,
    operationCatalog,
    periodBounds,
    publicConfig,
    request,
    tenantDetail,
    trace,
  });
})();
