/**
 * 支付工具函数
 * 封装微信支付相关逻辑
 */

import Taro from '@tarojs/taro'

/**
 * 微信支付参数类型
 */
export interface WechatPaymentParams {
  timeStamp: string
  nonceStr: string
  package: string
  signType: string
  paySign: string
}

/**
 * 支付结果类型
 */
export interface PaymentResult {
  success: boolean
  type?: 'success' | 'cancel' | 'fail' | 'error'
  message?: string
  result?: any
}

/**
 * 调用微信支付
 * @param paymentData 支付参数
 * @returns 支付结果
 */
export const requestWechatPayment = async (paymentData: WechatPaymentParams): Promise<PaymentResult> => {
  try {
    const result = await Taro.requestPayment({
      timeStamp: paymentData.timeStamp,
      nonceStr: paymentData.nonceStr,
      package: paymentData.package,
      signType: paymentData.signType as any, // Taro类型定义问题，使用any绕过
      paySign: paymentData.paySign
    })

    return {
      success: true,
      type: 'success',
      result
    }
  } catch (error: any) {
    console.error('微信支付调用失败:', error)

    // 根据错误码处理不同场景
    if (error.errMsg?.includes('cancel')) {
      return {
        success: false,
        type: 'cancel',
        message: '用户取消支付'
      }
    } else if (error.errMsg?.includes('fail')) {
      return {
        success: false,
        type: 'fail',
        message: '支付失败'
      }
    } else {
      return {
        success: false,
        type: 'error',
        message: error.errMsg || '支付异常'
      }
    }
  }
}

/**
 * 验证支付参数
 * @param paymentData 支付参数
 * @returns 验证结果
 */
export const validatePaymentParams = (paymentData: WechatPaymentParams): { valid: boolean; errors: string[] } => {
  const errors: string[] = []

  if (!paymentData.timeStamp) {
    errors.push('时间戳不能为空')
  }

  if (!paymentData.nonceStr) {
    errors.push('随机字符串不能为空')
  }

  if (!paymentData.package) {
    errors.push('预支付ID不能为空')
  }

  if (!paymentData.signType) {
    errors.push('签名类型不能为空')
  }

  if (!paymentData.paySign) {
    errors.push('签名不能为空')
  }

  return {
    valid: errors.length === 0,
    errors
  }
}

/**
 * 处理支付金额
 * @param amount 金额（元）
 * @returns 金额（分）
 */
export const formatPaymentAmount = (amount: number): number => {
  // 微信支付金额单位为分，需要乘以100
  return Math.round(amount * 100)
}

/**
 * 检查支付环境
 * @returns 是否支持微信支付
 */
export const checkPaymentEnvironment = async (): Promise<boolean> => {
  try {
    // 检查是否在微信小程序环境中
    if (typeof Taro.requestPayment === 'undefined') {
      console.error('当前环境不支持微信支付')
      return false
    }

    // 可以添加更多环境检查逻辑
    return true
  } catch (error) {
    console.error('检查支付环境失败:', error)
    return false
  }
}

/**
 * 支付安全验证
 * @param orderId 订单ID
 * @param amount 支付金额
 * @param paymentParams 支付参数
 * @returns 验证结果
 */
export const validatePaymentSecurity = (
  orderId: number,
  amount: number,
  paymentParams: WechatPaymentParams
): { valid: boolean; reason?: string } => {
  // 验证订单ID
  if (!orderId || orderId <= 0) {
    return { valid: false, reason: '订单ID无效' }
  }

  // 验证金额
  if (!amount || amount <= 0) {
    return { valid: false, reason: '支付金额无效' }
  }

  // 验证支付参数
  const paramValidation = validatePaymentParams(paymentParams)
  if (!paramValidation.valid) {
    return {
      valid: false,
      reason: `支付参数错误: ${paramValidation.errors.join(', ')}`
    }
  }

  // 时间戳验证（防止重放攻击）
  const timestamp = parseInt(paymentParams.timeStamp)
  const currentTime = Math.floor(Date.now() / 1000)
  const timeDiff = Math.abs(currentTime - timestamp)

  // 时间戳应该在5分钟内有效
  if (timeDiff > 300) {
    return { valid: false, reason: '支付参数已过期，请重新发起支付' }
  }

  // 随机字符串长度验证 - 放宽限制以适应微信支付实际返回
  if (!paymentParams.nonceStr || paymentParams.nonceStr.length < 8) {
    return { valid: false, reason: '随机字符串长度无效' }
  }

  // 签名类型验证 - 放宽限制以适应微信支付实际返回
  if (!paymentParams.signType) {
    return { valid: false, reason: '签名类型不能为空' }
  }

  // 预支付ID格式验证 - 放宽限制以适应微信支付实际返回
  if (!paymentParams.package) {
    return { valid: false, reason: '预支付ID不能为空' }
  }

  // 签名长度验证 - 放宽限制以适应微信支付实际返回
  if (!paymentParams.paySign || paymentParams.paySign.length < 16) {
    return { valid: false, reason: '签名长度过短' }
  }

  return { valid: true }
}

