<script lang='ts' setup>
import type { GenericObject } from "vee-validate";
import type { PhoneNumberVerifyClient } from "@/api/types";
import type { PhoneCountry } from "@/auth/type";
import { toastController } from "@ionic/vue";
import { toTypedSchema } from "@vee-validate/yup";
import { chevronDown } from "ionicons/icons";
import { Field, Form } from "vee-validate";
import * as yup from "yup";
import { authClient, countries } from "@/auth";
import Country from "./country.vue";

const emit = defineEmits<{
  (e: "submit", value: PhoneNumberVerifyClient): void;
}>();

const { t } = useI18n();

const countdown = ref(0);
const isSending = ref(false);
const canResend = computed(() => countdown.value === 0 && !isSending.value);

const phoneNumber = ref("");
const phoneNumberError = ref("");
const modalInst = useTemplateRef<ModalInstance>("modalInst");
const countryCode = ref<string>(countries[0].code);
const currentCountry = computed<PhoneCountry>(() => {
  return countries.find(c => c.code === countryCode.value) || countries[0];
});
let timer: number | null = null;

function dismiss() {
  modalInst.value?.$el.dismiss();
}
function handleChangeCountry() {
  dismiss();
  phoneNumber.value = "";
  phoneNumberError.value = "";
}

function validatePhoneNumber(phone: string): boolean {
  return currentCountry.value.pattern.test(phone);
}

const schema = computed(() => toTypedSchema(yup.object({
  phoneNumber: yup
    .string()
    .required(t("auth.login.validation.phoneNumberRequired"))
    .test(
      "phone-format",
      t("auth.login.validation.phoneNumberInvalid"),
      value => !value || validatePhoneNumber(value),
    ),
  code: yup
    .string()
    .required(t("auth.login.validation.codeRequired"))
    .matches(/^\d{6}$/, t("auth.login.validation.codeInvalid")),
})));

function startCountdown() {
  countdown.value = 60;
  timer = setInterval(() => {
    countdown.value--;
    if (countdown.value <= 0) {
      if (timer) {
        clearInterval(timer);
        timer = null;
      }
    }
  }, 1000);
}

async function sendOtp() {
  const phone = phoneNumber.value.trim();
  if (!phone) {
    phoneNumberError.value = t("auth.login.validation.phoneNumberRequired");
    return;
  }

  if (!validatePhoneNumber(phone)) {
    phoneNumberError.value = t("auth.login.validation.phoneNumberInvalid");
    return;
  }

  if (!canResend.value) {
    return;
  }

  try {
    phoneNumberError.value = "";
    isSending.value = true;
    await authClient.phoneNumber.sendOtp({
      phoneNumber: `${currentCountry.value.dialCode}${phone}`,
    });

    const toast = await toastController.create({
      message: t("auth.login.sendCodeSuccess"),
      duration: 2000,
      position: "top",
      color: "success",
    });
    await toast.present();
    startCountdown();
  }
  catch (error: any) {
    const toast = await toastController.create({
      message: error?.message || t("auth.common.failedSendCode"),
      duration: 2000,
      position: "top",
      color: "danger",
    });
    await toast.present();
  }
  finally {
    isSending.value = false;
  }
}

function handleSubmit(values: GenericObject) {
  emit("submit", {
    phoneNumber: `${currentCountry.value.dialCode}${values.phoneNumber}`,
    code: values.code,
  });
}

onUnmounted(() => {
  if (timer) {
    clearInterval(timer);
    timer = null;
  }
});
</script>

<template>
  <Form :validation-schema="schema" class="mt-5" @submit="handleSubmit">
    <Field v-slot="{ field, errors }" name="phoneNumber" type="tel">
      <div class="mb-4">
        <ui-input
          v-bind="field"
          v-model="phoneNumber"
          :placeholder="currentCountry.placeholder"
          :maxlength="currentCountry.maxLength"
          type="tel"
        >
          <ion-button
            id="open-country"
            slot="start"
            fill="clear"
            size="small"
          >
            {{ currentCountry.dialCode }}
            <ion-icon slot="end" :icon="chevronDown" class="text-sm" />
          </ion-button>

          <ion-button
            slot="end"
            fill="clear"
            size="small"
            :disabled="!canResend"
            @click="sendOtp"
          >
            <span v-if="countdown > 0">
              {{ countdown }}s
            </span>
            <span v-else-if="isSending">
              {{ t('auth.login.sending') }}
            </span>
            <span v-else>
              {{ t('auth.login.getCode') }}
            </span>
          </ion-button>
        </ui-input>
        <div v-if="errors[0] || phoneNumberError" class="text-xs text-red-500 mt-1">
          {{ errors[0] || phoneNumberError }}
        </div>
      </div>
    </Field>
    <Field v-slot="{ field, errorMessage }" name="code" type="text">
      <div class="mb-4">
        <ui-input
          v-bind="field"
          :placeholder="t('auth.login.enterCode')"
          :maxlength="6"
        />
        <div v-if="errorMessage" class="text-xs text-red-500 mt-1">
          {{ errorMessage }}
        </div>
      </div>
    </Field>

    <ion-button
      expand="block"
      class="ion-margin-top"
      shape="round"
      type="submit"
    >
      {{ t('auth.login.loginButton') }}
    </ion-button>
  </Form>

  <ion-modal ref="modalInst" trigger="open-country" :initial-breakpoint="0.95" :breakpoints="[0, 0.95]">
    <ion-content class="ion-padding">
      <Country v-model="countryCode" @update:model-value="handleChangeCountry" />
    </ion-content>
  </ion-modal>
</template>

<style lang='css' scoped>
@reference "tailwindcss";
</style>
