<template>
  <a-modal
    :destroy-on-close="true"
    :footer="footerContent"
    :mask-closable="false"
    :open="visible"
    :title="title"
    :width="payMethod === 'native' ? 480 : 420"
    @cancel="handleClose"
  >
    <!-- 订单信息 -->
    <div class="mb-5">
      <a-descriptions :column="1" bordered size="small">
        <a-descriptions-item label="订单号">
          <span class="font-mono text-sm">{{ orderNo }}</span>
        </a-descriptions-item>
        <a-descriptions-item label="订单金额">
          <span class="text-xl font-bold text-orange-500">¥{{ payPrice }}</span>
        </a-descriptions-item>
      </a-descriptions>
    </div>

    <!-- 支付方式选择 -->
    <div v-if="!started" class="space-y-3">
      <div class="text-sm text-gray-500 mb-2">请选择支付方式</div>

      <!-- 微信支付 -->
      <div
        v-if="availableMethods.wechat"
        :class="{ active: selectedMethod === 'wechat' }"
        class="pay-method-item"
        @click="selectedMethod = 'wechat'"
      >
        <svg class="h-8 w-8" fill="#07C160" viewBox="0 0 24 24">
          <path d="M8.691 2.188C3.891 2.188 0 5.476 0 9.53c0 2.212 1.17 4.203 3.002 5.55a.59.59 0 0 1 .213.665l-.39 1.48c-.019.07-.048.141-.048.213 0 .163.13.295.29.295a.326.326 0 0 0 .167-.054l1.903-1.114a.864.864 0 0 1 .717-.098 10.16 10.16 0 0 0 2.837.403c.276 0 .543-.027.811-.05-.857-2.578.157-4.972 1.932-6.446 1.703-1.415 3.882-1.98 5.853-1.838-.576-3.583-4.196-6.348-8.596-6.348zM5.785 5.991c.642 0 1.162.529 1.162 1.18a1.17 1.17 0 0 1-1.162 1.178A1.17 1.17 0 0 1 4.623 7.17c0-.651.52-1.18 1.162-1.18zm5.813 0c.642 0 1.162.529 1.162 1.18a1.17 1.17 0 0 1-1.162 1.178 1.17 1.17 0 0 1-1.162-1.178c0-.651.52-1.18 1.162-1.18zm5.34 2.867c-1.797-.052-3.746.512-5.28 1.786-1.72 1.428-2.687 3.72-1.78 6.22.942 2.453 3.666 4.229 6.884 4.229.826 0 1.622-.12 2.361-.336a.722.722 0 0 1 .598.082l1.584.926a.272.272 0 0 0 .14.047c.134 0 .24-.11.24-.245 0-.06-.023-.12-.038-.177l-.327-1.233a.582.582 0 0 1-.023-.156.49.49 0 0 1 .201-.398C23.024 18.48 24 16.82 24 14.98c0-3.21-2.931-5.837-6.656-6.088V8.87a5.755 5.755 0 0 0-.407-.012zm-1.155 2.26c.535 0 .969.44.969.982a.976.976 0 0 1-.969.983.976.976 0 0 1-.969-.983c0-.542.434-.982.97-.982zm4.857 0c.535 0 .969.44.969.982a.976.976 0 0 1-.969.983.976.976 0 0 1-.969-.983c0-.542.434-.982.969-.982z"/>
        </svg>
        <div class="flex-1 ml-3">
          <div class="font-medium">微信支付</div>
          <div class="text-xs text-gray-400">推荐</div>
        </div>
        <a-radio :checked="selectedMethod === 'wechat'" />
      </div>

      <!-- 支付宝 -->
      <div
        v-if="availableMethods.alipay"
        :class="{ active: selectedMethod === 'alipay' }"
        class="pay-method-item"
        @click="selectedMethod = 'alipay'"
      >
        <svg class="h-8 w-8" fill="#1677FF" viewBox="0 0 24 24">
          <path d="M21.97 11.1c-1.23-.79-2.75-1.04-4.33-.86-1.09-1.65-2.78-2.59-4.72-2.59-2.91 0-5.27 2.27-5.27 5.06 0 2.07 1.25 3.89 3.1 4.78V13.2c-.42-.11-.86-.17-1.32-.17-2.56 0-4.64 2.03-4.64 4.53 0 2.51 2.08 4.53 4.64 4.53.32 0 .63-.03.93-.08v2.58c-.31.04-.63.06-.95.06-3.45 0-6.25-2.74-6.25-6.1 0-3.36 2.8-6.1 6.25-6.1 1.01 0 1.95.24 2.78.67-.05-.32-.08-.65-.08-.99 0-2.59 2.15-4.69 4.79-4.69 1.52 0 2.88.68 3.78 1.75.19-.03.38-.05.58-.05 1.94 0 3.51 1.57 3.51 3.51 0 1.06-.48 2-1.24 2.64 1.1.4 1.83 1.47 1.83 2.67 0 1.73-1.49 3.13-3.32 3.13-.65 0-1.26-.18-1.78-.5.06.22.1.45.1.69 0 2.07-1.7 3.75-3.79 3.75-.45 0-.89-.07-1.3-.22v2.49c.45.13.92.2 1.4.2 2.97 0 5.38-2.36 5.38-5.26 0-2.22-1.32-4.15-3.22-4.93zm-8.16 2.09c-.46 0-.84-.37-.84-.83s.38-.84.84-.84.84.38.84.84-.38.83-.84.83zm5.14-.83c0-.46.38-.84.84-.84s.84.38.84.84-.38.83-.84.83-.84-.37-.84-.83zm-.87 2.49l-.69-.55c-.34-.27-.55-.67-.55-1.1 0-.74.61-1.34 1.36-1.34.46 0 .88.24 1.12.62l.77.62c.01-.35-.28-.67-.64-.8v-.06h-.09c-.54 0-.98-.44-.98-.98s.44-.98.98-.98.98.44.98.98v.03h.05l.15.12c.57.45.91 1.14.91 1.87 0 1.21-.89 2.23-2.05 2.48l-.33-.91h-.01zm-2.24-1.38h.08c.34 0 .61-.27.61-.61s-.27-.61-.61-.61h-.08v1.22zm.61 2.16c-.14.04-.29.06-.45.06h-.16v-1.16h.25c.26 0 .47.1.47.36 0 .38-.06.67-.11.74zm-.11-3.52c.18 0 .32-.14.32-.32s-.14-.32-.32-.32-.32.14-.32.32.14.32.32.32zm0 1.86c-.18 0-.32.14-.32.32s.14.32.32.32.32-.14.32-.32-.14-.32-.32-.32z"/>
        </svg>
        <div class="flex-1 ml-3">
          <div class="font-medium">支付宝</div>
          <div class="text-xs text-gray-400">安全便捷</div>
        </div>
        <a-radio :checked="selectedMethod === 'alipay'" />
      </div>

      <!-- 余额支付 -->
      <div
        v-if="availableMethods.balance && userBalance !== undefined"
        :class="{ active: selectedMethod === 'balance' }"
        class="pay-method-item"
        @click="selectedMethod = 'balance'"
      >
        <div class="flex items-center justify-center h-8 w-8 rounded-full bg-yellow-100 text-yellow-600">
          <WalletOutlined />
        </div>
        <div class="flex-1 ml-3">
          <div class="font-medium">余额支付</div>
          <div class="text-xs text-gray-400">可用余额：¥{{ userBalance }}</div>
        </div>
        <a-radio :checked="selectedMethod === 'balance'" />
      </div>
    </div>

    <!-- Native 二维码支付 -->
    <div v-else-if="payMethod === 'native' && !paid" class="text-center">
      <div v-if="loading" class="py-10">
        <a-spin size="large" />
        <div class="mt-3 text-gray-500">正在获取支付二维码...</div>
      </div>

      <div v-else-if="codeUrl" class="py-4">
        <div class="text-sm text-gray-500 mb-4">请使用微信/支付宝扫描下方二维码完成支付</div>
        <div class="flex justify-center bg-white p-4 rounded-lg">
          <a-qrcode :size="200" :value="codeUrl" />
        </div>
        <div class="mt-4 text-sm text-gray-500">
          <template v-if="countdown > 0">
            二维码 {{ countdown }} 秒后过期，请尽快支付
          </template>
          <a-button v-else size="small" type="link" @click="rebuildQrcode">
            二维码已过期，点击重新获取
          </a-button>
        </div>
      </div>

      <div v-else-if="errorMsg" class="py-10 text-center">
        <a-result :sub-title="errorMsg" status="error" title="获取二维码失败">
          <template #extra>
            <a-button type="primary" @click="rebuildQrcode">重试</a-button>
          </template>
        </a-result>
      </div>
    </div>

    <!-- 等待支付状态 -->
    <div v-else-if="!paid" class="text-center py-6">
      <a-spin size="large" />
      <div class="mt-4">
        <div class="text-base font-medium">等待支付中...</div>
        <div class="text-sm text-gray-500 mt-1">
          {{ selectedMethod === 'balance' ? '正在处理余额支付...' : '请在支付页面完成付款' }}
        </div>
      </div>
    </div>

    <!-- 支付成功 -->
    <div v-else class="text-center py-6">
      <a-result status="success" sub-title="您的订单已支付成功，页面即将跳转..." title="支付成功">
        <template #extra>
          <a-button type="primary" @click="handleSuccess">查看订单</a-button>
          <a-button @click="handleClose">继续逛逛</a-button>
        </template>
      </a-result>
    </div>

    <!-- 错误提示 -->
    <div v-if="errorMsg && !paid" class="mt-4">
      <a-alert :message="errorMsg" show-icon type="error" />
    </div>
  </a-modal>

  <!-- 支付宝跳转提示 -->
  <a-modal
    v-model:open="alipayRedirectVisible"
    :footer="null"
    :mask-closable="false"
    centered
    title="正在跳转支付宝"
  >
    <div class="text-center py-6">
      <a-spin size="large" />
      <div class="mt-4 text-base">正在跳转到支付宝支付页面</div>
      <div class="text-sm text-gray-500 mt-2">
        如果支付页面没有弹出，<a :href="alipayUrl" target="_blank">点击这里</a>继续支付
      </div>
    </div>
  </a-modal>
