<template>
  <view class="login-page">
    <view class="header-hero" :style="{ paddingTop: (statusBarHeight + 16) + 'px' }">
      <view class="logo-section">
        <image class="login-logo" src="/static/logo_us.png" mode="aspectFit" />
        <text class="hero-sub">{{ t('login.employeePortal') }}</text>
      </view>
    </view>

    <view class="form-wrap">
      <view class="form-card">
        <template v-if="mode === 'signin'">
          <view class="form-group">
            <text class="label">{{ t('login.email') }}</text>
            <input
              v-model="email"
              type="text"
              inputmode="email"
              class="input"
              :placeholder="t('login.emailPlaceholder')"
              placeholder-class="placeholder"
            />
          </view>
          <view class="form-group">
            <text class="label">{{ t('login.password') }}</text>
            <view class="input-wrap">
              <input
                v-model="password"
                :type="showSignInPassword ? 'text' : 'password'"
                class="input input-in-wrap"
                :placeholder="t('login.passwordPlaceholder')"
                placeholder-class="placeholder"
              />
              <view class="eye-btn" @tap="showSignInPassword = !showSignInPassword">
                <AppIcon name="eye" size="sm" :color="showSignInPassword ? 'primary' : 'gray'" />
              </view>
            </view>
          </view>
          <view class="form-row">
            <view class="remember-row">
              <switch :checked="rememberMe" color="#1F3A8A" @change="onRememberChange" />
              <text class="remember-text">{{ t('login.rememberMe') }}</text>
            </view>
            <text class="forgot-link" @tap="goForgot">{{ t('login.forgotPassword') }}</text>
          </view>
          <view
            class="submit-btn"
            :class="{ disabled: isLoading }"
            @tap="handleLogin"
          >
            <text class="submit-btn-text">{{ isLoading ? t('login.signingIn') : t('login.signIn') }}</text>
          </view>
        </template>

        <template v-else>
          <text class="reset-heading">{{ t('login.resetTitle') }}</text>
          <view class="form-group">
            <text class="label">{{ t('login.email') }}</text>
            <input
              v-model="fpEmail"
              type="text"
              inputmode="email"
              class="input"
              :placeholder="t('login.emailPlaceholder')"
              placeholder-class="placeholder"
            />
          </view>
          <view class="form-group">
            <text class="label">{{ t('login.verificationCode') }}</text>
            <view class="code-row">
              <input
                v-model="fpCode"
                type="text"
                inputmode="numeric"
                class="input input-code"
                :placeholder="t('login.verificationPlaceholder')"
                placeholder-class="placeholder"
              />
              <view
                class="send-code-btn"
                :class="{ disabled: sendingCode || cooldown > 0 || !fpEmail.trim() }"
                @tap="handleSendCode"
              >
                <text class="send-code-text">{{ sendCodeLabel }}</text>
              </view>
            </view>
          </view>
          <view class="form-group">
            <text class="label">{{ t('login.newPassword') }}</text>
            <view class="input-wrap">
              <input
                v-model="fpNew"
                :type="showResetNew ? 'text' : 'password'"
                class="input input-in-wrap"
                :placeholder="t('login.newPasswordPlaceholder')"
                placeholder-class="placeholder"
              />
              <view class="eye-btn" @tap="showResetNew = !showResetNew">
                <AppIcon name="eye" size="sm" :color="showResetNew ? 'primary' : 'gray'" />
              </view>
            </view>
          </view>
          <view class="form-group">
            <text class="label">{{ t('login.confirmNewPassword') }}</text>
            <view class="input-wrap">
              <input
                v-model="fpConfirm"
                :type="showResetConfirm ? 'text' : 'password'"
                class="input input-in-wrap"
                :placeholder="t('login.confirmPasswordPlaceholder')"
                placeholder-class="placeholder"
              />
              <view class="eye-btn" @tap="showResetConfirm = !showResetConfirm">
                <AppIcon name="eye" size="sm" :color="showResetConfirm ? 'primary' : 'gray'" />
              </view>
            </view>
          </view>
          <view
            class="submit-btn"
            :class="{ disabled: resetting || !canSubmitReset }"
            @tap="handleReset"
          >
            <text class="submit-btn-text">{{ resetting ? t('login.updatingPassword') : t('login.updatePassword') }}</text>
          </view>
          <text class="back-link" @tap="goSignIn">{{ t('login.backToSignIn') }}</text>
        </template>
      </view>
      <text class="copyright">{{ t('login.copyright') }}</text>
    </view>
  </view>
