import { computed, onBeforeUnmount, ref, watch } from 'vue'
import QRCode from 'qrcode'

import { queryOrderPayment, type PaymentOrder } from '@/features/orders/api/orders'

type PaidHandler = () => Promise<void> | void

/**
 * 从支付单提取实际支付 URL。顺序与现网 PC/Mobile 一致：jspay_url → td_code → jspay_info。
 */
export function paymentPayURL(payment?: PaymentOrder | null): string {
  return payment?.jspay_url || payment?.td_code || payment?.jspay_info || ''
}

function isHTTPURL(value: string): boolean {
  return /^https?:\/\//i.test(value)
}

export interface UseOrderPaymentCashierOptions {
  /** 成功提示。 */
  notifySuccess: (message: string) => void
  /** 错误提示（如二维码生成失败、查询支付状态失败）。 */
  notifyError: (message: string) => void
  /** 非静默查询未完成时的轻量提示（"支付暂未完成"）。 */
  notifyInfo: (message: string) => void
  /**
   * 兜底提示：支付 URL 非 HTTP 或为空、无法渲染二维码时展示。
   * Mobile 用 vant dialog（带"知道了"按钮）做强提示，PC 用普通提示即可。
   */
  notifyFallback: (message: string) => void
  /** 支付完成的提示文案，默认 "支付成功，正在进入群消息"。 */
  paidMessage?: string
  /** 轮询间隔，PC 3000 / Mobile 2500。 */
  pollIntervalMs?: number
  /** 二维码宽度，PC 240 / Mobile 220。 */
  qrWidth?: number
  /**
   * 拦截 HTTP 支付 URL 的外部打开方式。
   * Mobile（微信/支付宝内嵌浏览器）注入 `window.location.href = url` 直接拉起支付；
   * PC 不注入（直接渲染二维码弹窗）。返回 true 表示已处理（不再走弹窗），false 走默认弹窗流程。
   */
  openExternalURL?: (url: string) => boolean
  /** 弹窗显隐控制方式。PC 用 el-dialog（v-model 一个 ref），Mobile 用 van-popup。返回 true 表示用 ref，false 表示 composable 内部 ref。 */
}

/**
 * 支付收银台 Composable（PC / Mobile 共用）。
 *
 * 封装支付单创建后的 UI 流程：HTTP URL 直接跳转 / 二维码渲染 + 轮询查询 / 兜底提示。
 * UI 反馈通过 options 注入；轮询间隔、二维码宽度、外部跳转等差异通过参数控制。
 */
export function useOrderPaymentCashier(options: UseOrderPaymentCashierOptions) {
  const paymentPopupVisible = ref(false)
  const activePayment = ref<PaymentOrder | null>(null)
  const paymentQRCodeURL = ref('')
  const qrGenerating = ref(false)
  const checkingPayment = ref(false)
  let paymentPollingTimer: number | undefined
  let paidHandler: PaidHandler | undefined

  const pollIntervalMs = options.pollIntervalMs ?? 2500
  const qrWidth = options.qrWidth ?? 220
  const paidMessage = options.paidMessage ?? '支付成功，正在进入群消息'

  const payURL = computed(() => paymentPayURL(activePayment.value))

  async function openPaymentCashier(payment: PaymentOrder, onPaid?: PaidHandler) {
    activePayment.value = payment
    paidHandler = onPaid

    if (payment.paid) {
      await handlePaid()
      return
    }

    const currentPayURL = paymentPayURL(payment)
    if (currentPayURL && options.openExternalURL?.(currentPayURL)) {
      return
    }

    if (currentPayURL && isHTTPURL(currentPayURL)) {
      paymentPopupVisible.value = true
      await renderPaymentQRCode(payment)
      startPaymentPolling()
      return
    }

    // 非 HTTP URL（或空）：无法渲染二维码，仅展示兜底提示。
    options.notifyFallback(currentPayURL || '支付单已创建，请稍后刷新订单状态。')
  }

  async function renderPaymentQRCode(payment = activePayment.value) {
    const currentPayURL = paymentPayURL(payment)
    paymentQRCodeURL.value = ''
    if (!currentPayURL || !isHTTPURL(currentPayURL)) return

    qrGenerating.value = true
    try {
      paymentQRCodeURL.value = await QRCode.toDataURL(currentPayURL, {
        width: qrWidth,
        margin: 1,
        errorCorrectionLevel: 'M',
        color: {
          dark: '#111827',
          light: '#ffffff',
        },
      })
    } catch {
      options.notifyError('二维码生成失败')
    } finally {
      qrGenerating.value = false
    }
  }

  function startPaymentPolling() {
    stopPaymentPolling()
    paymentPollingTimer = window.setInterval(() => {
      void refreshPaymentStatus(true)
    }, pollIntervalMs)
  }

  function stopPaymentPolling() {
    if (paymentPollingTimer === undefined) return
    window.clearInterval(paymentPollingTimer)
    paymentPollingTimer = undefined
  }

  async function refreshPaymentStatus(silent = false) {
    if (!activePayment.value || checkingPayment.value) return

    checkingPayment.value = true
    const previousPayURL = payURL.value
    try {
      const payment = await queryOrderPayment(activePayment.value.order_id)
      activePayment.value = payment
      if (payment.paid) {
        await handlePaid()
        return
      }
      if (paymentPayURL(payment) !== previousPayURL) {
        await renderPaymentQRCode(payment)
      }
      if (!silent) {
        options.notifyInfo('支付暂未完成')
      }
    } catch {
      if (!silent) {
        options.notifyError('查询支付状态失败')
      }
    } finally {
      checkingPayment.value = false
    }
  }

  async function handlePaid() {
    stopPaymentPolling()
    paymentPopupVisible.value = false
    options.notifySuccess(paidMessage)
    await paidHandler?.()
  }

  watch(paymentPopupVisible, visible => {
    if (!visible) stopPaymentPolling()
  })

  onBeforeUnmount(stopPaymentPolling)

  return {
    paymentPopupVisible,
    activePayment,
    payURL,
    paymentQRCodeURL,
    qrGenerating,
    checkingPayment,
    openPaymentCashier,
    refreshPaymentStatus,
    stopPaymentPolling,
  }
}