</template>

<script lang="ts" setup>
import { ref, computed, watch, h } from 'vue'
import { message } from 'ant-design-vue'
import { WalletOutlined } from '@ant-design/icons-vue'
import {
  detectPayEnvironment,
  isWechatBrowser,
  isAlipayBrowser,
  createWechatJsapiPay,
  createWechatH5Pay,
  createWechatNativePay,
  createAlipayPay,
  queryPayStatus
} from '@/api/payment'
import type { PayResult } from '@/api/payment'

/** Props */
const props = defineProps<{
  visible: boolean
  orderNo: string
  orderId?: number
  payPrice: string | number
  /** 可用支付方式，默认全部 */
  availableMethods?: {
    wechat?: boolean
    alipay?: boolean
    balance?: boolean
    native?: boolean
  }
  /** 用户余额（余额支付时） */
  userBalance?: number
  /** 标题 */
  title?: string
}>()

/** Emits */
const emit = defineEmits<{
  (e: 'update:visible', val: boolean): void
  (e: 'success', result: PayResult): void
  (e: 'close'): void
}>()

/** 状态 */
const selectedMethod = ref<'wechat' | 'alipay' | 'balance'>('wechat')
const started = ref(false)
const loading = ref(false)
const paid = ref(false)
const errorMsg = ref('')
const codeUrl = ref('')
const countdown = ref(0)
const alipayRedirectVisible = ref(false)
const alipayUrl = ref('')