</template>

<script setup lang="ts">
import { ref, onMounted, computed, watchEffect } from 'vue'
import { useI18n } from 'vue-i18n'
import { getStatusBarHeight } from '../../utils/statusBar'
import { usAppLogin } from '../../services/usAppAuth'
import { sendPasswordResetCode, confirmPasswordReset } from '../../services/passwordReset'
import {
  saveAuthSession,
  loadSavedCredentials,
  saveRememberPreference,
  isLoggedIn,
} from '../../utils/authSession'
import { performInitialOfflineSync } from '../../utils/offlineSyncManager'
import {
  findOfflineAuthAccount,
  initOfflineSqlite,
  isNetworkOnline,
  saveOfflineAuthAccount,
} from '../../utils/sqliteSync'
import AppIcon from '../../components/AppIcon.vue'

const { t } = useI18n()
const statusBarHeight = getStatusBarHeight()

type Mode = 'signin' | 'forgot'
const mode = ref<Mode>('signin')

const email = ref('')
const password = ref('')
const rememberMe = ref(false)
const isLoading = ref(false)

/** 密码可见切换（登录 / 重置密码） */
const showSignInPassword = ref(false)
const showResetNew = ref(false)
const showResetConfirm = ref(false)

const fpEmail = ref('')
const fpCode = ref('')
const fpNew = ref('')
const fpConfirm = ref('')
const sendingCode = ref(false)
const resetting = ref(false)
const cooldown = ref(0)

const CODE_COOLDOWN_SEC = 60
const MIN_PASSWORD_LEN = 6

watchEffect((onCleanup) => {
  if (cooldown.value <= 0) return
  const id = setTimeout(() => {
    cooldown.value = Math.max(0, cooldown.value - 1)
  }, 1000)
  onCleanup(() => clearTimeout(id))
})

const sendCodeLabel = computed(() => {
  if (sendingCode.value) return t('login.sendingCode')
  if (cooldown.value > 0) return t('login.resendIn', { s: cooldown.value })
  return t('login.sendCode')
})

const canSubmitReset = computed(() => {
  const em = fpEmail.value.trim()
  const code = fpCode.value.trim()
  const np = fpNew.value
  const cf = fpConfirm.value
  return (
    !!em &&
    !!code &&
    np.length >= MIN_PASSWORD_LEN &&
    np === cf &&
    !resetting.value
  )
})

function displayNameFromEmail(mail: string): string {
  const m = mail.trim()
  if (!m) return 'Employee'
  const at = m.indexOf('@')
  return at > 0 ? m.slice(0, at) : m
}

onMounted(() => {
  if (isLoggedIn()) {
    const sid = uni.getStorageSync('storeId')
    if (sid) {
      uni.reLaunch({ url: '/pages/index/index' })
    } else {
      uni.reLaunch({ url: '/pages/store-select/store-select' })
    }
    return
  }
  const saved = loadSavedCredentials()
  if (saved.remember) {
    rememberMe.value = true
    email.value = saved.email
    password.value = saved.password
  }
})

function onRememberChange(e: { detail?: { value?: boolean } }) {
  rememberMe.value = !!e.detail?.value
}

function goForgot() {
  fpEmail.value = email.value.trim()
  fpCode.value = ''
  fpNew.value = ''
  fpConfirm.value = ''
  cooldown.value = 0
  showResetNew.value = false
  showResetConfirm.value = false
  mode.value = 'forgot'
}

