<!-- 登录页面 -->
<template>
  <div class="login-page flex w-full h-screen">
    <LoginLeftView />

    <div class="auth-stage relative flex-1">
      <AuthTopBar />

      <div class="auth-right-wrap">
        <div class="form">
          <div class="login-card-brand">
            <ArtLogo size="34" />
            <span>{{ AppConfig.systemInfo.shortName }}</span>
            <small>用户门户</small>
          </div>
          <h3 class="title">{{ $t('login.title') }}</h3>
          <p class="sub-title">{{ $t('login.subTitle') }}</p>
          <ElForm
            ref="formRef"
            :model="formData"
            :rules="rules"
            :key="formKey"
            @keyup.enter="handleSubmit"
            style="margin-top: 25px"
          >
            <ElFormItem v-if="isDev" prop="account">
              <ElSelect v-model="formData.account" @change="setupAccount">
                <ElOption
                  v-for="account in accounts"
                  :key="account.key"
                  :label="account.label"
                  :value="account.key"
                >
                  <span>{{ account.label }}</span>
                </ElOption>
              </ElSelect>
            </ElFormItem>
            <div class="field-label">{{ $t('login.accountLabel') }}</div>
            <ElFormItem prop="username">
              <ElInput
                class="custom-height"
                :placeholder="$t('login.placeholder.username')"
                v-model.trim="formData.username"
              />
            </ElFormItem>
            <div class="field-label">{{ $t('login.passwordLabel') }}</div>
            <ElFormItem prop="password">
              <ElInput
                class="custom-height"
                :placeholder="$t('login.placeholder.password')"
                v-model.trim="formData.password"
                type="password"
                autocomplete="off"
                show-password
              />
            </ElFormItem>

            <div class="flex-cb mt-2 text-sm">
              <ElCheckbox v-model="formData.rememberPassword">{{
                $t('login.rememberPwd')
              }}</ElCheckbox>
              <RouterLink class="text-theme" :to="{ name: 'ForgetPassword' }">{{
                $t('login.forgetPwd')
              }}</RouterLink>
            </div>

            <div style="margin-top: 30px">
              <ElButton
                class="w-full custom-height"
                type="primary"
                @click="handleSubmit"
                :loading="loading"
                v-ripple
              >
                {{ $t('login.btnText') }}
              </ElButton>
            </div>

            <template v-if="ssoProviders.length">
              <ElDivider>企业身份登录</ElDivider>
              <div class="grid gap-2">
                <ElButton
                  v-for="provider in ssoProviders"
                  :key="provider.code"
                  class="w-full"
                  @click="startSSO(provider.code)"
                >
                  使用 {{ provider.display_name }} 登录
                </ElButton>
              </div>
            </template>

            <div class="login-register-row mt-5 text-sm">
              <span>{{ $t('login.noAccount') }}</span>
              <RouterLink class="text-theme" :to="{ name: 'Register' }">{{
                $t('login.register')
              }}</RouterLink>
            </div>
          </ElForm>
        </div>

        <!-- 安全徽标 -->
        <div class="security-badge">
          <span class="sb-dot"></span>
          <span>{{ $t('login.securityBadge') }}</span>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
  import AppConfig from '@/config'
  import { useUserStore } from '@/store/modules/user'
  import { useI18n } from 'vue-i18n'
  import { HttpError } from '@/utils/http/error'
  import { exchangeSSOCode, fetchLogin, fetchSSOProviders, fetchTOTPLogin, SSOProvider } from '@/api/auth'
  import { ElMessage, ElMessageBox, ElNotification, type FormInstance, type FormRules } from 'element-plus'

  defineOptions({ name: 'Login' })

  const { t, locale } = useI18n()
  const formKey = ref(0)

  // 监听语言切换，重置表单
  watch(locale, () => {
    formKey.value++
  })

  type AccountKey = 'super' | 'admin' | 'user'

  export interface Account {
    key: AccountKey
    label: string
    userName: string
    password: string
    roles: string[]
  }

  // Built-in demo accounts are for local development only. Shipping known
  // passwords in a production bundle turns them into a backdoor, so the
  // selector is only populated when Vite runs in DEV mode.
  const isDev = import.meta.env.DEV
  const accounts = computed<Account[]>(() => {
    if (!isDev) return []
    return [
      {
        key: 'super',
        label: t('login.roles.super'),
        userName: 'Super',
        password: '123456',
        roles: ['R_SUPER']
      },
      {
        key: 'admin',
        label: t('login.roles.admin'),
        userName: 'Admin',
        password: '123456',
        roles: ['R_ADMIN']
      },
      {
        key: 'user',
        label: t('login.roles.user'),
        userName: 'User',
        password: '123456',
        roles: ['R_USER']
      }
    ]
  })

  const userStore = useUserStore()
  const router = useRouter()
  const route = useRoute()

  const systemName = AppConfig.systemInfo.name
  const formRef = ref<FormInstance>()

  const formData = reactive({
    account: '',
    username: '',
    password: '',
    rememberPassword: true
  })

  const rules = computed<FormRules>(() => ({
    username: [{ required: true, message: t('login.placeholder.username'), trigger: 'blur' }],
    password: [{ required: true, message: t('login.placeholder.password'), trigger: 'blur' }]
  }))

  const loading = ref(false)
  const ssoProviders = ref<SSOProvider[]>([])

  onMounted(async () => {
    if (isDev) {
      setupAccount('super')
    }
    try {
      ssoProviders.value = await fetchSSOProviders()
      // 回调 302 把参数放在 # 之前的 query(SPA hash 路由看不到),这里合并读取。
      const pathQuery = new URLSearchParams(window.location.search)
      const ssoCode = (route.query.sso_code as string) || pathQuery.get('sso_code') || ''
      const ssoError = (route.query.sso_error as string) || pathQuery.get('sso_error') || ''
      if (ssoCode) {
        loading.value = true
        const result = await exchangeSSOCode(ssoCode)
        if (!result.token) throw new Error('SSO exchange returned no token')
        userStore.setToken(result.token, result.refreshToken || '')
        userStore.setLoginStatus(true)
        history.replaceState(null, '', window.location.pathname + window.location.hash)
        await router.replace('/')
      } else if (ssoError) {
        const errorText = ({
          unbound: '该企业账号尚未绑定本系统账号，请先用账号密码登录后在「账号安全」中绑定',
          disabled: '账号已被停用',
          expired: '登录状态已过期，请重新扫码',
          login_failed: '企业登录失败，请重试或联系管理员'
        } as Record<string, string>)[ssoError] || ssoError
        ElMessage.error(errorText)
        history.replaceState(null, '', window.location.pathname + window.location.hash)
      }
    } finally {
      loading.value = false
    }
  })

  function startSSO(code: string) {
    window.location.assign(`/api/v1/portal/sso/${encodeURIComponent(code)}/start`)
  }

  // 设置账号
  const setupAccount = (key: AccountKey) => {
    const selectedAccount = accounts.value.find((account: Account) => account.key === key)
    formData.account = key
    formData.username = selectedAccount?.userName ?? ''
    formData.password = selectedAccount?.password ?? ''
  }

  // 登录
  const handleSubmit = async () => {
    if (!formRef.value) return

    try {
      // 表单验证
      const valid = await formRef.value.validate()
      if (!valid) return

      loading.value = true

      // 登录请求
      const { username, password } = formData

	  let loginResult = await fetchLogin({
        userName: username,
        password
      })

	  if (loginResult.require_totp) {
		if (!loginResult.temp_token) throw new Error('Login failed - no TOTP challenge token')
		const { value } = await ElMessageBox.prompt(
		  '请输入身份验证器中的 6 位动态验证码，或输入备用码',
		  '两步验证',
		  {
			confirmButtonText: '验证',
			cancelButtonText: '取消',
			inputPattern: /^(\d{6}|[A-Za-z2-9]{4}-?[A-Za-z2-9]{4})$/,
			inputErrorMessage: '请输入 6 位动态验证码或 8 位备用码'
		  }
		)
		const factor = value.trim()
		loginResult = await fetchTOTPLogin({
		  temp_token: loginResult.temp_token,
		  ...( /^\d{6}$/.test(factor) ? { code: factor } : { backup_code: factor } )
		})
	  }

	  const { token, refreshToken } = loginResult

      // 验证token
      if (!token) {
        throw new Error('Login failed - no token received')
      }

      // 存储 token 和登录状态
	  userStore.setToken(token, refreshToken || '')
      userStore.setLoginStatus(true)

      // 登录成功处理
      showLoginSuccessNotice()

      // 获取 redirect 参数，如果存在则跳转到指定页面，否则跳转到首页。
      // 只允许站内相对路径，杜绝 //host、外部协议等畸形/钓鱼落点。
      const redirect = route.query.redirect as string
      const isSafeRedirect = typeof redirect === 'string' && redirect.startsWith('/') && !redirect.startsWith('//') && !redirect.includes(':')
      router.push(isSafeRedirect ? redirect : '/')
    } catch (error) {
      // 处理 HttpError
      if (error instanceof HttpError) {
        // console.log(error.code)
      } else {
        // 处理非 HttpError
        // ElMessage.error('登录失败，请稍后重试')
        console.error('[Login] Unexpected error:', error)
      }
    } finally {
      loading.value = false
    }
  }

  // 登录成功提示
  const showLoginSuccessNotice = () => {
    setTimeout(() => {
      ElNotification({
        title: t('login.success.title'),
        type: 'success',
        duration: 2500,
        zIndex: 10000,
        message: `${t('login.success.message')}, ${systemName}!`
      })
    }, 1000)
  }
