<template>
  <div class='login-page'>
    <div class='bg-geometry'></div>
    <div class='login-stack'>
      <el-card class='login-card' shadow='never'>
        <div class='brand-row'>
          <div class='brand-chip'>B</div>
          <span class='brand-name'>Bastion SSO</span>
        </div>
        <h1 class='login-title'>登录</h1>
        <p class='login-subtitle'>使用邮箱或手机号继续</p>
        <el-form :model='form' :rules='rules' ref='formRef' @submit.prevent='handleLogin'>
          <el-form-item prop='account'>
            <el-input v-model='form.account' placeholder='邮箱、手机号' class='login-input' />
          </el-form-item>
          <el-form-item prop='password'>
            <el-input v-model='form.password' type='password' show-password placeholder='密码' class='login-input' />
          </el-form-item>
          <div class='assist-links'>
            <a href='javascript:void(0)'>无法访问您的帐户？</a>
            <a href='javascript:void(0)' @click='applyDialogVisible = true'>账号申请</a>
          </div>
          <div class='btn-row'>
            <el-button :loading='submitting' type='primary' class='login-btn' @click='handleLogin'>登录</el-button>
          </div>
        </el-form>
      </el-card>
    </div>

    <el-dialog v-model='forcePasswordDialogVisible' title='请先修改密码' width='480px' :close-on-click-modal='true' :show-close='true'>
      <el-form :model='forcePasswordForm' label-width='96px'>
        <el-form-item label='当前密码'>
          <el-input v-model='forcePasswordForm.current_password' type='password' show-password />
        </el-form-item>
        <el-form-item label='新密码'>
          <el-input v-model='forcePasswordForm.password' type='password' show-password />
        </el-form-item>
        <el-form-item label='确认新密码'>
          <el-input v-model='forcePasswordForm.password_confirmation' type='password' show-password />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click='forcePasswordDialogVisible = false'>稍后修改</el-button>
        <el-button @click='handleForceUserLogout'>退出当前账号</el-button>
        <el-button type='primary' :loading='forcingPassword' @click='submitForcePasswordChange'>确认修改并进入系统</el-button>
      </template>
    </el-dialog>

    <el-dialog v-model='applyDialogVisible' title='账号申请' width='520px'>
      <el-form ref='applyFormRef' :model='applyForm' :rules='applyRules' label-width='90px'>
        <el-form-item label='昵称' prop='nickname'>
          <el-input v-model='applyForm.nickname' placeholder='请输入昵称' />
        </el-form-item>
        <el-form-item label='邮箱' prop='email'>
          <el-input v-model='applyForm.email' placeholder='请输入邮箱' />
        </el-form-item>
        <el-form-item label='手机号' prop='phone'>
          <el-input v-model='applyForm.phone' placeholder='请输入手机号' />
        </el-form-item>
        <el-form-item label='密码' prop='password'>
          <el-input v-model='applyForm.password' type='password' show-password placeholder='请输入密码' />
        </el-form-item>
        <el-form-item label='确认密码' prop='password_confirmation'>
          <el-input v-model='applyForm.password_confirmation' type='password' show-password placeholder='请再次输入密码' />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click='applyDialogVisible = false'>取消</el-button>
        <el-button type='primary' :loading='applying' @click='submitApplyAccount'>提交申请</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang='ts'>
import type { FormInstance, FormRules } from 'element-plus'
import { ElMessage } from 'element-plus'
import { onMounted, reactive, ref } from 'vue'
import { useRouter } from 'vue-router'
import { authApi } from '@/api/auth'
import { getToken } from '@/composables/token'
import { removeToken, setToken } from '@/composables/token'
import { useAuthStore } from '@/stores/auth'

const router = useRouter()
const authStore = useAuthStore()
const formRef = ref<FormInstance>()
const submitting = ref(false)
const forcingPassword = ref(false)
const forcePasswordDialogVisible = ref(false)
const applyDialogVisible = ref(false)
const applying = ref(false)
const applyFormRef = ref<FormInstance>()
const forcePasswordForm = reactive({ current_password: '', password: '', password_confirmation: '' })

const form = reactive({ account: '', password: '' })
const applyForm = reactive({
  nickname: '',
  email: '',
  phone: '',
  password: '',
  password_confirmation: '',
})
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
const phoneRegex = /^1\d{10}$/
const rules: FormRules = {
  account: [{
    required: true,
    trigger: 'blur',
    validator: (_rule, value, callback) => {
      const account = String(value || '').trim()
      if (!account) {
        callback(new Error('请输入邮箱或手机号'))
        return
      }
      if (!emailRegex.test(account) && !phoneRegex.test(account)) {
        callback(new Error('请输入正确的邮箱或手机号'))
        return
      }
      callback()
    },
  }],
  password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
}
const applyRules: FormRules = {
  nickname: [{ required: true, message: '请输入昵称', trigger: 'blur' }],
  email: [{ required: true, message: '请输入邮箱', trigger: 'blur' }],
  phone: [{ required: true, message: '请输入手机号', trigger: 'blur' }],
  password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
  password_confirmation: [{ required: true, message: '请再次输入密码', trigger: 'blur' }],
}