function goSignIn() {
  mode.value = 'signin'
  fpCode.value = ''
  fpNew.value = ''
  fpConfirm.value = ''
  cooldown.value = 0
  showResetNew.value = false
  showResetConfirm.value = false
  showSignInPassword.value = false
}

function toastResetError(e: unknown): string {
  if (e instanceof Error && e.message === 'RESET_API_NOT_AVAILABLE') {
    return t('login.resetNotAvailable')
  }
  return e instanceof Error ? e.message : t('login.resetFailed')
}

async function handleSendCode() {
  const em = fpEmail.value.trim()
  if (!em) {
    uni.showToast({ title: t('login.resetEmailRequired'), icon: 'none' })
    return
  }
  if (cooldown.value > 0 || sendingCode.value) return
  sendingCode.value = true
  try {
    await sendPasswordResetCode(em)
    cooldown.value = CODE_COOLDOWN_SEC
    uni.showToast({ title: t('login.resetCodeSent'), icon: 'success' })
  } catch (e: unknown) {
    uni.showToast({
      title: toastResetError(e),
      icon: 'none',
      duration: 2800,
    })
  } finally {
    sendingCode.value = false
  }
}

async function handleReset() {
  const em = fpEmail.value.trim()
  const code = fpCode.value.trim()
  const np = fpNew.value
  const cf = fpConfirm.value
  if (!em || !code) {
    uni.showToast({ title: t('login.resetMissingFields'), icon: 'none' })
    return
  }
  if (np.length < MIN_PASSWORD_LEN) {
    uni.showToast({ title: t('login.resetPasswordTooShort'), icon: 'none' })
    return
  }
  if (np !== cf) {
    uni.showToast({ title: t('login.resetPasswordMismatch'), icon: 'none' })
    return
  }
  resetting.value = true
  try {
    await confirmPasswordReset({ email: em, code, newPassword: np })
    uni.showToast({ title: t('login.resetSuccess'), icon: 'success' })
    email.value = em
    password.value = ''
    goSignIn()
  } catch (e: unknown) {
    uni.showToast({
      title: toastResetError(e),
      icon: 'none',
      duration: 2800,
    })
  } finally {
    resetting.value = false
  }
}

const handleLogin = async () => {
  const em = email.value.trim()
  const pw = password.value
  if (!em || !pw) {
    uni.showToast({ title: t('login.fillRequired'), icon: 'none' })
    return
  }
  isLoading.value = true
  try {
    await initOfflineSqlite()
    const online = await isNetworkOnline()

    if (!online) {
      const offline = await findOfflineAuthAccount(em, pw)
      if (!offline?.token) {
        uni.showToast({ title: t('login.offlineLoginFailed'), icon: 'none', duration: 2800 })
        return
      }
      saveRememberPreference(rememberMe.value, em, pw)
      saveAuthSession({
        token: offline.token,
        refreshToken: offline.refreshToken || '',
        locations: offline.locations ?? [],
        displayName: offline.displayName || displayNameFromEmail(em),
        email: em,
      })
      uni.showToast({ title: t('login.offlineLoginSuccess'), icon: 'success' })
      setTimeout(() => {
        uni.redirectTo({ url: '/pages/store-select/store-select' })
      }, 400)
      return
    }

    const res = await usAppLogin({ email: em, password: pw })
    if (!res.token) {
      uni.showToast({ title: t('login.loginFailed'), icon: 'none' })
      return
    }
    saveRememberPreference(rememberMe.value, em, pw)
    saveAuthSession({
      token: res.token,
      refreshToken: res.refreshToken || '',
      locations: res.locations ?? [],
      displayName: displayNameFromEmail(em),
      email: em,
    })
    await saveOfflineAuthAccount({
      email: em,
      password: pw,
      token: res.token,
      refreshToken: res.refreshToken || '',
      locations: res.locations ?? [],
      displayName: displayNameFromEmail(em),
    })
    try {
      await performInitialOfflineSync()
    } catch {
      // 预同步失败不阻断登录
    }
    uni.showToast({ title: t('login.loginSuccess'), icon: 'success' })
    setTimeout(() => {
      uni.redirectTo({ url: '/pages/store-select/store-select' })
    }, 400)
  } catch (e: unknown) {
    const msg = e instanceof Error ? e.message : String(e)
    uni.showToast({ title: msg || t('login.loginFailed'), icon: 'none', duration: 2500 })
  } finally {
    isLoading.value = false
  }
}
</script>

