<template>
  <div class="qr-login">
    <div class="qr-box">
      <div v-if="status === 'loading'" class="qr-state">
        <a-spin size="large" />
        <p class="muted">正在生成二维码…</p>
      </div>

      <!-- 微信扫码登录 -->
      <div v-else-if="status === 'active'" class="qr-state">
        <!-- 小程序码（优先展示，Base64格式） -->
        <img
          v-if="miniprogramQrCode"
          :src="miniprogramQrCode"
          class="qrcode-img"
          alt="小程序码登录"
          @click="refresh"
        />
        <!-- 普通二维码（降级方案） -->
        <img
          v-else-if="qrCodeDataUrl"
          :src="qrCodeDataUrl"
          class="qrcode-img"
          alt="扫码登录"
          @click="refresh"
        />
        <div v-else class="qrcode-placeholder">
          <a-spin size="large" />
        </div>
        <p class="tip">请使用微信扫一扫，扫码后自动登录</p>
        <p class="muted">有效期：{{ formatCountdown(expireSeconds) }}</p>
      </div>

      <div v-else-if="status === 'scanned'" class="qr-state">
        <CheckCircleOutlined class="icon ok" />
        <p class="ok-text">已识别扫码，请在手机上确认登录</p>
      </div>

      <div v-else-if="status === 'expired'" class="qr-state">
        <ClockCircleOutlined class="icon bad" />
        <p class="bad-text">二维码已过期</p>
        <a-button type="primary" @click="refresh">刷新二维码</a-button>
      </div>

      <div v-else-if="status === 'error'" class="qr-state">
        <ExclamationCircleOutlined class="icon bad" />
        <p class="bad-text">{{ errorMessage || '生成二维码失败' }}</p>
        <a-button type="primary" @click="refresh">重新生成</a-button>
      </div>
    </div>

    <div v-if="status === 'active'" class="actions">
      <a-button type="link" :loading="refreshing" @click="refresh">
        <ReloadOutlined />
        刷新二维码
      </a-button>
    </div>
  </div>
</template>

<script setup lang="ts">
import { onMounted, onUnmounted, ref } from 'vue'
import { message } from 'ant-design-vue'
import {
  CheckCircleOutlined,
  ClockCircleOutlined,
  ExclamationCircleOutlined,
  ReloadOutlined
} from '@ant-design/icons-vue'
import {
  checkQrCodeStatus,
  generateQrCode,
  type QrCodeResponse,
  type QrCodeStatusResponse
} from '@/api/passport/qrLogin'
import { generateQrCodeDataUrl } from '@/composables/useQRCode'

const emit = defineEmits<{
  (e: 'loginSuccess', data: QrCodeStatusResponse): void
  (e: 'loginError', error: string): void
}>()

const router = useRouter()

const qrCodeDataUrl = ref('')  // 前端生成的base64二维码图片
const miniprogramQrCode = ref('')  // 后端返回的小程序码Base64图片（优先使用）
const token = ref('')
const status = ref<'loading' | 'active' | 'scanned' | 'expired' | 'error'>('loading')
const expireSeconds = ref(0)
const errorMessage = ref('')
const refreshing = ref(false)

let statusTimer: ReturnType<typeof setInterval> | null = null
let countdownTimer: ReturnType<typeof setInterval> | null = null

function stopTimers() {
  if (statusTimer) clearInterval(statusTimer)
  if (countdownTimer) clearInterval(countdownTimer)
  statusTimer = null
  countdownTimer = null
}

// 启动轮询（小程序码和普通二维码共用）
function startStatusPolling() {
  // 状态轮询
  statusTimer = setInterval(async () => {
    try {
      const current = await checkQrCodeStatus(token.value)
      if (current.expiresIn !== undefined) expireSeconds.value = current.expiresIn
      if (current.status === 'scanned') {
        status.value = 'scanned'
        return
      }
      if (current.status === 'bind_phone') {
        stopTimers()
        message.info(current.message || '检测到新用户，请先绑定手机号')
        await router.replace(`/bind-phone?token=${token.value}`)
        return
      }
      if (current.status === 'expired') {
        status.value = 'expired'
        stopTimers()
        return
      }
      if (current.status === 'confirmed') {
        stopTimers()
        emit('loginSuccess', current)
      }
    } catch {
      // ignore polling errors, keep polling
    }
  }, 2000)

  // 倒计时
  countdownTimer = setInterval(() => {
    expireSeconds.value = Math.max(0, expireSeconds.value - 1)
    if (expireSeconds.value <= 0) {
      status.value = 'expired'
      stopTimers()
    }
  }, 1000)
}

