<script setup lang="ts">
import { ref, computed, nextTick } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { storeToRefs } from 'pinia'
import { useAuthStore } from '@/stores/auth'
import { useToast } from '@/composables/useToast'
import { useIntervalFn } from '@vueuse/core'
import { useI18n } from 'vue-i18n'
import AuthLayout from '@/components/auth/AuthLayout.vue'
import AppInput from '@/components/common/AppInput.vue'
import AppButton from '@/components/common/AppButton.vue'

const { t } = useI18n()
const router = useRouter()
const route = useRoute()
const authStore = useAuthStore()
const toast = useToast()
const { loading } = storeToRefs(authStore)

const email = ref('')
const password = ref('')
const digits = ref<string[]>(Array(6).fill(''))
const inputRefs = ref<HTMLInputElement[]>([])
const emailError = ref('')
const passwordError = ref('')
const codeError = ref('')

const code = computed(() => digits.value.join(''))
const canConfirm = computed(() => code.value.length === 6)

function setRef(el: unknown, i: number) {
  if (el) inputRefs.value[i] = el as HTMLInputElement
}

function onDigitInput(i: number, e: Event) {
  const raw = (e.target as HTMLInputElement).value.replace(/\D/g, '')
  digits.value[i] = raw.slice(-1)
  ;(e.target as HTMLInputElement).value = digits.value[i]
  if (digits.value[i] && i < 5) nextTick(() => inputRefs.value[i + 1]?.focus())
}

// beforeinput handles iOS soft keyboard where keydown Backspace may not fire
function onDigitBeforeInput(i: number, e: InputEvent) {
  if (e.inputType === 'deleteContentBackward') {
    e.preventDefault()
    if (digits.value[i]) {
      digits.value[i] = '';
      (e.target as HTMLInputElement).value = ''
    } else if (i > 0) {
      nextTick(() => inputRefs.value[i - 1]?.focus())
    }
  }
}

function onDigitKeydown(i: number, e: KeyboardEvent) {
  // Fallback for environments where beforeinput is not supported
  if (e.key === 'Backspace') {
    if (digits.value[i]) { digits.value[i] = '' }
    else if (i > 0) inputRefs.value[i - 1]?.focus()
  }
}

function onDigitPaste(e: ClipboardEvent) {
  e.preventDefault()
  const text = e.clipboardData?.getData('text').replace(/\D/g, '') ?? ''
  if (!text) return
  text.slice(0, 6).split('').forEach((c, i) => { digits.value[i] = c })
  nextTick(() => inputRefs.value[Math.min(text.length, 5)]?.focus())
}

const showModal = ref(false)
const codeSent = ref(false)
const countdown = ref(0)

const { pause, resume } = useIntervalFn(() => {
  if (countdown.value > 0) countdown.value--
  else pause()
}, 1000, { immediate: false })

const maskedEmail = computed(() => {
  if (!email.value) return ''
  const [local, domain] = email.value.split('@')
  if (!domain) return email.value
  return `${local.slice(0, 2)}****@${domain}`
})

function validateForm() {
  emailError.value = ''
  passwordError.value = ''
  let ok = true
  if (!email.value) { emailError.value = t('error.emailRequired'); ok = false }
  else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email.value)) { emailError.value = t('error.emailInvalid'); ok = false }
  if (!password.value) { passwordError.value = t('error.passwordRequired'); ok = false }
  return ok
}

async function handleContinue() {
  if (!validateForm()) {
    return
  }
  authStore.clearError()
  passwordError.value = ''
  const ok = await authStore.checkLoginPassword(email.value, password.value)
  if (!ok) {
    passwordError.value = authStore.error || t('error.loginFailed')
    return
  }
  digits.value = Array(6).fill('')
  codeError.value = ''
  codeSent.value = false
  showModal.value = true
  nextTick(() => inputRefs.value[0]?.focus())
}

async function sendCode() {
  authStore.clearError()
  await authStore.sendLoginCode(email.value)
  if (!authStore.error) {
    codeSent.value = true
    countdown.value = 60
    resume()
    nextTick(() => inputRefs.value[0]?.focus())
  } else {
    toast.error(authStore.error)
  }
}