// 轮询定时器
let pollTimer: ReturnType<typeof setTimeout> | null = null
let countdownTimer: ReturnType<typeof setInterval> | null = null

/** 默认可用支付方式 */
const defaultMethods = { wechat: true, alipay: true, balance: true, native: true }
const methods = computed(() => ({ ...defaultMethods, ...props.availableMethods }))

/** 实际使用的支付方式 */
const payMethod = computed(() => {
  if (!started.value) return 'select'

  const env = detectPayEnvironment()

  // 微信浏览器内 → JSAPI
  if (selectedMethod.value === 'wechat' && isWechatBrowser()) {
    return 'wechat_jsapi'
  }

  // 支付宝浏览器内 → 支付宝 WAP
  if (selectedMethod.value === 'alipay' && isAlipayBrowser()) {
    return 'alipay_wap'
  }

  // 桌面端 / 其他情况 → Native 或 H5
  if (env === 'desktop') {
    return 'native'
  }

  return 'h5'
})

/** 底部按钮 */
const footerContent = computed(() => {
  if (paid.value || started.value) return null

  return [
    h('a-button', { onClick: handleClose }, '取消'),
    h('a-button', {
      type: 'primary',
      loading: loading.value,
      onClick: startPay
    }, `确认支付 ¥${props.payPrice}`)
  ]
})