/**
 * 生成支付参数哈希（用于防篡改验证）
 * @param paymentParams 支付参数
 * @returns 参数哈希
 */
export const generatePaymentParamsHash = (paymentParams: WechatPaymentParams): string => {
  const paramsString = [
    paymentParams.timeStamp,
    paymentParams.nonceStr,
    paymentParams.package,
    paymentParams.signType
  ].join('&')

  // 在实际项目中，这里应该使用更安全的哈希算法
  // 这里使用简单的哈希作为示例
  let hash = 0
  for (let i = 0; i < paramsString.length; i++) {
    const char = paramsString.charCodeAt(i)
    hash = ((hash << 5) - hash) + char
    hash = hash & hash // 转换为32位整数
  }
  return Math.abs(hash).toString(16)
}

/**
 * 验证支付参数完整性
 * @param originalParams 原始支付参数
 * @param receivedParams 接收到的支付参数
 * @returns 验证结果
 */
export const verifyPaymentParamsIntegrity = (
  originalParams: WechatPaymentParams,
  receivedParams: WechatPaymentParams
): { valid: boolean; reason?: string } => {
  const originalHash = generatePaymentParamsHash(originalParams)
  const receivedHash = generatePaymentParamsHash(receivedParams)

  if (originalHash !== receivedHash) {
    return { valid: false, reason: '支付参数被篡改' }
  }

  return { valid: true }
}

/**
 * 支付金额一致性验证
 * @param expectedAmount 预期金额（元）
 * @param paymentAmount 支付金额（分）
 * @returns 验证结果
 */
export const validateAmountConsistency = (
  expectedAmount: number,
  paymentAmount: number
): { valid: boolean; reason?: string } => {
  const expectedInFen = Math.round(expectedAmount * 100)

  if (expectedInFen !== paymentAmount) {
    return {
      valid: false,
      reason: `金额不一致: 预期 ${expectedInFen} 分，实际 ${paymentAmount} 分`
    }
  }

  return { valid: true }
}

/**
 * 支付频率限制检查
 */
export class PaymentRateLimiter {
  private static instance: PaymentRateLimiter
  private attempts: Map<number, number[]> = new Map()
  private readonly MAX_ATTEMPTS = 5
  private readonly TIME_WINDOW = 60000 // 1分钟

  private constructor() {}

  static getInstance(): PaymentRateLimiter {
    if (!PaymentRateLimiter.instance) {
      PaymentRateLimiter.instance = new PaymentRateLimiter()
    }
    return PaymentRateLimiter.instance
  }

  /**
   * 检查是否超过支付频率限制
   */
  isRateLimited(orderId: number): { limited: boolean; remainingTime?: number } {
    const now = Date.now()
    const attempts = this.attempts.get(orderId) || []

    // 清理过期的尝试记录
    const recentAttempts = attempts.filter(time => now - time < this.TIME_WINDOW)
    this.attempts.set(orderId, recentAttempts)

    if (recentAttempts.length >= this.MAX_ATTEMPTS) {
      const oldestAttempt = Math.min(...recentAttempts)
      const remainingTime = this.TIME_WINDOW - (now - oldestAttempt)
      return { limited: true, remainingTime }
    }

    return { limited: false }
  }

  /**
   * 记录支付尝试
   */
  recordAttempt(orderId: number): void {
    const attempts = this.attempts.get(orderId) || []
    attempts.push(Date.now())
    this.attempts.set(orderId, attempts)
  }

  /**
   * 清除支付尝试记录
   */
  clearAttempts(orderId: number): void {
    this.attempts.delete(orderId)
  }
}