async function resendCode() {
  authStore.clearError()
  await authStore.sendLoginCode(email.value)
  if (!authStore.error) {
    countdown.value = 60
    resume()
    toast.info(t('auth.codeSentAgain'))
  } else {
    toast.error(authStore.error)
  }
}

async function handleConfirm() {
  codeError.value = ''
  if (code.value.length !== 6) { codeError.value = t('error.code6Required'); return }
  authStore.clearError()
  await authStore.login(email.value, password.value, code.value)
  if (!authStore.error) {
    closeModal()
    const redirect = route.query.redirect as string | undefined
    router.replace(redirect || '/')
    toast.success(t('auth.loginSuccess'))
  } else {
    codeError.value = authStore.error
  }
}

function closeModal() {
  showModal.value = false
  codeSent.value = false
  countdown.value = 0
  pause()
  digits.value = Array(6).fill('')
  codeError.value = ''
}
</script>

<template>
  <AuthLayout>
    <h1 class="auth-title">{{ t('auth.loginTitle') }}</h1>

    <div class="form">
      <AppInput v-model="email" :label="t('auth.emailLogin')" :placeholder="t('auth.emailPlaceholder')" :error="emailError" @keyup.enter="handleContinue" />

      <div class="pwd-field">
        <div class="label-row">
          <span class="field-label">{{ t('auth.password') }}</span>
          <RouterLink to="/forgot-password" class="forgot-link">{{ t('auth.forgotPassword') }}</RouterLink>
        </div>
        <AppInput v-model="password" type="password" :placeholder="t('auth.passwordPlaceholder')" :error="passwordError" @keyup.enter="handleContinue" />
      </div>
    </div>

    <AppButton pill block size="lg" :loading="loading" class="submit-btn" @click="handleContinue">{{ t('auth.loginBtn') }}</AppButton>
    <RouterLink to="/download" class="download-btn">{{ t('home.downloadApp') }}</RouterLink>
    <p class="foot-tip">{{ t('auth.noAccount') }}<RouterLink to="/register" class="link">{{ t('auth.registerNow') }}</RouterLink></p>
  </AuthLayout>

  <!-- 验证码弹窗 -->
  <Teleport to="body">
    <Transition name="modal">
      <div v-if="showModal" class="modal-overlay" @click.self="closeModal">
        <div class="modal">
          <button class="modal-close" @click="closeModal">
            <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
              <line x1="18" y1="6" x2="6" y2="18" /><line x1="6" y1="6" x2="18" y2="18" />
            </svg>
          </button>

          <h2 class="modal-title">{{ t('auth.verifyTitle') }}</h2>

          <template v-if="codeSent">
            <p class="modal-desc">{{ t('auth.codeSentDesc', { email: maskedEmail }) }}</p>

            <div class="digit-row">
              <input
                v-for="(_, i) in 6"
                :key="i"
                :ref="el => setRef(el, i)"
                class="digit-box"
                type="text"
                inputmode="numeric"
                maxlength="1"
                :value="digits[i]"
                @beforeinput="onDigitBeforeInput(i, $event as InputEvent)"
                @input="onDigitInput(i, $event)"
                @keydown="onDigitKeydown(i, $event)"
                @paste="onDigitPaste($event)"
              />
            </div>

            <div class="resend-row">
              <span v-if="countdown > 0" class="countdown">{{ t('auth.countdownResend', { n: countdown }) }}</span>
              <button v-else class="resend-btn" :disabled="loading" @click="resendCode">{{ t('auth.resendCode') }}</button>
            </div>
            <p v-if="codeError" class="code-error">{{ codeError }}</p>

            <AppButton pill block size="lg" :loading="loading" :disabled="!canConfirm" class="confirm-btn" @click="handleConfirm">{{ t('auth.confirmBtn') }}</AppButton>
          </template>

          <template v-else>
            <p class="modal-desc">{{ t('auth.codeSendDesc', { email: maskedEmail }) }}</p>
            <AppButton pill block size="lg" :loading="loading" class="confirm-btn" @click="sendCode">{{ t('auth.sendCode') }}</AppButton>
          </template>
          <p class="forgot-tip"><RouterLink to="/forgot-password" @click="closeModal">{{ t('auth.forgotVerify') }}</RouterLink></p>
        </div>
      </div>
    </Transition>
  </Teleport>
