<script lang="ts" setup>
import { computed, ref } from 'vue'
import { RouterLink, useRouter } from 'vue-router'
import { Box } from '@/components/ui/box'
import { Button } from '@/components/ui/button'
import { CheckboxRoot, CheckboxControl, CheckboxLabel } from '@/components/ui/checkbox'
import { Input } from '@/components/ui/input'
import { AlertRoot, AlertTitle, AlertDescription } from '@/components/ui/alert'
import { PasswordInput } from '@/components/ui/password-input'
import {
  getPhoneVerificationErrorMessage,
  getRegisterErrorMessage,
  register,
  resolvePostAuthRoute,
  sendPhoneVerificationOtp,
  verifyPhoneVerificationOtp,
} from '@/modules/auth'
import { useAuthStore } from '@/stores/auth'
import { HelpdeskFab } from '@/modules/feedback'
import { sanitizeIcNumberInput, sanitizeNameInput } from '@/utils/form-input.utils'
import illustrationUrl from '@/assets/images/logo.svg'

const steps = [
  { id: 1, label: 'No. Telefon' },
  { id: 2, label: 'Sahkan OTP' },
  { id: 3, label: 'Maklumat Akaun' },
  { id: 4, label: 'Kata Laluan' },
] as const

const router = useRouter()
const authStore = useAuthStore()

const currentStep = ref(1)
const phoneNumber = ref('')
const otp = ref('')
const phoneVerificationToken = ref('')
const name = ref('')
const email = ref('')
const icNumber = ref('')
const password = ref('')
const passwordConfirmation = ref('')
const termsAccepted = ref(false)
const loading = ref(false)
const errorMessage = ref('')
const successMessage = ref('')

const stepTitle = computed(() => {
  switch (currentStep.value) {
    case 1:
      return 'Sahkan Nombor Telefon'
    case 2:
      return 'Masukkan Kod OTP'
    case 3:
      return 'Maklumat Akaun'
    default:
      return 'Tetapkan Kata Laluan'
  }
})

const stepDescription = computed(() => {
  switch (currentStep.value) {
    case 1:
      return 'Masukkan nombor telefon anda untuk menerima kod OTP melalui SMS.'
    case 2:
      return 'Masukkan kod OTP 6 digit yang telah dihantar ke nombor telefon anda.'
    case 3:
      return 'Lengkapkan maklumat asas akaun anda.'
    default:
      return 'Tetapkan kata laluan dan bersetuju dengan terma pendaftaran.'
  }
})

const primaryActionLabel = computed(() => {
  if (loading.value) {
    switch (currentStep.value) {
      case 1:
        return 'Menghantar OTP...'
      case 2:
        return 'Mengesahkan OTP...'
      case 3:
        return 'Seterusnya'
      default:
        return 'Mendaftar...'
    }
  }

  switch (currentStep.value) {
    case 1:
      return 'Hantar OTP'
    case 2:
      return 'Sahkan OTP'
    case 3:
      return 'Seterusnya'
    default:
      return 'Daftar'
  }
})

const inputClass = 'box block min-w-full px-4 py-4 xl:min-w-md'

const handleNameInput = () => {
  name.value = sanitizeNameInput(name.value)
}

const handleIcNumberInput = () => {
  icNumber.value = sanitizeIcNumberInput(icNumber.value)
}

const handlePhoneInput = () => {
  phoneNumber.value = phoneNumber.value.replace(/[^\d+]/g, '')
  phoneVerificationToken.value = ''
}

const handleOtpInput = () => {
  otp.value = otp.value.replace(/\D/g, '').slice(0, 6)
}

const clearMessages = () => {
  errorMessage.value = ''
  successMessage.value = ''
}

const handleSendOtp = async () => {
  clearMessages()
  loading.value = true

  try {
    const response = await sendPhoneVerificationOtp({
      phone_number: phoneNumber.value,
    })

    successMessage.value = response.message
    currentStep.value = 2
  } catch (error) {
    errorMessage.value = getPhoneVerificationErrorMessage(error)
  } finally {
    loading.value = false
  }
}

const handleVerifyOtp = async () => {
  clearMessages()
  loading.value = true

  try {
    const response = await verifyPhoneVerificationOtp({
      phone_number: phoneNumber.value,
      otp: otp.value,
    })

    phoneNumber.value = response.data.phone_number
    phoneVerificationToken.value = response.data.verification_token
    successMessage.value = response.message
    currentStep.value = 3
  } catch (error) {
    errorMessage.value = getPhoneVerificationErrorMessage(error)
  } finally {
    loading.value = false
  }
}

const validateAccountStep = (): boolean => {
  clearMessages()

  if (!name.value.trim()) {
    errorMessage.value = 'Nama penuh diperlukan.'
    return false
  }

  if (!email.value.trim()) {
    errorMessage.value = 'Emel diperlukan.'
    return false
  }

  if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email.value)) {
    errorMessage.value = 'Emel tidak sah.'
    return false
  }

  if (!icNumber.value.trim()) {
    errorMessage.value = 'No. kad pengenalan diperlukan.'
    return false
  }

  return true
}

