/**
 * 账单管理工具函数
 *
 * 提供账单相关的通用工具函数
 *
 * @module utils/billing
 */

import { $t } from '@/locales'
import {
  BillingType,
  ExportFormat,
  TenantPaymentMethod,
  TenantPaymentStatus
} from '@/enums/Billing'

/**
 * 格式化账单状态为文本
 * @param status 账单状态
 * @returns 状态文本
 */
export function formatBillingStatus(status: number): string {
  const statusMap: Record<number, string> = {
    0: $t('billing.status.pending'),
    1: $t('billing.status.paid'),
    2: $t('billing.status.overdue'),
    3: $t('billing.status.cancelled'),
    // 兼容：若后端未来扩展状态值（或历史数据脏值）
    4: $t('billing.status.cancelled')
  }
  return statusMap[status] || '未知'
}

/**
 * 获取账单状态对应的 Element Plus Tag 类型
 * @param status 账单状态
 * @returns Tag 类型
 */
export function getBillingStatusType(status: number): 'success' | 'warning' | 'danger' | 'info' {
  const typeMap: Record<number, 'success' | 'warning' | 'danger' | 'info'> = {
    0: 'warning',
    1: 'success',
    2: 'danger',
    3: 'info',
    4: 'info'
  }
  return typeMap[status] || 'info'
}

/**
 * 获取账单状态颜色
 * @param status 账单状态
 * @returns 颜色值
 */
export function getBillingStatusColor(status: number): string {
  const colorMap: Record<number, string> = {
    0: 'var(--el-color-warning)',
    1: 'var(--el-color-success)',
    2: 'var(--el-color-danger)',
    3: 'var(--el-color-info)',
    4: 'var(--el-color-info)'
  }
  return colorMap[status] || 'var(--el-color-info)'
}

/**
 * 格式化账单类型为文本
 * @param type 账单类型
 * @returns 类型文本
 */
export function formatBillingType(type?: BillingType | number | null): string {
  if (type === undefined || type === null) return '-'
  const typeMap: Record<number, string> = {
    [BillingType.Subscription]: $t('billing.billingType.subscription'),
    [BillingType.QuotaPurchase]: $t('billing.billingType.quotaPurchase'),
    [BillingType.Manual]: $t('billing.billingType.manual'),
    [BillingType.Renewal]: $t('billing.billingType.renewal')
  }
  return typeMap[type as number] || '未知'
}

/**
 * 格式化支付方式为文本
 * @param method 支付方式
 * @returns 方式文本
 */
export function formatPaymentMethod(method: TenantPaymentMethod | number): string {
  const methodMap: Record<number, string> = {
    [TenantPaymentMethod.Online]: $t('billing.paymentMethod.online'),
    [TenantPaymentMethod.BankTransfer]: $t('billing.paymentMethod.bankTransfer'),
    [TenantPaymentMethod.Other]: $t('billing.paymentMethod.other')
  }
  return methodMap[method as number] || '未知'
}

/**
 * 获取支付方式图标名称
 * @param method 支付方式
 * @returns 图标名称（Element Plus Icon）
 */
export function getPaymentMethodIcon(method: TenantPaymentMethod | number): string {
  const iconMap: Record<number, string> = {
    [TenantPaymentMethod.Online]: 'CreditCard',
    [TenantPaymentMethod.BankTransfer]: 'Wallet',
    [TenantPaymentMethod.Other]: 'Money'
  }
  return iconMap[method as number] || 'Money'
}

/**
 * 格式化支付状态为文本
 * @param status 支付状态
 * @returns 状态文本
 */
export function formatPaymentStatus(status: TenantPaymentStatus | number): string {
  const statusMap: Record<number, string> = {
    [TenantPaymentStatus.Pending]: $t('billing.paymentStatus.pending'),
    [TenantPaymentStatus.Success]: $t('billing.paymentStatus.success'),
    [TenantPaymentStatus.Failed]: $t('billing.paymentStatus.failed'),
    [TenantPaymentStatus.Refunded]: $t('billing.paymentStatus.refunded')
  }
  return statusMap[status as number] || '未知'
}

/**
 * 获取支付状态对应的 Tag 类型
 * @param status 支付状态
 * @returns Tag 类型
 */
export function getPaymentStatusType(
  status: TenantPaymentStatus | number
): 'success' | 'warning' | 'danger' | 'info' {
  const typeMap: Record<number, 'success' | 'warning' | 'danger' | 'info'> = {
    [TenantPaymentStatus.Pending]: 'warning' as const,
    [TenantPaymentStatus.Success]: 'success' as const,
    [TenantPaymentStatus.Failed]: 'danger' as const,
    [TenantPaymentStatus.Refunded]: 'info' as const
  }
  return typeMap[status as number] || 'info'
}

/**
 * 计算逾期天数
 * @param dueDate 到期日期（ISO 8601 字符串）
 * @returns 逾期天数（负数表示未到期）
 */
export function calculateDaysOverdue(dueDate: string): number {
  const due = new Date(dueDate)
  const now = new Date()
  const diff = now.getTime() - due.getTime()
  return Math.floor(diff / (1000 * 60 * 60 * 24))
}