<style scoped>
.login-page {
  min-height: 100vh;
  background: #f9fafb;
  padding-bottom: 48rpx;
}

.header-hero {
  background: linear-gradient(135deg, var(--theme-primary), var(--theme-primary-dark));
  padding: 0 48rpx 24rpx;
  text-align: center;
  flex-shrink: 0;
}

.logo-section {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.login-logo {
  width: 360rpx;
  height: 120rpx;
  margin-bottom: 12rpx;
  background: rgba(255, 255, 255, 0.92);
  border-radius: 16rpx;
  padding: 16rpx;
}

.hero-sub {
  font-size: 28rpx;
  color: rgba(255, 255, 255, 0.85);
}

.form-wrap {
  padding: 24rpx 48rpx 48rpx;
}

.form-card {
  background: #fff;
  padding: 48rpx;
  border-radius: 20rpx;
  box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.06);
}

.reset-heading {
  display: block;
  text-align: center;
  font-size: 36rpx;
  font-weight: 600;
  color: #111827;
  margin-bottom: 8rpx;
}

.form-group {
  margin-bottom: 40rpx;
}

.label {
  font-size: 30rpx;
  font-weight: 500;
  color: #374151;
  display: block;
  margin-bottom: 16rpx;
}

.input {
  height: 96rpx;
  min-height: 48px;
  padding: 0 24rpx;
  background: #f3f4f6;
  border-radius: 16rpx;
  font-size: 32rpx;
  display: block;
  width: 100%;
  box-sizing: border-box;
}

.input-wrap {
  display: flex;
  align-items: center;
  background: #f3f4f6;
  border-radius: 16rpx;
  padding-right: 12rpx;
  box-sizing: border-box;
}

.input-in-wrap {
  flex: 1;
  min-width: 0;
  width: auto;
  background: transparent;
  border-radius: 16rpx 0 0 16rpx;
}

.eye-btn {
  width: 72rpx;
  height: 72rpx;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.code-row {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 16rpx;
}

.input-code {
  flex: 1;
  min-width: 0;
  width: auto;
}

.send-code-btn {
  flex-shrink: 0;
  height: 96rpx;
  min-height: 48px;
  padding: 0 20rpx;
  max-width: 240rpx;
  border-radius: 16rpx;
  border: 2rpx solid #d1d5db;
  background: #ffffff;
  display: flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
}

.send-code-btn.disabled {
  opacity: 0.45;
  pointer-events: none;
}

.send-code-text {
  font-size: 26rpx;
  font-weight: 600;
  color: var(--theme-primary);
  text-align: center;
  line-height: 1.2;
}

.placeholder {
  color: #9ca3af;
}

.form-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 40rpx;
}

.remember-row {
  display: flex;
  align-items: center;
  gap: 16rpx;
}

.remember-text {
  font-size: 28rpx;
  color: #374151;
}

.forgot-link {
  font-size: 28rpx;
  color: var(--theme-primary);
  font-weight: 500;
}

.back-link {
  display: block;
  text-align: center;
  margin-top: 32rpx;
  font-size: 28rpx;
  color: #6b7280;
  font-weight: 500;
}

.submit-btn {
  width: 100%;
  height: 96rpx;
  background: var(--theme-primary);
  border-radius: 16rpx;
  display: flex;
  align-items: center;
  justify-content: center;
}

.submit-btn.disabled {
  opacity: 0.7;
  pointer-events: none;
}

.submit-btn-text {
  font-size: 32rpx;
  font-weight: 600;
  color: #ffffff;
  line-height: 1;
}

.copyright {
  display: block;
  text-align: center;
  font-size: 24rpx;
  color: #9ca3af;
  margin-top: 48rpx;
}
</style>
