<script setup lang="ts">
import { toTypedSchema } from "@vee-validate/zod";
import PhoneInput from "base-vue-phone-input";
import type { Results } from "base-vue-phone-input";
import { useFocus, useThrottleFn } from "@vueuse/core";
import { ChevronsUpDown } from "lucide-vue-next";
import { useForm } from "vee-validate";
import * as z from "zod";
import type { Country, Service } from "~/types/Contact";

const { t } = useI18n();
const localePath = useLocalePath();
const { getUTMPayload } = useUtmPayload();

interface Props {
  isCampaign?: boolean;
  services: Service[];
}

const { isCampaign = false } = defineProps<Props>();
const phoneInput = ref(null);
const { focused } = useFocus(phoneInput);
const open = ref(false);
const phoneResult = ref<Results | null>();
const successMessage = ref("");
const errorMessage = ref("");
const loading = ref(false);

const formSubmitted = useState("form-submitted", () => false);
const formSchema = computed(() => createFormSchema(t));
function onPhoneUpdate(res: Results) {
  phoneResult.value = res;
}
function createFormSchema(t: (key: string) => string) {
  return toTypedSchema(
    z.object({
      full_name: z
        .string({ required_error: t("schemaErrors.required_field_error") })
        .min(3, t("schemaErrors.min")),
      email: z
        .string({ required_error: t("schemaErrors.email_required_error") })
        .email(t("schemaErrors.email_invalid_error")),
      phone: z
        .string({ required_error: t("schemaErrors.required_field_error") })
        .min(1, t("schemaErrors.required_field_error"))
        .refine(
          () => phoneResult.value?.isValid === true,
          t("schemaErrors.phone_invalid_error"),
        ),
      service_id: z
        .number({ required_error: t("schemaErrors.required_field_error") })
        .min(1, t("schemaErrors.min_service")),
      description: z.string().optional(),
    }),
  );
}

const { handleSubmit, resetForm } = useForm({
  validationSchema: formSchema,
  validateOnMount: false,
});

const throttledSubmit = useThrottleFn(
  handleSubmit(async (values) => {
    const { post } = useApi();
    if (phoneResult.value?.isValid === false) {
      return;
    }

    try {
      loading.value = true;
      errorMessage.value = "";
      successMessage.value = "";

      const payload = {
        full_name: values.full_name,
        email: values.email,
        phone: phoneResult.value?.formatInternational,
        country_code: phoneResult.value?.countryCode,
        service_id: values.service_id,
        description: values.description,

        utm: getUTMPayload(),
      };

      await post("contact_us", payload);

      successMessage.value = t("success_message");
      resetForm();
      formSubmitted.value = true;
      await navigateTo(localePath("/thank-you"));
    } catch (err: unknown) {
      console.error("Contact form submission error:", err);

      const maybeAxiosErr = err as {
        response?: { data?: { message?: unknown } };
      };
      const message =
        typeof maybeAxiosErr?.response?.data?.message === "string"
          ? (maybeAxiosErr.response!.data!.message as string)
          : t("error_message");

      errorMessage.value = message;

      setTimeout(() => {
        errorMessage.value = "";
      }, 3000);
    } finally {
      loading.value = false;
    }
  }),
  5000,
);
</script>

