<script setup lang="ts">
import type { FormError, FormSubmitEvent } from '@nuxt/ui'
import { DEFAULT_AUTHENTICATED_LANDING_PATH, normalizeSafeRedirect } from '../../utils/auth-routes'
import { useAuthSession } from '../../composables/useAuthSession'

definePageMeta({
  title: '登录',
  layout: 'blank',
})

type LoginFormState = {
  username: string
  password: string
  captchaAnswer: string
}

type LoginResult = {
  user: {
    id: number
    username: string
  }
}

const USERNAME_REGEX = /^[a-zA-Z0-9_]{3,20}$/

const state = reactive<LoginFormState>({
  username: '',
  password: '',
  captchaAnswer: '',
})

const captchaIdRef = ref('')
const captchaImageSrc = ref('')

async function refreshCaptcha() {
  state.captchaAnswer = ''
  captchaImageSrc.value = ''
  const res = await fetchData<{ captchaId: string; imageSvg: string }>('/api/auth/captcha', {
    method: 'GET',
    notify: false,
  })
  captchaIdRef.value = res.captchaId
  captchaImageSrc.value = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(res.imageSvg)}`
}

onMounted(() => {
  void refreshCaptcha()
})

const loading = ref(false)
const resultType = ref<'success' | 'error' | ''>('')
const resultMessage = ref('')
const route = useRoute()
const { refresh } = useAuthSession()
const { allowRegister } = useGlobalConfig()
const { fetchData, getApiErrorMessage } = useClientApi()

const validate = (formState: LoginFormState): FormError[] => {
  const errors: FormError[] = []

  if (!formState.username) {
    errors.push({ name: 'username', message: '请输入用户名' })
  } else if (!USERNAME_REGEX.test(formState.username)) {
    errors.push({ name: 'username', message: '用户名需为 3-20 位字母、数字或下划线' })
  }

  if (!formState.password) {
    errors.push({ name: 'password', message: '请输入密码' })
  } else if (formState.password.length < 6) {
    errors.push({ name: 'password', message: '密码至少 6 位' })
  }

  if (!formState.captchaAnswer?.trim()) {
    errors.push({ name: 'captchaAnswer', message: '请输入验证码' })
  }

  return errors
}

const onSubmit = async (_event: FormSubmitEvent<LoginFormState>) => {
  resultType.value = ''
  resultMessage.value = ''
  loading.value = true

  try {
    const res = await fetchData<LoginResult>('/api/auth/login', {
      method: 'POST',
      body: {
        username: state.username,
        password: state.password,
        captchaId: captchaIdRef.value,
        captchaAnswer: state.captchaAnswer,
      },
      notify: false,
    })

    await refresh(true)

    resultType.value = 'success'
    resultMessage.value = `登录成功，欢迎 ${res.user.username}`
    const redirectCandidate = Array.isArray(route.query.redirect)
      ? route.query.redirect[0]
      : route.query.redirect
    const redirectTarget = normalizeSafeRedirect(redirectCandidate, DEFAULT_AUTHENTICATED_LANDING_PATH)
    await navigateTo(redirectTarget)
  } catch (error: unknown) {
    resultType.value = 'error'
    resultMessage.value = getApiErrorMessage(error)
    try {
      await refreshCaptcha()
    } catch {
      /* ignore captcha refresh errors */
    }
  } finally {
    loading.value = false
  }
}
</script>

<template>
  <div class="min-h-screen flex items-start justify-center px-4 pt-14 pb-8 md:pt-20">
    <div class="w-full max-w-md space-y-4">
      <div class="text-center space-y-1">
        <NuxtLink to="/" class="inline-flex items-center gap-2 text-sm text-muted hover:text-primary transition-colors">
          <UIcon name="i-lucide-arrow-left" class="size-4" />
          返回首页
        </NuxtLink>
      </div>

      <UCard class="shadow-lg">
      <template #header>
        <div class="space-y-1 text-center">
          <h1 class="text-2xl font-semibold">欢迎登录</h1>
          <p class="text-sm text-muted">请输入用户名和密码继续使用</p>
          <p class="text-xs text-muted">
            若尚未开通账号，请联系管理员。
          </p>
        </div>
      </template>

      <UForm :state="state" :validate="validate" class="space-y-4" @submit="onSubmit">
        <UFormField label="用户名" name="username" required>
          <UInput
            v-model="state.username"
            placeholder="请输入用户名"
            autocomplete="username"
            class="w-full"
          />
        </UFormField>

        <UFormField label="密码" name="password" required>
          <UInput
            v-model="state.password"
            type="password"
            placeholder="请输入密码"
            autocomplete="current-password"
            class="w-full"
          />
        </UFormField>

        <UFormField label="验证码" name="captchaAnswer" required>
          <div class="flex flex-wrap gap-2 items-center">
            <img
              v-if="captchaImageSrc"
              :src="captchaImageSrc"
              alt="验证码"
              class="h-10 rounded border border-default bg-elevated shrink-0"
            />
            <UInput
              v-model="state.captchaAnswer"
              placeholder="请输入图中字符"
              class="flex-1 min-w-[8rem]"
              autocomplete="off"
            />
            <UButton type="button" color="neutral" variant="outline" class="shrink-0" @click="refreshCaptcha">
              换一张
            </UButton>
          </div>
        </UFormField>

        <UButton type="submit" block :loading="loading">
          立即登录
        </UButton>
      </UForm>

      <UAlert
        v-if="resultType"
        :color="resultType === 'success' ? 'success' : 'error'"
        :title="resultType === 'success' ? '操作成功' : '操作失败'"
        :description="resultMessage"
        class="mt-4"
      />

      <div v-if="allowRegister" class="mt-4 flex items-center justify-center text-sm">
        <NuxtLink to="/register" class="text-primary hover:underline">
          没有账号？去注册
        </NuxtLink>
      </div>
    </UCard>
    </div>
  </div>
</template>