</template>

<style scoped>
.auth-title { font-size: 30px; font-weight: 700; color: #fff; margin-bottom: 32px; }
.form { display: flex; flex-direction: column; gap: 20px; }
.pwd-field { display: flex; flex-direction: column; gap: 8px; }
.label-row { display: flex; justify-content: space-between; align-items: center; }
.field-label { font-size: 13px; color: #888; }
.forgot-link { font-size: 13px; color: var(--color-primary); }
.forgot-link:hover { opacity: 0.8; }
.submit-btn { margin-top: 32px; }
.download-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 52px;
  margin-top: 12px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.14);
  color: #fff;
  font-size: 15px;
  font-weight: 600;
  text-decoration: none;
  transition: background 0.2s, border-color 0.2s;
}
.download-btn:hover {
  background: rgba(255, 255, 255, 0.1);
  border-color: rgba(255, 255, 255, 0.22);
}
.foot-tip { margin-top: 20px; text-align: center; font-size: 13px; color: #666; }
.link { color: var(--color-primary); }
.link:hover { opacity: 0.8; }

/* Modal */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.75);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 200;
  backdrop-filter: blur(4px);
  padding: 16px;
}
.modal {
  position: relative;
  width: 100%;
  max-width: 440px;
  background: #1a1d24;
  border: 1px solid rgba(255,255,255,0.1);
  border-radius: 20px;
  padding: 36px 32px 32px;
}
.modal-close {
  position: absolute;
  top: 16px; right: 16px;
  width: 32px; height: 32px;
  display: flex; align-items: center; justify-content: center;
  color: #666; border-radius: 8px;
  transition: color 0.2s, background 0.2s;
}
.modal-close:hover { color: #fff; background: rgba(255,255,255,0.06); }
.modal-title { font-size: 22px; font-weight: 700; color: #fff; margin-bottom: 8px; }
.modal-desc { font-size: 13px; color: #888; line-height: 1.6; margin-bottom: 24px; }

.digit-row {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 8px;
  margin-bottom: 16px;
}
.digit-box {
  width: 100%; aspect-ratio: 1;
  text-align: center; font-size: 20px; font-weight: 700;
  background: rgba(255,255,255,0.05);
  border: 1.5px solid rgba(255,255,255,0.12);
  border-radius: 10px;
  color: #fff; outline: none; padding: 0;
  caret-color: transparent;
  transition: border-color 0.15s, background 0.15s, box-shadow 0.15s;
}
.digit-box:focus {
  border-color: var(--color-primary);
  background: rgba(240,185,11,0.06);
  box-shadow: 0 0 0 3px rgba(240,185,11,0.12);
}

.resend-row { min-height: 22px; margin-bottom: 4px; }
.countdown { font-size: 13px; color: #555; }
.resend-btn {
  font-size: 13px; font-weight: 600;
  color: var(--color-primary); background: none;
  transition: opacity 0.2s;
}
.resend-btn:hover:not(:disabled) { opacity: 0.8; }
.resend-btn:disabled { opacity: 0.4; cursor: not-allowed; }
.code-error { font-size: 12px; color: var(--color-down); margin-bottom: 4px; }
.confirm-btn { margin-top: 16px; }
.forgot-tip { margin-top: 14px; text-align: center; font-size: 13px; color: var(--color-primary); }
.forgot-tip a { color: inherit; }

/* Transition */
.modal-enter-active { transition: opacity 0.2s ease; }
.modal-leave-active { transition: opacity 0.15s ease; }
.modal-enter-active .modal { transition: transform 0.2s ease, opacity 0.2s ease; }
.modal-leave-active .modal { transition: transform 0.15s ease, opacity 0.15s ease; }
.modal-enter-from, .modal-leave-to { opacity: 0; }
.modal-enter-from .modal, .modal-leave-to .modal { transform: translateY(16px) scale(0.97); opacity: 0; }
</style>