/**
 * 判断账单是否即将到期（7天内）
 * @param dueDate 到期日期
 * @returns 是否即将到期
 */
export function isBillingDueSoon(dueDate: string): boolean {
  const days = calculateDaysOverdue(dueDate)
  return days >= -7 && days < 0
}

function pad2(n: number): string {
  return String(n).padStart(2, '0')
}

/**
 * 格式化日期时间（YYYY-MM-DD HH:mm）
 * @param value ISO 字符串 / Date 可解析值
 */
export function formatDateTime(value?: string | null): string {
  if (!value) return '-'
  const date = new Date(value)
  if (Number.isNaN(date.getTime())) return '-'
  return `${date.getFullYear()}-${pad2(date.getMonth() + 1)}-${pad2(date.getDate())} ${pad2(date.getHours())}:${pad2(date.getMinutes())}`
}

/**
 * 格式化日期（YYYY-MM-DD）
 * @param value ISO 字符串 / Date 可解析值
 */
export function formatDate(value?: string | null): string {
  if (!value) return '-'
  const date = new Date(value)
  if (Number.isNaN(date.getTime())) return '-'
  return `${date.getFullYear()}-${pad2(date.getMonth() + 1)}-${pad2(date.getDate())}`
}

/**
 * 格式化金额（带货币符号）
 * @param amount 金额
 * @param currency 货币类型（默认 CNY）
 * @returns 格式化后的金额
 */
export function formatAmount(amount?: number | null, currency: string = 'CNY'): string {
  const safeAmount = Number.isFinite(amount as number) ? (amount as number) : 0
  const currencySymbol = currency === 'CNY' ? '¥' : currency === 'USD' ? '$' : ''
  if (currencySymbol) {
    return `${currencySymbol}${safeAmount.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`
  }
  return `${currency} ${safeAmount.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`
}

/**
 * 生成导出文件名
 * @param format 导出格式
 * @param dateRange 日期范围（可选）
 * @returns 文件名
 */
export function generateExportFileName(
  format: ExportFormat,
  dateRange?: { start?: string; end?: string }
): string {
  const timestamp = new Date().toISOString().split('T')[0] // YYYY-MM-DD
  const formatExt =
    format === ExportFormat.Excel ? 'xlsx' : format === ExportFormat.Pdf ? 'pdf' : 'csv'

  const baseName = $t('billing.export.fileName') || 'billing_export'
  let fileName = `${baseName}_${timestamp}`
  if (dateRange?.start && dateRange?.end) {
    fileName = `${baseName}_${dateRange.start}_to_${dateRange.end}`
  }

  // Windows 文件名非法字符处理
  const safeName = fileName.replace(/[\\/:*?"<>|]/g, '_').replace(/\s+/g, '_')

  return `${safeName}.${formatExt}`
}

/**
 * 解析账单明细 JSON
 * @param lineItemsJson 明细 JSON 字符串
 * @returns 明细数组
 */
export function parseLineItems(lineItemsJson?: string): Api.Billing.BillingLineItemDto[] {
  if (!lineItemsJson) return []
  try {
    return JSON.parse(lineItemsJson)
  } catch {
    return []
  }
}

/**
 * 计算账单总金额（包含税费和折扣）
 * @param billing 账单数据
 * @returns 总金额
 */
export function calculateTotalAmount(
  billing: Partial<Api.Billing.BillingListDto | Api.Billing.BillingDetailDto>
): number {
  const { amountDue = 0, discountAmount = 0, taxAmount = 0 } = billing
  return amountDue - discountAmount + taxAmount
}

/**
 * 计算未付款金额
 * @param billing 账单数据
 * @returns 未付款金额
 */
export function calculateRemainingAmount(
  billing: Partial<Api.Billing.BillingListDto | Api.Billing.BillingDetailDto>
): number {
  const total = calculateTotalAmount(billing)
  const paid = billing.amountPaid || 0
  return Math.max(total - paid, 0)
}

/**
 * 格式化导出格式为文本
 * @param format 导出格式
 * @returns 格式文本
 */
export function formatExportFormat(format: ExportFormat): string {
  const formatMap = {
    [ExportFormat.Excel]: 'Excel',
    [ExportFormat.Pdf]: 'PDF',
    [ExportFormat.Csv]: 'CSV'
  }
  return formatMap[format] || '未知'
}

/**
 * 验证金额格式
 * @param amount 金额字符串
 * @returns 是否有效
 */
export function validateAmount(amount: string): boolean {
  const regex = /^\d+(\.\d{1,2})?$/
  return regex.test(amount) && parseFloat(amount) > 0
}

/**
 * 格式化日期范围为查询参数
 * @param dateRange 日期范围（数组格式 [start, end]）
 * @returns 查询参数
 */
export function formatDateRangeParams(dateRange?: [string, string] | null): {
  StartDate?: string
  EndDate?: string
} {
  if (!dateRange || dateRange.length !== 2) return {}
  return {
    StartDate: dateRange[0],
    EndDate: dateRange[1]
  }
}