/**
 * 支付重试逻辑
 * @param paymentFn 支付函数
 * @param maxRetries 最大重试次数
 * @param delay 重试延迟（毫秒）
 * @returns 支付结果
 */
export const retryPayment = async (
  paymentFn: () => Promise<PaymentResult>,
  maxRetries: number = 3,
  delay: number = 1000
): Promise<PaymentResult> => {
  let lastError: any = null

  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      const result = await paymentFn()

      if (result.success) {
        return result
      }

      // 如果是用户取消，不重试
      if (result.type === 'cancel') {
        return result
      }

      lastError = result

      if (attempt < maxRetries) {
        console.log(`支付失败，第${attempt}次重试...`)
        await new Promise(resolve => setTimeout(resolve, delay))
      }
    } catch (error) {
      lastError = error

      if (attempt < maxRetries) {
        console.log(`支付异常，第${attempt}次重试...`)
        await new Promise(resolve => setTimeout(resolve, delay))
      }
    }
  }

  return {
    success: false,
    type: 'error',
    message: `支付失败，已重试${maxRetries}次: ${lastError?.message || '未知错误'}`
  }
}

/**
 * 支付状态枚举
 */
export enum PaymentStatus {
  PENDING = '待支付',
  PROCESSING = '支付中',
  SUCCESS = '支付成功',
  FAILED = '支付失败',
  REFUNDED = '已退款',
  CLOSED = '已关闭'
}

/**
 * 支付状态管理类
 */
export class PaymentStateManager {
  private static instance: PaymentStateManager
  private state: Map<number, PaymentStatus> = new Map()

  private constructor() {}

  static getInstance(): PaymentStateManager {
    if (!PaymentStateManager.instance) {
      PaymentStateManager.instance = new PaymentStateManager()
    }
    return PaymentStateManager.instance
  }

  /**
   * 设置支付状态
   */
  setPaymentState(orderId: number, status: PaymentStatus): void {
    this.state.set(orderId, status)
    console.log(`订单 ${orderId} 支付状态更新为: ${status}`)
  }

  /**
   * 获取支付状态
   */
  getPaymentState(orderId: number): PaymentStatus | undefined {
    return this.state.get(orderId)
  }

  /**
   * 检查是否重复支付
   */
  isDuplicatePayment(orderId: number): boolean {
    const currentStatus = this.getPaymentState(orderId)
    return currentStatus === PaymentStatus.PROCESSING || currentStatus === PaymentStatus.SUCCESS
  }

  /**
   * 清除支付状态
   */
  clearPaymentState(orderId: number): void {
    this.state.delete(orderId)
  }

  /**
   * 获取所有支付状态
   */
  getAllPaymentStates(): Map<number, PaymentStatus> {
    return new Map(this.state)
  }
}

/**
 * 支付超时处理
 * @param orderId 订单ID
 * @param timeout 超时时间（毫秒）
 * @returns 超时Promise
 */
export const createPaymentTimeout = (timeout: number = 30000): Promise<PaymentResult> => {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve({
        success: false,
        type: 'error',
        message: '支付超时，请检查网络或重试'
      })
    }, timeout)
  })
}

/**
 * 支付状态同步
 * @param orderId 订单ID
 * @param expectedStatus 期望状态
 * @param maxAttempts 最大尝试次数
 * @param interval 检查间隔（毫秒）
 * @returns 同步结果
 */
export const syncPaymentStatus = async (
  orderId: number,
  expectedStatus: PaymentStatus,
  maxAttempts: number = 10,
  interval: number = 2000
): Promise<{ synced: boolean; currentStatus?: PaymentStatus }> => {
  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
    try {
      // 这里可以调用后端API查询实际支付状态
      // 暂时使用状态管理器模拟
      const stateManager = PaymentStateManager.getInstance()
      const currentStatus = stateManager.getPaymentState(orderId)

      if (currentStatus === expectedStatus) {
        return { synced: true, currentStatus }
      }

      console.log(`支付状态同步中... 第${attempt}次检查，当前状态: ${currentStatus}`)

      if (attempt < maxAttempts) {
        await new Promise(resolve => setTimeout(resolve, interval))
      }
    } catch (error) {
      console.error(`支付状态同步失败，第${attempt}次尝试:`, error)
    }
  }

  return { synced: false }
}