<script setup lang="ts">
import { ref, computed, onMounted, onUnmounted, watch } from 'vue';
import QRCode from 'qrcode';
import { io, type Socket } from 'socket.io-client';
import { SOCKET_EVENTS } from '@gala/shared/constants';
import type { ScanStatusUpdatePayload, ScanLoginStatus } from '@gala/shared/types';

const emit = defineEmits<{
  (e: 'login-success', data: { userId: string; userName: string; department: string; sessionToken: string }): void;
  (e: 'login-cancel'): void;
}>();

const props = defineProps<{
  serverUrl?: string;
}>();

// State
const socket = ref<Socket | null>(null);
const scanToken = ref<string>('');
const qrCodeDataUrl = ref<string>('');
const status = ref<ScanLoginStatus>('pending');
const expiresAt = ref<number>(0);
const countdown = ref<number>(0);
const isLoading = ref<boolean>(true);
const error = ref<string>('');

// Computed
const statusText = computed(() => {
  switch (status.value) {
    case 'pending':
      return '请使用微信扫描二维码';
    case 'scanned':
      return '已扫描，请在手机上完成登录';
    case 'confirmed':
      return '登录成功！';
    case 'expired':
      return '二维码已过期，请刷新';
    default:
      return '';
  }
});

const isExpired = computed(() => status.value === 'expired' || countdown.value <= 0);

// Timer
let countdownTimer: ReturnType<typeof setInterval> | null = null;

// Initialize socket and generate QR code
async function initialize() {
  isLoading.value = true;
  error.value = '';

  try {
    // Connect socket
    const serverUrl = props.serverUrl || import.meta.env.VITE_SOCKET_URL || 'http://localhost:3000';
    socket.value = io(serverUrl, {
      transports: ['websocket', 'polling'],
    });

    await new Promise<void>((resolve, reject) => {
      socket.value!.on('connect', () => resolve());
      socket.value!.on('connect_error', (err) => reject(err));
      setTimeout(() => reject(new Error('Connection timeout')), 10000);
    });

    // Generate QR code
    await generateQRCode();

    // Listen for status updates
    socket.value.on(SOCKET_EVENTS.SCAN_STATUS_UPDATE as any, handleStatusUpdate);

    // Start countdown
    startCountdown();
  } catch (err) {
    error.value = '连接服务器失败，请刷新重试';
    console.error('QR Login init error:', err);
  } finally {
    isLoading.value = false;
  }
}

async function generateQRCode() {
  if (!socket.value?.id) {
    throw new Error('Socket not connected');
  }

  const serverUrl = props.serverUrl || import.meta.env.VITE_API_URL || 'http://localhost:3000';
  const response = await fetch(`${serverUrl}/api/scan/generate`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ pcSocketId: socket.value.id }),
  });

  const result = await response.json();

  if (!result.success) {
    throw new Error(result.error || 'Failed to generate QR code');
  }

  scanToken.value = result.data.scanToken;
  expiresAt.value = result.data.expiresAt;

  // Generate QR code image
  qrCodeDataUrl.value = await QRCode.toDataURL(result.data.qrCodeUrl, {
    width: 256,
    margin: 2,
    color: {
      dark: '#000000',
      light: '#ffffff',
    },
  });

  // Subscribe to scan updates
  socket.value.emit(SOCKET_EVENTS.SCAN_SUBSCRIBE as any, { scanToken: scanToken.value });
}

function handleStatusUpdate(data: ScanStatusUpdatePayload) {
  if (data.scanToken !== scanToken.value) return;

  status.value = data.status;

  if (data.status === 'confirmed' && data.userInfo) {
    // Login successful
    stopCountdown();
    emit('login-success', {
      userId: data.userInfo.userId,
      userName: data.userInfo.userName,
      department: data.userInfo.department,
      sessionToken: data.userInfo.sessionToken,
    });
  }
}

function startCountdown() {
  stopCountdown();
  updateCountdown();
  countdownTimer = setInterval(updateCountdown, 1000);
}

function stopCountdown() {
  if (countdownTimer) {
    clearInterval(countdownTimer);
    countdownTimer = null;
  }
}

function updateCountdown() {
  const remaining = Math.max(0, Math.floor((expiresAt.value - Date.now()) / 1000));
  countdown.value = remaining;

  if (remaining <= 0) {
    status.value = 'expired';
    stopCountdown();
  }
}

async function refresh() {
  status.value = 'pending';
  await initialize();
}

function cancel() {
  emit('login-cancel');
}

// Lifecycle
onMounted(() => {
  initialize();
});