const handleRegister = async () => {
  if (!password.value || !passwordConfirmation.value) {
    errorMessage.value = 'Kata laluan diperlukan.'
    return
  }

  if (password.value !== passwordConfirmation.value) {
    errorMessage.value = 'Pengesahan kata laluan tidak sepadan.'
    return
  }

  if (!termsAccepted.value) {
    errorMessage.value = 'Sila bersetuju dengan Dasar Privasi dan Terma dan Syarat.'
    return
  }

  clearMessages()
  loading.value = true

  try {
    const response = await register({
      name: name.value,
      email: email.value,
      ic_number: icNumber.value,
      phone_number: phoneNumber.value,
      phone_verification_token: phoneVerificationToken.value,
      password: password.value,
      password_confirmation: passwordConfirmation.value,
    })

    authStore.setSession(
      response.data.user,
      response.active_role ?? null,
      response.can_switch_role ?? false,
    )
    await router.push(resolvePostAuthRoute(response.data.user, response.redirect_path))
  } catch (error) {
    errorMessage.value = getRegisterErrorMessage(error)
  } finally {
    loading.value = false
  }
}

const handlePrimaryAction = async () => {
  if (currentStep.value === 1) {
    await handleSendOtp()
    return
  }

  if (currentStep.value === 2) {
    await handleVerifyOtp()
    return
  }

  if (currentStep.value === 3) {
    if (!validateAccountStep()) {
      return
    }

    currentStep.value = 4
    return
  }

  await handleRegister()
}

const goPrevious = () => {
  clearMessages()

  if (currentStep.value > 1) {
    currentStep.value -= 1
  }
}

const stepButtonClass = (stepId: number) => {
  if (stepId === currentStep.value) {
    return 'size-10 rounded-full shadow-none'
  }

  if (stepId < currentStep.value) {
    return 'size-10 rounded-full shadow-none bg-primary text-primary-foreground'
  }

  return 'bg-background border border-foreground/15 shadow-none size-10 rounded-full'
}

const stepLabelClass = (stepId: number) => {
  return stepId === currentStep.value
    ? 'mt-2 text-xs font-medium text-primary'
    : 'mt-2 text-xs opacity-70'
}
</script>