/** 关闭弹窗 */
function handleClose() {
  stopPoll()
  emit('update:visible', false)
  emit('close')
}

/** 支付成功 */
function handleSuccess() {
  stopPoll()
  emit('success', { orderNo: props.orderNo })
  handleClose()
}

/** 开始支付 */
async function startPay() {
  errorMsg.value = ''
  loading.value = true

  try {
    const params = {
      orderNo: props.orderNo,
      subject: `订单支付-${props.orderNo}`,
      body: 'WebSoft 产品订单',
      totalAmount: Math.round(Number(props.payPrice) * 100) // 转为分
    }

    let result: PayResult

    switch (payMethod.value) {
      case 'wechat_jsapi':
        result = await createWechatJsapiPay({
          ...params,
          openId: await getWxOpenId()
        })
        await handleWechatJsapiResult(result)
        break

      case 'native':
        started.value = true
        result = await createWechatNativePay(params)
        handleNativeResult(result)
        break

      case 'h5':
        if (selectedMethod.value === 'wechat') {
          result = await createWechatH5Pay({ ...params, returnUrl: window.location.href })
          handleH5Result(result, 'wechat')
        } else {
          result = await createAlipayPay({ ...params, returnUrl: window.location.href })
          handleH5Result(result, 'alipay')
        }
        break

      case 'alipay_wap':
        result = await createAlipayPay({ ...params, returnUrl: window.location.href })
        handleH5Result(result, 'alipay')
        break

      case 'balance':
        await handleBalancePay()
        break

      default:
        throw new Error('不支持的支付方式')
    }
  } catch (err: unknown) {
    const e = err as Error
    errorMsg.value = e.message || '发起支付失败'
    message.error(errorMsg.value)
  } finally {
    loading.value = false
  }
}

/** 处理微信 JSAPI 支付结果 */
async function handleWechatJsapiResult(result: PayResult) {
  // 如果返回的是跳转链接（H5支付链接），直接跳转
  if (result.mwebUrl) {
    window.location.href = result.mwebUrl
    return
  }

  // JSAPI 调起支付
  if (result.prepayId) {
    const appId = result.codeUrl || '' // 实际应该从后端获取
    const timestamp = String(Math.floor(Date.now() / 1000))
    const nonceStr = Math.random().toString(36).slice(2)
    const pkg = `prepay_id=${result.prepayId}`
    const signType = 'MD5'
    const paySign = '' // 后端需要返回签名

    try {
      // 动态加载微信 JSSDK
      await loadWechatJSSDK()

      // @ts-ignore
      window.WeixinJSBridge?.invoke('getBrandWCPayRequest', {
        appId,
        timeStamp: timestamp,
        nonceStr,
        package: pkg,
        signType,
        paySign
      }, (res: { err_msg: string }) => {
        if (res.err_msg === 'get_brand_wcpay_request:ok') {
          paid.value = true
          startPoll()
        } else if (res.err_msg === 'get_brand_wcpay_request:cancel') {
          errorMsg.value = '用户取消支付'
        } else {
          errorMsg.value = res.err_msg
        }
      })
    } catch {
      // 如果 JSSDK 不可用，降级到 H5 支付
      const h5Result = await createWechatH5Pay({
        orderNo: props.orderNo,
        subject: `订单支付-${props.orderNo}`,
        totalAmount: Math.round(Number(props.payPrice) * 100)
      })
      if (h5Result.mwebUrl) {
        window.location.href = h5Result.mwebUrl
      } else {
        throw new Error('JSAPI 支付失败')
      }
    }
  }
}

/** 处理 Native 支付结果 */
function handleNativeResult(result: PayResult) {
  loading.value = false

  if (result.codeUrl) {
    codeUrl.value = result.codeUrl
    // 二维码有效期 2 分钟
    countdown.value = 120
    startCountdown()
    startPoll()
  } else if (result.qrcode) {
    codeUrl.value = result.qrcode
    countdown.value = 120
    startCountdown()
    startPoll()
  } else {
    errorMsg.value = '获取支付二维码失败'
  }
}