onUnmounted(() => {
  stopCountdown();
  if (socket.value) {
    if (scanToken.value) {
      socket.value.emit(SOCKET_EVENTS.SCAN_UNSUBSCRIBE as any, { scanToken: scanToken.value });
    }
    socket.value.disconnect();
  }
});
</script>

<template>
  <div class="qr-login-container">
    <div class="qr-login-card">
      <h2 class="title">扫码登录</h2>

      <div class="qr-wrapper">
        <!-- Loading state -->
        <div v-if="isLoading" class="loading-state">
          <div class="spinner"></div>
          <p>正在加载...</p>
        </div>

        <!-- Error state -->
        <div v-else-if="error" class="error-state">
          <p class="error-text">{{ error }}</p>
          <button class="refresh-btn" @click="refresh">重新加载</button>
        </div>

        <!-- QR Code -->
        <div v-else class="qr-content">
          <div class="qr-image-wrapper" :class="{ expired: isExpired, scanned: status === 'scanned' }">
            <img v-if="qrCodeDataUrl" :src="qrCodeDataUrl" alt="QR Code" class="qr-image" />

            <!-- Overlay for expired/scanned states -->
            <div v-if="isExpired" class="overlay expired-overlay">
              <span class="overlay-icon">⏰</span>
              <span>已过期</span>
            </div>
            <div v-else-if="status === 'scanned'" class="overlay scanned-overlay">
              <span class="overlay-icon">✓</span>
              <span>已扫描</span>
            </div>
          </div>

          <!-- Status text -->
          <p class="status-text" :class="status">{{ statusText }}</p>

          <!-- Countdown -->
          <p v-if="!isExpired && status === 'pending'" class="countdown">
            {{ Math.floor(countdown / 60) }}:{{ String(countdown % 60).padStart(2, '0') }} 后过期
          </p>

          <!-- Refresh button -->
          <button v-if="isExpired" class="refresh-btn" @click="refresh">刷新二维码</button>
        </div>
      </div>

      <!-- Cancel button -->
      <button class="cancel-btn" @click="cancel">取消</button>
    </div>
  </div>
</template>

<style scoped>
.qr-login-container {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.6);
  z-index: 1000;
}

.qr-login-card {
  background: linear-gradient(135deg, #fff5f5 0%, #fef8f0 100%);
  border-radius: 16px;
  padding: 32px;
  min-width: 360px;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
  text-align: center;
}

.title {
  font-size: 24px;
  color: #c41230;
  margin-bottom: 24px;
  font-weight: bold;
}

.qr-wrapper {
  min-height: 320px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.loading-state,
.error-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
}

.spinner {
  width: 48px;
  height: 48px;
  border: 4px solid #f3f3f3;
  border-top: 4px solid #c41230;
  border-radius: 50%;
  animation: spin 1s linear infinite;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

.error-text {
  color: #c41230;
  font-size: 14px;
}

.qr-content {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
}

.qr-image-wrapper {
  position: relative;
  padding: 16px;
  background: white;
  border-radius: 12px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  transition: all 0.3s ease;
}

.qr-image-wrapper.expired .qr-image,
.qr-image-wrapper.scanned .qr-image {
  filter: blur(4px);
  opacity: 0.5;
}

.qr-image {
  display: block;
  width: 256px;
  height: 256px;
}

.overlay {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 16px 24px;
  border-radius: 8px;
  font-weight: bold;
}

.expired-overlay {
  background: rgba(196, 18, 48, 0.9);
  color: white;
}

.scanned-overlay {
  background: rgba(76, 175, 80, 0.9);
  color: white;
}

.overlay-icon {
  font-size: 32px;
}

.status-text {
  font-size: 16px;
  color: #333;
}

.status-text.scanned {
  color: #4caf50;
}

.status-text.confirmed {
  color: #4caf50;
  font-weight: bold;
}

.status-text.expired {
  color: #c41230;
}

.countdown {
  font-size: 14px;
  color: #666;
}

.refresh-btn {
  padding: 12px 32px;
  background: linear-gradient(135deg, #c41230 0%, #a00f28 100%);
  color: white;
  border: none;
  border-radius: 24px;
  font-size: 16px;
  cursor: pointer;
  transition: transform 0.2s, box-shadow 0.2s;
}

.refresh-btn:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(196, 18, 48, 0.3);
}

.cancel-btn {
  margin-top: 24px;
  padding: 8px 24px;
  background: transparent;
  color: #666;
  border: 1px solid #ddd;
  border-radius: 20px;
  font-size: 14px;
  cursor: pointer;
  transition: all 0.2s;
}

.cancel-btn:hover {
  background: #f5f5f5;
  border-color: #ccc;
}
</style>