<template>
  <div :class="[
    'relative min-h-dvh bg-primary bg-noise xl:h-screen xl:overflow-hidden xl:bg-background xl:bg-none',
    'before:hidden before:xl:block before:content-[\'\'] before:w-[57%] before:mt-[-28%] before:mb-[-16%] before:ml-[-12%] before:absolute before:inset-y-0 before:left-0 before:transform before:rotate-6 before:bg-primary/95 before:bg-noise before:rounded-[35%]',
    'after:hidden after:xl:block after:content-[\'\'] after:w-[57%] after:mt-[-28%] after:mb-[-16%] after:ml-[-12%] after:absolute after:inset-y-0 after:left-0 after:transform after:rotate-6 after:border after:bg-accent after:bg-cover after:blur-xl after:rounded-[35%] after:border-primary',
  ]">
    <HelpdeskFab />
    <div :class="[
      'relative p-3 sm:px-8',
      'before:hidden before:xl:block before:w-[57%] before:mt-[-20%] before:mb-[-13%] before:ml-[-12%] before:absolute before:inset-y-0 before:left-0 before:transform before:-rotate-6 before:bg-primary/40 before:bg-noise before:border before:border-primary/50 before:opacity-60 before:rounded-[20%]',
    ]">
      <div class="container relative z-10 mx-auto sm:px-20">
        <div class="block xl:grid xl:grid-cols-2 xl:gap-4">
          <div class="hidden min-h-screen flex-col xl:flex">
            <div class="my-auto">
              <img class="-mt-16 w-1/2" :src="illustrationUrl" alt="logo-RAJD" />
              <div class="mt-10 text-4xl font-medium leading-tight text-white">
                Selamat Datang
              </div>
              <div class="mt-5 text-lg text-white opacity-60">
                Sistem Informasi Koperasi Online (MyKOPKB) 1.0
              </div>
            </div>
          </div>

          <div class="my-6 py-4 xl:my-0 xl:flex xl:min-h-screen xl:items-center xl:py-0">
            <Box raised="double"
              class="mx-auto w-full px-5 py-6 sm:w-3/4 sm:px-8 lg:w-2/4 xl:ml-24 xl:w-auto xl:p-0 xl:before:hidden xl:after:hidden xl:shadow-none xl:border-none xl:bg-none">
              <h2 class="text-center text-2xl font-semibold xl:text-left xl:text-3xl">Daftar Akaun</h2>

              <div
                class="before:bg-foreground/10 relative mt-5 flex flex-row justify-between gap-1 px-1 before:absolute before:bottom-[calc(50%-0.75rem)] before:left-[12%] before:right-[12%] before:h-0.5 before:w-auto">
                <div v-for="step in steps" :key="step.id" class="z-10 flex flex-1 flex-col items-center text-center">
                  <Button :class="stepButtonClass(step.id)" :variant="step.id === currentStep ? 'primary' : 'ghost'"
                    type="button">
                    {{ step.id }}
                  </Button>
                  <div :class="stepLabelClass(step.id)">
                    {{ step.label }}
                  </div>
                </div>
              </div>

              <div class="mt-5 border-t border-foreground/10 pt-5">
                <div class="text-center xl:text-left">
                  <div class="text-base font-medium">{{ stepTitle }}</div>
                  <div class="mt-1 text-sm opacity-70">{{ stepDescription }}</div>
                </div>

                <AlertRoot v-if="errorMessage" class="mt-4 py-3" variant="danger">
                  <AlertTitle>Ralat</AlertTitle>
                  <AlertDescription>{{ errorMessage }}</AlertDescription>
                </AlertRoot>

                <AlertRoot v-if="successMessage" class="mt-4 py-3" variant="success">
                  <AlertTitle>Berjaya</AlertTitle>
                  <AlertDescription>{{ successMessage }}</AlertDescription>
                </AlertRoot>

                <form class="mt-4 flex flex-col gap-5" @submit.prevent="handlePrimaryAction">
                  <div class="flex flex-col gap-3">
                    <template v-if="currentStep === 1">
                      <Input v-model="phoneNumber" :class="inputClass" type="tel" inputmode="tel"
                        placeholder="No. Telefon, contoh: 0123456790" autocomplete="tel" required
                        @input="handlePhoneInput" />
                    </template>

                    <template v-else-if="currentStep === 2">
                      <Input v-model="otp" :class="`${inputClass} text-center tracking-[0.4em]`" type="text"
                        inputmode="numeric" maxlength="6" placeholder="000000" autocomplete="one-time-code" required
                        @input="handleOtpInput" />
                      <Button class="box w-full px-4 py-4" look="outline" type="button" :disabled="loading"
                        @click="handleSendOtp">
                        Hantar Semula OTP
                      </Button>
                    </template>

                    <template v-else-if="currentStep === 3">
                      <div class="rounded-lg border border-foreground/10 bg-foreground/5 px-4 py-3 text-sm">
                        <span class="opacity-70">Telefon disahkan:</span>
                        <span class="ml-1 font-medium">{{ phoneNumber }}</span>
                      </div>
                      <Input v-model="name" :class="inputClass" type="text" placeholder="Nama Penuh" autocomplete="name"
                        required @input="handleNameInput" />
                      <Input v-model="email" :class="inputClass" type="email" placeholder="Email" autocomplete="email"
                        required />
                      <Input v-model="icNumber" :class="inputClass" type="text" inputmode="numeric" maxlength="15"
                        placeholder="No. Kad Pengenalan, contoh: 900101011234" required @input="handleIcNumberInput" />
                    </template>

                    <template v-else>
                      <PasswordInput v-model="password" :class="inputClass" placeholder="Kata Laluan"
                        autocomplete="new-password" minlength="8" required />
                      <PasswordInput v-model="passwordConfirmation" :class="inputClass" placeholder="Sahkan Kata Laluan"
                        autocomplete="new-password" minlength="8" required />

                      <div class="flex text-xs sm:text-sm">
                        <CheckboxRoot :checked="termsAccepted"
                          @checked-change="({ checked }) => (termsAccepted = checked === true)">
                          <CheckboxControl />
                          <CheckboxLabel>
                            Dengan mendaftar, anda bersetuju dengan
                            <RouterLink class="text-primary ml-1" to="/privacy-policy">
                              Dasar Privasi
                            </RouterLink>
                            &amp;
                            <RouterLink class="text-primary ml-1" to="/terms">
                              Terma dan Syarat
                            </RouterLink>
                            .
                          </CheckboxLabel>
                        </CheckboxRoot>
                      </div>
                    </template>
                  </div>

                  <div class="space-y-3">
                    <div class="flex gap-3">
                      <Button v-if="currentStep > 1" class="box w-full px-4 py-4" look="outline" type="button"
                        :disabled="loading" @click="goPrevious">
                        Sebelum
                      </Button>
                      <Button class="box w-full px-4 py-4" variant="primary" type="submit"
                        :disabled="loading || (currentStep === 4 && !termsAccepted)">
                        {{ primaryActionLabel }}
                      </Button>
                    </div>
                    <button type="button" class="w-full text-sm opacity-70 hover:opacity-100"
                      @click="router.push({ name: 'login' })">
                      Sudah mempunyai akaun? Log masuk
                    </button>
                  </div>
                </form>
              </div>
            </Box>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>