<template>
  <form class="mx-auto w-full space-y-3" @submit.prevent="throttledSubmit">
    <!-- First Row -->
    <div class="grid grid-cols-1 gap-4 md:grid-cols-2">
      <FormField
        v-slot="{ componentField }"
        name="full_name"
        :validate-on-blur="true"
        :validate-on-input="false"
      >
        <FormItem>
          <FormLabel class="text-primary capitalize">{{
            $t("labels.full_name_label")
          }}</FormLabel>
          <FormControl>
            <Input
              class="!bg-background border-input-border focus-visible:border-input-border h-[40px] rounded-sm border p-3 placeholder:text-[12px] focus-visible:ring-0"
              v-bind="componentField"
              :placeholder="$t('placeholders.name')"
            />
          </FormControl>
          <div class="text-destructive min-h-[20px] !text-sm">
            <FormMessage />
          </div>
        </FormItem>
      </FormField>

      <FormField v-slot="{ componentField }" name="phone">
        <FormItem>
          <FormLabel class="text-primary capitalize">
            {{ $t("labels.phone_label") }}
          </FormLabel>
          <ClientOnly>
            <PhoneInput
              noUseBrowserLocale
              fetchCountry
              :country-code="'SA'"
              :country-locale="$i18n.locale"
              class="flex items-center"
              :only-countries="[
                'SA',
                'EG',
                'AE',
                'KW',
                'QA',
                'BH',
                'JO',
                'MA',
                'PS',
                'TN',
                'DZ',
                'KM',
                'DJ',
                'IQ',
                'LB',
                'LY',
                'MR',
                'OM',
                'SD',
                'SY',
                'YE',
              ]"
              @update="onPhoneUpdate"
            >
              <template #selector="{ inputValue, updateInputValue, countries }">
                <Popover>
                  <PopoverTrigger>
                    <Button
                      type="button"
                      class="!bg-background border-input-border focus-visible:border-input-border border-e-none h-[40px] rounded-sm rounded-e-none border p-3 placeholder:text-[12px] focus-visible:ring-0"
                    >
                      <ContactFlagComponent :country="inputValue" />
                      <ChevronsUpDown
                        class="text-foreground h-4 w-4 opacity-50"
                      />
                    </Button>
                  </PopoverTrigger>
                  <PopoverContent
                    :align="'start'"
                    class="!bg-background border-input-border ws-scrollbar w-[287px] rounded-sm p-0 sm:w-[540px] md:w-[325px] lg:w-[455px] xl:w-[270px] 2xl:w-[335px]"
                  >
                    <Command :dir="$i18n.locale === 'ar' ? 'rtl' : 'ltr'">
                      <CommandInput :placeholder="$t('placeholders.country')" />
                      <CommandEmpty>{{
                        $t("placeholders.noResult")
                      }}</CommandEmpty>
                      <CommandList>
                        <CommandGroup>
                          <CommandItem
                            v-for="option in countries"
                            :key="option.iso2"
                            :value="option.iso2"
                            class="gap-2"
                            @select="
                              () => {
                                updateInputValue(option.iso2);
                                open = false;
                                focused = true;
                              }
                            "
                          >
                            <ContactFlagComponent :country="option?.iso2" />
                            <span class="flex-1 text-sm">{{
                              option.name
                            }}</span>
                            <span class="text-foreground/50 text-sm">{{
                              option.dialCode
                            }}</span>
                          </CommandItem>
                        </CommandGroup>
                      </CommandList>
                    </Command>
                  </PopoverContent>
                </Popover>
              </template>

              <!-- Phone number input slot -->
              <template #input="{ inputValue, updateInputValue, placeholder }">
                <FormControl>
                  <Input
                    ref="phoneInput"
                    class="!bg-background border-input-border focus-visible:border-input-border border-s-none h-[40px] rounded-sm rounded-s-none border p-3 placeholder:text-[12px] focus-visible:ring-0"
                    type="text"
                    v-bind="componentField"
                    :model-value="inputValue"
                    :placeholder="placeholder"
                    style="unicode-bidi: plaintext"
                    @input="updateInputValue"
                  />
                </FormControl>
              </template>
            </PhoneInput>
          </ClientOnly>
          <div class="text-destructive min-h-[20px] !text-sm">
            <FormMessage />
          </div>
        </FormItem>
      </FormField>
    </div>

    <!-- Second Row -->
    <div class="grid grid-cols-1 gap-4 md:grid-cols-2">
      <FormField
        v-slot="{ componentField }"
        name="email"
        :validate-on-blur="true"
        :validate-on-input="false"
      >
        <FormItem>
          <FormLabel class="text-primary capitalize">{{
            $t("labels.email_label")
          }}</FormLabel>
          <FormControl>
            <Input
              class="!bg-background border-input-border focus-visible:border-input-border h-[40px] rounded-sm border p-3 placeholder:text-[12px] focus-visible:ring-0"
              v-bind="componentField"
              placeholder="email@example.com"
            />
          </FormControl>
          <div class="text-destructive min-h-[20px] !text-sm">
            <FormMessage />
          </div>
        </FormItem>
      </FormField>
      <FormField
        v-slot="{ componentField }"
        name="service_id"
        :validate-on-blur="true"
        :validate-on-input="false"
      >
        <FormItem>
          <FormLabel class="text-primary capitalize">{{
            $t("labels.service_label")
          }}</FormLabel>
          <Select v-bind="componentField">
            <FormControl>
              <SelectTrigger
                :aria-label="$t('ariaLabels.services')"
                class="!bg-background border-input-border focus-visible:border-input-border !h-[40px] w-full rounded-sm border p-3 shadow-none focus-visible:ring-0 ltr:text-left rtl:flex-row-reverse rtl:text-right"
              >
                <SelectValue
                  class="placeholder:text-[12px]"
                  :placeholder="$t('placeholders.service')"
                />
              </SelectTrigger>
            </FormControl>
            <SelectContent
              class="!bg-background border-input-border rounded-sm"
            >
              <SelectItem
                v-for="service in services"
                :key="service.id"
                :value="service.id"
                >{{ service.title }}
              </SelectItem>
            </SelectContent>
          </Select>
          <div class="text-destructive min-h-[20px] !text-sm">
            <FormMessage />
          </div>
        </FormItem>
      </FormField>
    </div>

    <!-- Description -->
    <FormField v-slot="{ componentField }" name="description">
      <FormItem>
        <FormLabel class="text-primary capitalize"
          >{{ $t("labels.project_description_label") }}
        </FormLabel>
        <FormControl>
          <Textarea
            class="!bg-background border-input-border focus-visible:border-input-border h-[78px] resize-none rounded-sm border p-3 placeholder:text-[12px] focus-visible:ring-0"
            v-bind="componentField"
            :placeholder="$t('placeholders.project_description')"
          />
        </FormControl>
        <div class="text-destructive min-h-[20px] !text-sm">
          <FormMessage />
        </div>
      </FormItem>
    </FormField>

    <!-- Submit Button -->
    <Button
      v-if="isCampaign"
      type="submit"
      variant="wsDefault"
      :class="loading ? 'cursor-not-allowed opacity-50' : 'cursor-pointer'"
      class="h-[48px] w-full !text-black dark:!text-white"
    >
      <span v-if="loading" class="flex items-center gap-2">
        <span>{{ $t("buttons.loading_send_button") }}</span>
        <span class="animate-spin-loader" />
      </span>

      <span v-else>
        {{ $t("buttons.send_button2") }}
      </span>
    </Button>

    <Button
      v-else
      type="submit"
      :class="loading ? 'cursor-not-allowed opacity-50' : 'cursor-pointer'"
      class="ws-gradient-border text-foreground h-[48px] w-full"
    >
      <span v-if="loading" class="flex items-center gap-2">
        <span>{{ $t("buttons.loading_send_button") }}</span>
        <span class="animate-spin-loader" />
      </span>

      <span v-else>
        {{ $t("buttons.send_button") }}
      </span>
    </Button>
    <div v-if="errorMessage" class="text-center text-red-500">
      {{ errorMessage }}
    </div>
  </form>
</template>
