<template>
  <view class="login-shell">
    <AppNavbar title="登录注册" />

    <view class="login-page">
      <AtTabs
        class="login-tabs"
        :current="currentTab"
        :tab-list="modeTabs"
        :swipeable="false"
        @click="switchMode"
      >
        <AtTabsPane :current="currentTab" :index="LOGIN_TAB_INDEX">
          <AtInput v-model:value="loginForm.username" name="loginUsername" title="账号" placeholder="请输入账号" />

          <AtInput
            v-model:value="loginForm.password"
            name="loginPassword"
            title="密码"
            type="password"
            placeholder="请输入密码"
          />

          <view v-if="isCaptchaOn" class="captcha-row">
            <AtInput v-model:value="loginForm.captchaCode" name="loginCaptchaCode" title="验证码" placeholder="请输入验证码" />
            <image class="captcha-img" :src="captchaUrl" mode="aspectFit" @tap="loadCaptcha" />
          </view>
        </AtTabsPane>

        <AtTabsPane :current="currentTab" :index="REGISTER_TAB_INDEX">
          <AtInput v-model:value="registerForm.username" name="registerUsername" title="账号" placeholder="请输入账号" />

          <AtInput v-model:value="registerForm.nickname" name="nickname" title="昵称" placeholder="默认使用账号" />

          <AtInput
            v-model:value="registerForm.password"
            name="registerPassword"
            title="密码"
            type="password"
            placeholder="请输入密码"
          />

          <AtInput
            v-model:value="registerForm.confirmPassword"
            name="confirmPassword"
            title="确认密码"
            type="password"
            placeholder="请再次输入密码"
          />

          <AtInput v-model:value="registerForm.email" name="email" title="邮箱" type="email" placeholder="选填" />

          <AtInput v-model:value="registerForm.phoneNumber" name="phoneNumber" title="手机号" type="tel" placeholder="选填" />

          <view v-if="isCaptchaOn" class="captcha-row">
            <AtInput v-model:value="registerForm.captchaCode" name="registerCaptchaCode" title="验证码" placeholder="请输入验证码" />
            <image class="captcha-img" :src="captchaUrl" mode="aspectFit" @tap="loadCaptcha" />
          </view>
        </AtTabsPane>
      </AtTabs>
    </view>

    <view class="login-actions">
      <AtButton class="login-submit-btn" type="primary" @click="handleSubmit">{{ submitButtonText }}</AtButton>
    </view>
  </view>
</template>

<script setup lang="ts">
import Taro, { useDidShow } from '@tarojs/taro'
import { computed, reactive, ref } from 'vue'
import { getCaptchaApi, getConfigApi, loginApi, registerApi } from '@/api/auth'
import { rsaEncrypt } from '@/utils/crypt'
import { isLoggedIn } from '@/utils/auth'
import { useUserStore } from '@/stores/user'
import AppNavbar from '@/components/AppNavbar.vue'

const LOGIN_TAB_INDEX = 0
const REGISTER_TAB_INDEX = 1

interface CaptchaForm {
  captchaCode: string
  captchaCodeKey: string
}

interface LoginForm extends CaptchaForm {
  username: string
  password: string
}

interface RegisterForm extends LoginForm {
  nickname: string
  confirmPassword: string
  email: string
  phoneNumber: string
}

const currentTab = ref(LOGIN_TAB_INDEX)
const captchaUrl = ref('')
const isCaptchaOn = ref(false)
const userStore = useUserStore()

const loginForm = reactive<LoginForm>({
  username: '',
  password: '',
  captchaCode: '',
  captchaCodeKey: ''
})

const registerForm = reactive<RegisterForm>({
  username: '',
  nickname: '',
  password: '',
  confirmPassword: '',
  email: '',
  phoneNumber: '',
  captchaCode: '',
  captchaCodeKey: ''
})

const isRegisterTab = computed(() => currentTab.value === REGISTER_TAB_INDEX)
const submitButtonText = computed(() => (isRegisterTab.value ? '注册并登录' : '登录'))
const modeTabs = [
  { title: '登录' },
  { title: '注册' }
]

useDidShow(() => {
  if (isLoggedIn()) {
    Taro.switchTab({ url: '/pages/collaboration/records/index' })
    return
  }
  loadConfig()
})

