import { apiRequest } from './api'; export interface PlatformOverview { tenants?: { total?: number; active?: number; suspended?: number; trial?: number; pastDue?: number; }; billing?: { unpaidAmountCents?: number; paidAmountCents?: number; overdueInvoices?: number; }; subscriptions?: { active?: number; expiringSoon?: number; }; usage?: { students?: number; questions?: number; storageGb?: number; }; } export interface PlatformSaasPlan { id: string; code: string; name: string; description?: string | null; billingCycle?: string | null; baseAmountCents?: number | string | null; currency?: string | null; includedQuotas?: Record | null; overagePrices?: Record | null; featureFlags?: Record | null; status?: string | null; sortOrder?: number | null; } export interface PlatformTenantItem { id: string; slug: string; name: string; legalName?: string | null; status?: string | null; mode?: string | null; billingStatus?: string | null; brandName?: string | null; planCode?: string | null; subscriptionStatus?: string | null; subscriptionExpiresAt?: string | null; openBalanceCents?: number | string | null; } export interface PlatformTenantBillingProfile { tenantId?: string | null; billingName?: string | null; taxId?: string | null; contactName?: string | null; contactPhone?: string | null; contactEmail?: string | null; billingAddress?: string | null; invoiceTitle?: string | null; invoiceType?: string | null; bankName?: string | null; bankAccountMasked?: string | null; metadata?: Record | null; } export interface PlatformTenantDetailTenant extends PlatformTenantItem, PlatformTenantBillingProfile { shortName?: string | null; serviceWechat?: string | null; ownerUserId?: string | null; metadata?: Record | null; createdAt?: string | null; updatedAt?: string | null; } export interface PlatformTenantDomain { id: string; host?: string | null; domainType?: string | null; status?: string | null; isPrimary?: boolean | null; verifiedAt?: string | null; createdAt?: string | null; } export interface PlatformTenantSubscription { id: string; planCode?: string | null; status?: string | null; startsAt?: string | null; expiresAt?: string | null; billingCycle?: string | null; amountCents?: number | string | null; metadata?: Record | null; createdAt?: string | null; } export interface PlatformTenantDetail { tenant?: PlatformTenantDetailTenant | null; domains?: PlatformTenantDomain[]; subscriptions?: PlatformTenantSubscription[]; invoices?: PlatformInvoiceItem[]; usage?: PlatformUsageItem[]; } export interface PlatformInvoiceItem { id: string; tenantId: string; tenantSlug?: string | null; tenantName?: string | null; invoiceNo?: string | null; invoiceType?: string | null; status?: string | null; currency?: string | null; totalCents?: number | string | null; paidCents?: number | string | null; balanceCents?: number | string | null; dueDate?: string | null; issuedAt?: string | null; paidAt?: string | null; note?: string | null; } export interface PlatformInvoiceReminderItem { id: string; tenantId: string; tenantSlug?: string | null; tenantName?: string | null; invoiceId: string; invoiceNo?: string | null; reminderType?: string | null; channel?: string | null; status?: string | null; reminderDate?: string | null; reminderLevel?: number | string | null; dueDate?: string | null; balanceCentsSnapshot?: number | string | null; message?: string | null; createdAt?: string | null; } export interface PlatformUsageItem { id: string; tenantId: string; tenantSlug?: string | null; tenantName?: string | null; metricKey?: string | null; metricValue?: number | string | null; periodStart?: string | null; periodEnd?: string | null; metadata?: Record | null; } export interface PlatformSubscriptionInvoiceCandidate { tenantId: string; tenantSlug?: string | null; tenantName?: string | null; billingStatus?: string | null; subscriptionId: string; planCode?: string | null; planName?: string | null; status?: string | null; startsAt?: string | null; expiresAt?: string | null; billingCycle?: string | null; amountCents?: number | string | null; existingInvoiceId?: string | null; existingInvoiceNo?: string | null; existingInvoiceStatus?: string | null; hasExistingInvoice?: boolean | null; wouldCreate?: boolean | null; } export interface PlatformQuestionBankItem { id: string; tenantId?: string | null; tenantSlug?: string | null; tenantName?: string | null; regionId?: string | null; regionName?: string | null; name: string; sourceScope?: string | null; status?: string | null; metadata?: Record | null; questionCount?: number | string | null; } export interface PlatformQuestionBankGrant { id: string; sourceQuestionBankId?: string | null; sourceQuestionBankName?: string | null; sourceRegionName?: string | null; grantScope?: string | null; allowedPlanCodes?: string[] | null; allowedTenantIds?: string[] | null; allowedRegionIds?: string[] | null; allowedSubjectIds?: string[] | null; status?: string | null; startsAt?: string | null; expiresAt?: string | null; } export interface PlatformAuditLogItem { id: string; tenantId?: string | null; tenantSlug?: string | null; tenantName?: string | null; actorUserId?: string | null; actorUsername?: string | null; actorName?: string | null; actorPhone?: string | null; action?: string | null; targetType?: string | null; targetId?: string | null; details?: Record | null; ipAddress?: string | null; userAgent?: string | null; createdAt?: string | null; } export interface PlatformAuditExportItem { filename?: string | null; format?: string | null; mimeType?: string | null; rowCount?: number | string | null; exportedAt?: string | null; sha256?: string | null; sizeBytes?: number | string | null; contentBase64?: string | null; filters?: Record | null; } export interface PlatformAuditAlertRuleItem { id: string; code?: string | null; name?: string | null; description?: string | null; enabled?: boolean | null; severity?: string | null; actionPatterns?: string[] | null; targetTypes?: string[] | null; tenantId?: string | null; conditions?: Record | null; metadata?: Record | null; createdAt?: string | null; updatedAt?: string | null; } export interface PlatformAuditAlertItem { id: string; ruleId?: string | null; ruleCode?: string | null; ruleName?: string | null; auditLogId?: string | null; tenantId?: string | null; tenantSlug?: string | null; tenantName?: string | null; severity?: string | null; status?: string | null; action?: string | null; targetType?: string | null; targetId?: string | null; title?: string | null; summary?: string | null; details?: Record | null; actorUserId?: string | null; actorUsername?: string | null; actorName?: string | null; ipAddress?: string | null; userAgent?: string | null; auditCreatedAt?: string | null; acknowledgedAt?: string | null; resolvedAt?: string | null; resolutionNote?: string | null; createdAt?: string | null; updatedAt?: string | null; } export interface PlatformAuditNotificationChannelItem { id: string; channelCode?: string | null; name?: string | null; description?: string | null; enabled?: boolean | null; provider?: string | null; secretRef?: string | null; minSeverity?: string | null; statusFilter?: string[] | null; actionPatterns?: string[] | null; tenantIds?: string[] | null; timeoutSec?: number | string | null; webhook?: { protocol?: string | null; host?: string | null; pathname?: string | null; } | null; metadata?: Record | null; createdAt?: string | null; updatedAt?: string | null; } export interface PlatformAuditNotificationEventItem { id: string; channelId?: string | null; channelCode?: string | null; channelName?: string | null; alertId?: string | null; auditLogId?: string | null; provider?: string | null; status?: string | null; attempts?: number | string | null; lastHttpCode?: number | string | null; lastError?: string | null; lastResponseSummary?: string | null; alertSeverity?: string | null; alertStatus?: string | null; alertTitle?: string | null; alertAction?: string | null; tenantName?: string | null; tenantSlug?: string | null; sentAt?: string | null; createdAt?: string | null; updatedAt?: string | null; } export interface PlatformDunningNotificationChannelItem { id: string; channelCode?: string | null; name?: string | null; description?: string | null; enabled?: boolean | null; provider?: string | null; secretRef?: string | null; reminderTypes?: string[] | null; reminderChannels?: string[] | null; minReminderLevel?: number | string | null; tenantIds?: string[] | null; timeoutSec?: number | string | null; webhook?: { protocol?: string | null; host?: string | null; pathname?: string | null; } | null; metadata?: Record | null; createdAt?: string | null; updatedAt?: string | null; } export interface PlatformDunningNotificationEventItem { id: string; channelId?: string | null; channelCode?: string | null; channelName?: string | null; reminderId?: string | null; invoiceId?: string | null; invoiceNo?: string | null; tenantId?: string | null; tenantName?: string | null; tenantSlug?: string | null; provider?: string | null; status?: string | null; attempts?: number | string | null; lastHttpCode?: number | string | null; lastError?: string | null; lastResponseSummary?: string | null; reminderType?: string | null; reminderChannel?: string | null; reminderLevel?: number | string | null; invoiceBalanceCents?: number | string | null; sentAt?: string | null; createdAt?: string | null; updatedAt?: string | null; } export interface CreatePlatformTenantInput { slug: string; name: string; legalName?: string; brandName?: string; shortName?: string; primaryHost?: string; planCode?: string; status?: string; billingStatus?: string; amountCents?: number; } export interface UpdatePlatformTenantStatusInput { tenantId: string; status?: string; billingStatus?: string; reason?: string; } export interface UpsertPlatformTenantBillingProfileInput extends PlatformTenantBillingProfile { tenantId: string; } export interface CreatePlatformSubscriptionInput { tenantId: string; planCode: string; status?: string; startsAt?: string; expiresAt?: string; amountCents?: number; } export interface CreatePlatformInvoiceFromSubscriptionInput { tenantId: string; subscriptionId?: string; status?: string; dueDate?: string; note?: string; } export interface CreatePlatformInvoicesBatchFromSubscriptionsInput { tenantIds?: string[]; subscriptionIds?: string[]; daysAhead?: number; status?: string; dueDate?: string; note?: string; dryRun?: boolean; } export interface ConfirmPlatformInvoicePaymentInput { tenantId: string; invoiceId: string; amountCents: number; provider?: string; method?: string; providerTradeNo?: string; } export interface ProcessPlatformOverdueInvoicesInput { dryRun?: boolean; channel?: string; limit?: number; } export interface RecordPlatformUsageInput { tenantId: string; metricKey: string; metricValue: number; periodStart: string; periodEnd: string; } export interface UpsertPlatformQuestionBankGrantInput { id?: string; sourceQuestionBankId: string; grantScope: string; allowedPlanCodes?: string[]; allowedTenantIds?: string[]; allowedRegionIds?: string[]; allowedSubjectIds?: string[]; status?: string; startsAt?: string; expiresAt?: string; } export async function loadPlatformOverview() { return apiRequest<{ item?: PlatformOverview }>('/api/platform-admin/overview', { tenantId: null }); } export async function loadPlatformPlans(includeArchived = false) { return apiRequest<{ items?: PlatformSaasPlan[] }>('/api/platform-admin/plans', { query: { includeArchived }, tenantId: null, }); } export async function loadPlatformTenants(query: { q?: string; status?: string; billingStatus?: string; limit?: number } = {}) { return apiRequest<{ items?: PlatformTenantItem[] }>('/api/platform-admin/tenants', { query: { ...query, limit: query.limit || 80 }, tenantId: null, }); } export async function loadPlatformTenantDetail(tenantId: string) { return apiRequest<{ item?: PlatformTenantDetail }>('/api/platform-admin/tenants/detail', { query: { tenantId }, tenantId: null, }); } export async function loadPlatformAuditLogs(query: { tenantId?: string; action?: string; targetType?: string; actorUserId?: string; q?: string; limit?: number } = {}) { return apiRequest<{ items?: PlatformAuditLogItem[] }>('/api/platform-admin/audit-logs', { query: { ...query, limit: query.limit || 100 }, tenantId: null, }); } export async function exportPlatformAuditLogs(query: { tenantId?: string; action?: string; targetType?: string; actorUserId?: string; q?: string; startDate?: string; endDate?: string; format?: 'csv' | 'json'; limit?: number; } = {}) { return apiRequest<{ item?: PlatformAuditExportItem }>('/api/platform-admin/audit-logs/export', { query: { format: 'csv', ...query, limit: query.limit || 1000 }, tenantId: null, }); } export async function loadPlatformAuditAlertRules(query: { enabled?: boolean; limit?: number } = {}) { return apiRequest<{ items?: PlatformAuditAlertRuleItem[] }>('/api/platform-admin/audit-alert-rules', { query, tenantId: null, }); } export async function loadPlatformAuditAlerts(query: { tenantId?: string; status?: string; severity?: string; ruleCode?: string; q?: string; limit?: number; } = {}) { return apiRequest<{ items?: PlatformAuditAlertItem[] }>('/api/platform-admin/audit-alerts', { query: { ...query, limit: query.limit || 50 }, tenantId: null, }); } export async function updatePlatformAuditAlertStatus(input: { alertId: string; status: 'acknowledged' | 'resolved' | 'ignored'; resolutionNote?: string; }) { return apiRequest<{ item?: PlatformAuditAlertItem }>('/api/platform-admin/audit-alerts/status', { method: 'POST', body: input, tenantId: null, }); } export async function loadPlatformAuditNotificationChannels(query: { enabled?: boolean; provider?: string; limit?: number; } = {}) { return apiRequest<{ items?: PlatformAuditNotificationChannelItem[] }>('/api/platform-admin/audit-notification-channels', { query: { ...query, limit: query.limit || 50 }, tenantId: null, }); } export async function loadPlatformAuditNotificationEvents(query: { channelId?: string; alertId?: string; status?: string; provider?: string; limit?: number; } = {}) { return apiRequest<{ items?: PlatformAuditNotificationEventItem[] }>('/api/platform-admin/audit-notification-events', { query: { ...query, limit: query.limit || 50 }, tenantId: null, }); } export async function loadPlatformDunningNotificationChannels(query: { enabled?: boolean; provider?: string; limit?: number; } = {}) { return apiRequest<{ items?: PlatformDunningNotificationChannelItem[] }>('/api/platform-admin/dunning-notification-channels', { query: { ...query, limit: query.limit || 50 }, tenantId: null, }); } export async function loadPlatformDunningNotificationEvents(query: { channelId?: string; reminderId?: string; invoiceId?: string; tenantId?: string; status?: string; provider?: string; limit?: number; } = {}) { return apiRequest<{ items?: PlatformDunningNotificationEventItem[] }>('/api/platform-admin/dunning-notification-events', { query: { ...query, limit: query.limit || 50 }, tenantId: null, }); } export async function loadPlatformInvoices(query: { tenantId?: string; status?: string; limit?: number } = {}) { return apiRequest<{ items?: PlatformInvoiceItem[] }>('/api/platform-admin/invoices', { query: { ...query, limit: query.limit || 80 }, tenantId: null, }); } export async function loadPlatformUsage(query: { tenantId?: string; limit?: number } = {}) { return apiRequest<{ items?: PlatformUsageItem[] }>('/api/platform-admin/usage', { query: { ...query, limit: query.limit || 100 }, tenantId: null, }); } export async function loadPlatformSubscriptionInvoiceCandidates(query: { tenantIds?: string; subscriptionIds?: string; daysAhead?: number; includeExisting?: boolean; limit?: number } = {}) { return apiRequest<{ items?: PlatformSubscriptionInvoiceCandidate[] }>('/api/platform-admin/invoices/subscription-candidates', { query: { ...query, limit: query.limit || 100 }, tenantId: null, }); } export async function loadPlatformQuestionBanks(query: { q?: string; status?: string; includeTenantBanks?: boolean; limit?: number } = {}) { return apiRequest<{ items?: PlatformQuestionBankItem[] }>('/api/platform-admin/question-banks', { query: { status: 'active', ...query, limit: query.limit || 80 }, tenantId: null, }); } export async function loadPlatformQuestionBankGrants(query: { questionBankId?: string; status?: string; limit?: number } = {}) { return apiRequest<{ items?: PlatformQuestionBankGrant[] }>('/api/platform-admin/question-bank-grants', { query: { ...query, limit: query.limit || 120 }, tenantId: null, }); } export async function createPlatformTenant(input: CreatePlatformTenantInput) { return apiRequest<{ item?: PlatformTenantItem }>('/api/platform-admin/tenants', { method: 'POST', body: input, tenantId: null, }); } export async function updatePlatformTenantStatus(input: UpdatePlatformTenantStatusInput) { return apiRequest<{ item?: PlatformTenantItem }>('/api/platform-admin/tenants/status', { method: 'PATCH', body: input, tenantId: null, }); } export async function upsertPlatformTenantBillingProfile(input: UpsertPlatformTenantBillingProfileInput) { return apiRequest<{ item?: PlatformTenantBillingProfile }>('/api/platform-admin/tenants/billing-profile', { method: 'PUT', body: input, tenantId: null, }); } export async function createPlatformSubscription(input: CreatePlatformSubscriptionInput) { return apiRequest<{ item?: Record }>('/api/platform-admin/subscriptions', { method: 'POST', body: input, tenantId: null, }); } export async function createPlatformInvoiceFromSubscription(input: CreatePlatformInvoiceFromSubscriptionInput) { return apiRequest<{ item?: Record }>('/api/platform-admin/invoices/from-subscription', { method: 'POST', body: input, tenantId: null, }); } export async function createPlatformInvoicesBatchFromSubscriptions(input: CreatePlatformInvoicesBatchFromSubscriptionsInput) { return apiRequest<{ item?: { dryRun?: boolean; createdCount?: number; skippedCount?: number; items?: Array; skipped?: Array>; }; }>('/api/platform-admin/invoices/from-subscriptions-batch', { method: 'POST', body: input, tenantId: null, }); } export async function confirmPlatformInvoicePayment(input: ConfirmPlatformInvoicePaymentInput) { return apiRequest<{ item?: Record }>('/api/platform-admin/invoices/payments/manual-confirm', { method: 'POST', body: input, tenantId: null, }); } export async function processPlatformOverdueInvoices(input: ProcessPlatformOverdueInvoicesInput = {}) { return apiRequest<{ item?: { dryRun?: boolean; processed?: number; markedOverdue?: number; reminderCreated?: number; skippedReminder?: number; items?: Array; }; }>('/api/platform-admin/invoices/process-overdue', { method: 'POST', body: input, tenantId: null, }); } export async function loadPlatformInvoiceReminders(query: { tenantId?: string; invoiceId?: string; status?: string; reminderType?: string; limit?: number } = {}) { return apiRequest<{ items?: PlatformInvoiceReminderItem[] }>('/api/platform-admin/invoices/reminders', { query: { ...query, limit: query.limit || 100 }, tenantId: null, }); } export async function recordPlatformUsage(input: RecordPlatformUsageInput) { return apiRequest<{ item?: Record }>('/api/platform-admin/usage', { method: 'POST', body: input, tenantId: null, }); } export async function upsertPlatformQuestionBankGrant(input: UpsertPlatformQuestionBankGrantInput) { return apiRequest<{ item?: PlatformQuestionBankGrant }>('/api/platform-admin/question-bank-grants', { method: 'PUT', body: input, tenantId: null, }); }