function formatCountdown(seconds: number) {
  const m = Math.floor(seconds / 60)
  const s = Math.max(0, seconds % 60)
  return `${m}:${String(s).padStart(2, '0')}`
}

function getErrorMessage(error: unknown) {
  if (error instanceof Error) return error.message
  if (typeof error === 'string') return error
  if (typeof error === 'object' && error && 'message' in error) {
    const msg = (error as { message?: unknown }).message
    if (typeof msg === 'string') return msg
  }
  try {
    return String(error)
  } catch {
    return ''
  }
}

async function init() {
  if (!import.meta.client) return
  stopTimers()
  status.value = 'loading'
  errorMessage.value = ''
  qrCodeDataUrl.value = ''
  try {
    const response: QrCodeResponse = await generateQrCode()
    token.value = response.token
    expireSeconds.value = response.expiresIn || 300

    // 优先使用后端返回的小程序码Base64图片（扫码后直接打开小程序）
    if (response.miniprogramQrCode) {
      miniprogramQrCode.value = response.miniprogramQrCode
      console.info('使用小程序码（Base64，长度: {}）', miniprogramQrCode.value.length)
      status.value = 'active'
      // 小程序码模式下不需要前端生成二维码，启动轮询即可
      startStatusPolling()
      return
    }

    // 小程序码不存在，降级到普通二维码
    miniprogramQrCode.value = ''
    console.warn('后端未返回小程序码，降级到普通二维码')

    // 获取二维码内容
    // 优先级：wechatScanUrl（H5页面，微信能识别）> qrCodeContent（如果是http开头）> 降级URL
    // 不使用 qrCodeContent，因为它是 websopy:// 自定义协议，微信无法识别
    let qrContent = '';
    if (response.wechatScanUrl) {
      // 优先使用 wechatScanUrl（H5 扫码页面，微信能打开）
      qrContent = response.wechatScanUrl
      console.info('使用微信扫码URL:', qrContent)
    } else if (response.qrCodeContent && response.qrCodeContent.startsWith('http')) {
      // 如果 qrCodeContent 是 http 开头，也可以使用
      qrContent = response.qrCodeContent
      console.info('使用 qrCodeContent:', qrContent)
    } else {
      // 降级：使用当前域名构建扫码URL
      const currentOrigin = window.location.origin
      qrContent = `${currentOrigin}/wx-scan?token=${response.token}`
      console.info('使用降级扫码URL:', qrContent)
    }

    // 前端直接生成base64二维码，不再依赖后端返回的图片URL
    try {
      qrCodeDataUrl.value = await generateQrCodeDataUrl(qrContent, {
        width: 280,
        margin: 2,
        color: {
          dark: '#000000',
          light: '#ffffff'
        }
      })
    } catch (e) {
      console.error('生成二维码失败:', e)
      throw new Error('生成二维码失败，请刷新重试')
    }

    status.value = 'active'

    // 启动轮询
    startStatusPolling()
  } catch (error: unknown) {
    status.value = 'error'
    errorMessage.value = getErrorMessage(error) || '生成二维码失败'
    message.error(errorMessage.value)
    emit('loginError', errorMessage.value)
  }
}

async function refresh() {
  refreshing.value = true
  try {
    await init()
  } finally {
    refreshing.value = false
  }
}

onMounted(() => {
  init()
})

onUnmounted(() => {
  stopTimers()
})
</script>

<style scoped>
.qr-login {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 20px 0 12px;
}

.qr-box {
  width: 100%;
  min-height: 260px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.qr-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  text-align: center;
}

/* 二维码样式 */
.qrcode-img {
  width: 200px;
  height: 200px;
  border-radius: 8px;
  cursor: pointer;
  transition: transform 0.2s;
}
.qrcode-img:hover {
  transform: scale(1.02);
}
.qrcode-placeholder {
  width: 200px;
  height: 200px;
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #f5f5f5;
}

.tip {
  color: #111827;
  margin: 0;
  font-size: 14px;
}
.muted {
  color: #6b7280;
  margin: 0;
  font-size: 12px;
}
.actions {
  margin-top: 10px;
}
.icon {
  font-size: 48px;
}
.ok {
  color: #16a34a;
}
.bad {
  color: #ef4444;
}
.ok-text {
  margin: 0;
  color: #16a34a;
}
.bad-text {
  margin: 0;
  color: #ef4444;
}
</style>
