<template>
  <UAuthForm
    :fields="fields"
    :schema="schema"
    :providers="providers"
    :title="$t('login.title')"
    icon="i-lucide-lock"
    @submit="onSubmit($event)"
  >
    <template #footer>
      {{ $t('login.agree') }}
      <ULink
        to="/"
        class="text-primary font-medium"
      >
        {{ $t('login.terms') }}
      </ULink>.
    </template>
  </UAuthForm>
</template>

<script setup lang="ts">
import * as z from 'zod'
import type { FormSubmitEvent } from '@nuxt/ui'
import type { AuthFormField } from '@nuxt/ui/runtime/components/AuthForm.vue.js'

definePageMeta({
  layout: 'empty'
})

const { t } = useI18n()
const toast = useToast()

// The otpId is used to track the OTP request and verify the user
// null if no request was sent yet
const otpId = ref<string | null>(null)

const fields = computed(() => {
  const fields: AuthFormField[] = [{
    name: 'email',
    type: 'text',
    label: t('login.email'),
    placeholder: t('login.emailPlaceholder'),
    required: true
  }]
  if (otpId.value !== null) {
    fields.push({
      name: 'otp',
      type: 'otp',
      label: t('login.otp'),
      length: 6,
      size: 'xl'
    })
  }
  return fields
})

const { signInWithEmail, signInWithOAuth, signInWithOtp } = useUser()

const oAuthAndRedirect = async (provider: 'apple' | 'google') => {
  try {
    await signInWithOAuth(provider)
    navigateTo('/confirm')
  } catch (error) {
    toast.add({ color: 'error', description: (error as Error).message })
  }
}

const providers = [
  {
    label: 'Google',
    icon: 'i-simple-icons-google',
    onClick: () => oAuthAndRedirect('google')
  },
  {
    label: 'Apple',
    icon: 'i-simple-icons-apple',
    onClick: () => oAuthAndRedirect('apple')
  }
]

const schema = z.object({
  email: z.email(t('login.invalidEmail')),
  otp: z.array(z.string()).optional().transform(val => val?.join(''))
})

type Schema = z.output<typeof schema>

const { locale } = useI18n()
async function onSubmit(payload: FormSubmitEvent<Schema>) {
  try {
    if (otpId.value !== null && payload.data.otp?.length) {
    // If OTP is provided, sign in with OTP
      await signInWithOtp(otpId.value, payload.data.otp)
      navigateTo('/confirm')
    } else {
      // If OTP is not provided, sign in with email (send OTP)
      otpId.value = await signInWithEmail(payload.data.email, locale.value)
      toast.add({
        title: t('login.emailSent'),
        description: t('login.emailSentDescription'),
        icon: 'i-lucide-check',
        color: 'success'
      })
    }
  } catch (error) {
    toast.add({ color: 'error', description: (error as Error).message })
  }
}
</script>