async function handleLogin(): Promise<void> {
  const valid = await formRef.value?.validate().catch(() => false)
  if (!valid) {
    return
  }

  submitting.value = true
  try {
    const account = form.account.trim()
    const isEmail = emailRegex.test(account)
    const payload = {
      email: isEmail ? account : undefined,
      phone: isEmail ? undefined : account,
      password: form.password,
    }
    const response = await authApi.login(payload)
    setToken(response.data.token)
    const me = await authApi.me()
    authStore.setAuth(me.data.user, me.data.permissions)
    if (Boolean((me.data.user as any)?.force_password_change)) {
      forcePasswordForm.current_password = form.password
      forcePasswordForm.password = ''
      forcePasswordForm.password_confirmation = ''
      forcePasswordDialogVisible.value = true
      return
    }
    ElMessage.success('登录成功')
    await router.replace('/')
  } catch (error: any) {
    const first = error?.errors ? (Object.values(error.errors)[0] as string[])?.[0] : null
    ElMessage.error(first || error?.message || '登录失败')
  } finally {
    submitting.value = false
  }
}

async function submitForcePasswordChange(): Promise<void> {
  if (!forcePasswordForm.current_password || !forcePasswordForm.password || !forcePasswordForm.password_confirmation) {
    ElMessage.warning('请完整填写密码信息')
    return
  }

  forcingPassword.value = true
  try {
    await authApi.updatePassword(forcePasswordForm)
    const me = await authApi.me()
    authStore.setAuth(me.data.user, me.data.permissions)
    forcePasswordDialogVisible.value = false
    ElMessage.success('密码修改成功，欢迎使用')
    await router.replace('/')
  } catch (error: any) {
    const first = error?.errors ? (Object.values(error.errors)[0] as string[])?.[0] : null
    ElMessage.error(first || error?.message || '修改密码失败')
  } finally {
    forcingPassword.value = false
  }
}

async function handleForceUserLogout(): Promise<void> {
  try {
    await authApi.logout()
  } catch (_error) {
    // ignore
  }
  removeToken()
  authStore.clearAuth()
  forcePasswordDialogVisible.value = false
  form.password = ''
  ElMessage.success('已退出当前账号')
}

async function submitApplyAccount(): Promise<void> {
  const valid = await applyFormRef.value?.validate().catch(() => false)
  if (!valid) {
    return
  }
  if (applyForm.password !== applyForm.password_confirmation) {
    ElMessage.warning('两次输入的密码不一致')
    return
  }

  applying.value = true
  try {
    await authApi.applyAccount(applyForm)
    ElMessage.success('申请提交成功，请联系或等待管理员添加权限')
    applyDialogVisible.value = false
    Object.assign(applyForm, {
      nickname: '',
      email: '',
      phone: '',
      password: '',
      password_confirmation: '',
    })
  } catch (error: any) {
    const first = error?.errors ? (Object.values(error.errors)[0] as string[])?.[0] : null
    ElMessage.error(first || error?.message || '账号申请失败')
  } finally {
    applying.value = false
  }
}

onMounted(async () => {
  const token = getToken()
  if (!token) {
    return
  }

  try {
    const me = await authApi.me()
    authStore.setAuth(me.data.user, me.data.permissions)
    if (Boolean((me.data.user as any)?.force_password_change)) {
      forcePasswordForm.current_password = ''
      forcePasswordForm.password = ''
      forcePasswordForm.password_confirmation = ''
      forcePasswordDialogVisible.value = true
      return
    } else {
      await router.replace('/')
    }
  } catch (_error) {
    // ignore: invalid token will be handled by route guard
  }
})
</script>

<style scoped>
.login-page {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #f4f6f9;
  position: relative;
  overflow: hidden;
  padding: 40px 18px;
}
.bg-geometry {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(120deg, rgba(179, 186, 197, 0.2) 0 36%, transparent 36% 100%),
    linear-gradient(330deg, rgba(180, 184, 210, 0.18) 0 28%, transparent 28% 100%);
  pointer-events: none;
}
.login-stack {
  width: min(560px, 100%);
  display: flex;
  flex-direction: column;
  gap: 16px;
  position: relative;
  z-index: 2;
}
.login-card {
  border: 1px solid #e5e7eb;
  border-radius: 10px;
  box-shadow: 0 8px 22px rgba(15, 23, 42, 0.1);
}
.brand-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 14px;
}
.brand-chip {
  width: 26px;
  height: 26px;
  border-radius: 6px;
  background: #0f766e;
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  font-weight: 700;
}
.brand-name {
  color: #475569;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.02em;
}
.login-title {
  margin: 0 0 10px;
  font-size: 28px;
  font-weight: 600;
  color: #1f2937;
}
.login-subtitle {
  margin: 0 0 22px;
  color: #4b5563;
  font-size: 14px;
}
.assist-links {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 2px;
}
.assist-links a {
  color: #0067b8;
  text-decoration: none;
  font-size: 14px;
}
.assist-links a:hover { text-decoration: underline; }
.btn-row {
  display: flex;
  justify-content: flex-end;
  margin-top: 22px;
}
.login-btn {
  min-width: 110px;
  height: 38px;
  border-radius: 6px;
  font-size: 14px;
}
:deep(.el-card__body) {
  padding: 34px 38px 30px;
}

:deep(.el-form-item) {
  margin-bottom: 16px;
}
:deep(.login-input .el-input__wrapper) {
  box-shadow: none !important;
  border-radius: 6px;
  border-bottom: 1px solid #737373;
  padding-left: 0;
  padding-right: 0;
}
:deep(.login-input .el-input__wrapper.is-focus) {
  border-bottom: 1px solid #0067b8;
}
:deep(.login-input .el-input__inner) {
  height: 34px;
  font-size: 14px;
}
:deep(.el-form-item__error) {
  font-size: 12px;
}

@media (max-width: 640px) {
  .login-page {
    padding: 24px 14px;
  }
  :deep(.el-card__body) {
    padding: 24px 22px;
  }
  .login-title { font-size: 24px; }
  .login-subtitle { font-size: 13px; }
  .assist-links a { font-size: 13px; }
  .login-btn { font-size: 13px; }
}
</style>
