<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">
        <a-qrcode :value="qrCodeUrl" :size="200" @click="refresh" />
        <p class="tip">请使用手机 APP 或小程序扫码登录</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'

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

const qrCodeUrl = ref('')
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 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 = ''
  try {
    const response: QrCodeResponse = await generateQrCode()
    token.value = response.token
    expireSeconds.value = response.expiresIn || 300
    qrCodeUrl.value = `${window.location.origin}/qr-confirm?qrCodeKey=${encodeURIComponent(
      response.token
    )}`
    status.value = 'active'

    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 === '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)
  } 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;
}
.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>