</script>

<style scoped>
  @import './style.css';
</style>

<style lang="scss" scoped>
  :deep(.el-select__wrapper) {
    height: 40px !important;
  }
</style>

<style lang="scss">
  // 参考安全运营平台的深浅分屏：左侧 HUD，右侧明亮登录卡片。
  .login-page {
    background: #f3f8fa;

    .auth-stage {
      min-width: 0;
      background:
        radial-gradient(520px 380px at 58% 50%, rgb(74 172 191 / 9%), transparent 72%),
        #f3f8fa;
    }

    // 输入框
    .el-input__wrapper,
    .el-select__wrapper {
      background-color: #fff !important;
      border-radius: 9px;
      box-shadow: 0 0 0 1px #c8dce3 inset !important;
      transition: box-shadow 0.25s;
    }

    .el-input__wrapper.is-focus,
    .el-select__wrapper.is-focused {
      box-shadow:
        0 0 0 1px #13889d inset,
        0 0 0 4px rgb(19 136 157 / 9%) !important;
    }

    .el-input__inner,
    .el-select__placeholder,
    .el-select__selected-item {
      color: #0b2b3d !important;
      caret-color: #13889d;
    }

    .el-input__inner::placeholder {
      color: #8ba4af;
    }

    // 复选框
    .el-checkbox__label {
      color: #58717d;
    }

    // 登录按钮（青色渐变发光）
    .el-button--primary {
      color: #fff;
      font-weight: 600;
      letter-spacing: 2px;
      background: #0e8197;
      border: none;
      box-shadow: 0 8px 18px rgb(14 129 151 / 20%);

      &:hover,
      &:focus {
        color: #fff;
        background: #0a6e82;
        box-shadow: 0 10px 24px rgb(14 129 151 / 28%);
      }
    }

    // SSO 登录按钮
    .el-button:not(.el-button--primary) {
      color: #235263;
      background: #f8fbfc;
      border: 1px solid #cbdde3;
    }

    .el-divider {
      border-color: #dce7eb;

      .el-divider__text {
        color: #78909b;
        background: #fff;
      }
    }
  }
</style>