/** 处理 H5 支付结果 */
function handleH5Result(result: PayResult, type: 'wechat' | 'alipay') {
  if (type === 'alipay' && (result.paymentUrl || result.payUrl)) {
    const url = result.paymentUrl || result.payUrl
    if (result.paymentUrl?.includes('https://openapi.alipay.com')) {
      // PC 场景：显示二维码
      alipayRedirectVisible.value = true
      alipayUrl.value = url
    } else if (result.paymentUrl?.includes('https://m.alipay.com')) {
      // H5 场景：直接跳转
      window.location.href = url
    } else {
      // 未知格式，直接跳转
      window.location.href = url
    }
    started.value = true
    startPoll()
  } else if (type === 'wechat' && result.mwebUrl) {
    window.location.href = result.mwebUrl
  }
}

/** 余额支付 */
async function handleBalancePay() {
  started.value = true
  loading.value = false

  // 余额支付直接查询状态
  try {
    const status = await queryPayStatus(props.orderNo)
    if (status.paid || status.payStatus === 1) {
      paid.value = true
    } else {
      startPoll()
    }
  } catch {
    // 轮询查询
    startPoll()
  }
}

/** 轮询支付状态 */
async function startPoll() {
  stopPoll()
  pollTimer = setTimeout(async () => {
    try {
      const status = await queryPayStatus(props.orderNo)
      if (status.paid || status.payStatus === 1) {
        paid.value = true
        stopPoll()
        setTimeout(() => handleSuccess(), 1500)
      } else {
        startPoll()
      }
    } catch {
      startPoll()
    }
  }, 2000)
}

/** 停止轮询 */
function stopPoll() {
  if (pollTimer) {
    clearTimeout(pollTimer)
    pollTimer = null
  }
  if (countdownTimer) {
    clearInterval(countdownTimer)
    countdownTimer = null
  }
}

/** 二维码倒计时 */
function startCountdown() {
  countdownTimer = setInterval(() => {
    if (countdown.value > 0) {
      countdown.value--
    } else {
      stopPoll()
    }
  }, 1000)
}

/** 重新获取二维码 */
async function rebuildQrcode() {
  loading.value = true
  errorMsg.value = ''
  codeUrl.value = ''

  try {
    const params = {
      orderNo: props.orderNo,
      subject: `订单支付-${props.orderNo}`,
      totalAmount: Math.round(Number(props.payPrice) * 100)
    }

    const result = await createWechatNativePay(params)
    handleNativeResult(result)
  } catch (err: unknown) {
    const e = err as Error
    errorMsg.value = e.message || '获取二维码失败'
  } finally {
    loading.value = false
  }
}

/** 获取微信 OpenId */
async function getWxOpenId(): Promise<string> {
  // 从 localStorage 或 Vuex 获取已存储的 openId
  const stored = localStorage.getItem('wx_openid')
  if (stored) return stored

  // 如果没有，需要先通过 OAuth 获取
  // 这里可以引导用户授权，或从后端获取
  throw new Error('请先在微信中打开，或联系客服获取支付方式')
}

/** 动态加载微信 JSSDK */
async function loadWechatJSSDK(): Promise<void> {
  return new Promise((resolve, reject) => {
    // 如果已加载
    if (window.WeixinJSBridge || window.jWeixin) {
      resolve()
      return
    }

    // 加载 JSSDK
    const script = document.createElement('script')
    script.src = 'https://res.wx.qq.com/open/js/jweixin-1.6.0.js'
    script.onload = () => resolve()
    script.onerror = () => reject(new Error('微信 JSSDK 加载失败'))
    document.head.appendChild(script)
  })
}

// 监听 visible 变化
watch(() => props.visible, (val) => {
  if (!val) {
    stopPoll()
    started.value = false
    paid.value = false
    errorMsg.value = ''
    codeUrl.value = ''
  }
})
</script>

<style scoped>
.pay-method-item {
  display: flex;
  align-items: center;
  padding: 12px 16px;
  border: 2px solid #e5e7eb;
  border-radius: 8px;
  cursor: pointer;
  transition: all 0.2s;
}

.pay-method-item:hover {
  border-color: #d1d5db;
}

.pay-method-item.active {
  border-color: #1890ff;
  background: #f0f9ff;
}
</style>