async function loadConfig() {
  const { data } = await getConfigApi()
  userStore.setConfig(data)
  isCaptchaOn.value = Boolean(data.isCaptchaOn)
  await loadCaptcha()
}

async function loadCaptcha() {
  if (!isCaptchaOn.value) return
  const { data } = await getCaptchaApi()
  getCurrentCaptchaForm().captchaCodeKey = data.captchaCodeKey || ''
  captchaUrl.value = `data:image/jpeg;base64,${data.captchaCodeImg || ''}`
}

function switchMode(nextTab: number) {
  if (currentTab.value === nextTab) return
  currentTab.value = nextTab
  clearCurrentCaptcha()
  loadCaptcha()
}

function getCurrentCaptchaForm(): CaptchaForm {
  return isRegisterTab.value ? registerForm : loginForm
}

function clearCurrentCaptcha() {
  const captchaForm = getCurrentCaptchaForm()
  captchaForm.captchaCode = ''
  captchaForm.captchaCodeKey = ''
}

function handleSubmit() {
  if (isRegisterTab.value) {
    handleRegister()
    return
  }
  handleLogin()
}

async function handleLogin() {
  if (!validateLoginForm()) return
  try {
    await submitLoginForm()
  } catch {
    await loadCaptcha()
  }
}

async function handleRegister() {
  if (!validateRegisterForm()) return
  try {
    await submitRegisterForm()
  } catch {
    await loadCaptcha()
  }
}

async function submitLoginForm() {
  const response = await login()
  userStore.setSession(response.data)
  Taro.switchTab({ url: '/pages/collaboration/records/index' })
}

async function submitRegisterForm() {
  const response = await register()
  userStore.setSession(response.data)
  Taro.switchTab({ url: '/pages/collaboration/records/index' })
}

function login() {
  return loginApi({
    username: loginForm.username,
    password: rsaEncrypt(loginForm.password),
    captchaCode: loginForm.captchaCode,
    captchaCodeKey: loginForm.captchaCodeKey
  })
}

function register() {
  return registerApi({
    username: registerForm.username,
    nickname: registerForm.nickname,
    password: rsaEncrypt(registerForm.password),
    confirmPassword: rsaEncrypt(registerForm.confirmPassword),
    email: registerForm.email,
    phoneNumber: registerForm.phoneNumber,
    captchaCode: registerForm.captchaCode,
    captchaCodeKey: registerForm.captchaCodeKey
  })
}

function validateLoginForm() {
  if (loginForm.username && loginForm.password) return true
  showError('请输入账号和密码')
  return false
}

function validateRegisterForm() {
  if (!registerForm.username || !registerForm.password) {
    showError('请输入账号和密码')
    return false
  }
  return validateRegisterPassword()
}

function validateRegisterPassword() {
  if (!registerForm.confirmPassword) {
    showError('请再次输入密码')
    return false
  }
  if (registerForm.password !== registerForm.confirmPassword) {
    showError('两次输入的密码不一致')
    return false
  }
  return true
}

function showError(title: string) {
  Taro.showToast({ title, icon: 'none' })
}
</script>

<style lang="scss">
.login-shell {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  background: $bg-page;
}

.login-page {
  flex: 1;
  width: 100%;
  min-height: 0;
  padding: $space-xl $space-xl calc(#{$control-height} + #{$space-xl} * 3 + env(safe-area-inset-bottom));
}

.login-tabs {
  width: 100%;
  max-width: 720px;
  margin: 0 auto;
}

.captcha-row {
  display: grid;
  grid-template-columns: 1fr 220px;
  gap: 12px;
  align-items: center;
}

.login-actions {
  position: fixed;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 10;
  box-sizing: border-box;
  display: flex;
  justify-content: center;
  padding: $space-md $space-xl calc(#{$space-md} + env(safe-area-inset-bottom));
  background: $bg-page;
}

.login-submit-btn.at-button {
  width: 100%;
  max-width: 720px;
  height: $control-height;
  font-size: $font-lg;
  line-height: $control-height;
  color: $color-white;
  background: $color-primary;
  border-color: transparent;
  border-radius: $radius-md;
}

.captcha-img {
  width: 220px;
  height: 76px;
  background: $bg-muted;
  border: 1px solid $border-color-strong;
  border-radius: $radius-md;
}
</style>
