<template>
  <v-row dense>
    <!-- Country/Dial Code -->
    <v-col cols="4">
      <v-select
        v-model="localDialCode"
        :items="countryOptions"
        item-title="display"
        item-value="label"
        density="comfortable"
        :rules="[dialCodeRequired]"
        hide-details="auto"
        placeholder="Select Country"
        z-index="100000000"
        :menu-props="{
          maxHeight: 300,
          zIndex: 3000
        }"
        no-data-text="No countries available"
      >
        <template #selection="{ item }">
          <span class="text-body-2">{{ item.raw.dialCode }}</span>
        </template>
        <template #item="{ item }">
          <v-list-item-title>
            {{ item.raw.display }}
          </v-list-item-title>
        </template>
      </v-select>
    </v-col>

    <!-- Phone Number -->
    <v-col cols="8">
      <v-text-field
        v-model="localPhoneNumber"
        :placeholder="selectedCountry?.placeholder || 'Phone Number'"
        density="comfortable"
        :rules="phoneValidationRules"
        hide-details="auto"
        type="tel"
        @input="handlePhoneInput"
      />
    </v-col>
  </v-row>
</template>

<script setup lang="ts">
const props = defineProps({
  dialCode: {
    type: String,
    default: "+65",
  },
  phoneNumber: {
    type: String,
    default: "",
  },
  required: {
    type: Boolean,
    default: true,
  },
});

const emit = defineEmits([
  "update:dialCode",
  "update:phoneNumber",
  "update:isValid",
]);

const { countries, getCountryByDialCode, formatPhoneNumber } =
  usePhoneCountries();

const initialCountry = countries.find(
  (country) => country.dialCode === props.dialCode
);
const localDialCode = ref(initialCountry?.label || props.dialCode);
const localPhoneNumber = ref(props.phoneNumber);

const countryOptions = computed(() => {
  return countries.map((country) => ({
    ...country,
    display: `${country.country} (${country.dialCode})`,
  }));
});

const selectedCountry = computed(() => {
  const selected = countries.find(
    (country) => country.label === localDialCode.value
  );
  return selected;
});

const dialCodeRequired = (v: string) => {
  if (!props.required) return true;
  return !!v || "Country code is required";
};

const phoneRequired = (v: string) => {
  if (!props.required) return true;
  return !!v || "Phone number is required";
};

const phoneDigitsOnly = (v: string) => {
  if (!v) return props.required ? "Phone number is required" : true;
  return (
    /^\d+$/.test(v.replace(/\s|-|\(|\)/g, "")) || "Only numbers are allowed"
  );
};

const phoneValidLength = (v: string) => {
  if (!v || !selectedCountry.value) return true;

  const cleanNumber = v.replace(/\s|-|\(|\)/g, "");
  const { minLength, maxLength } = selectedCountry.value;

  if (cleanNumber.length < minLength) {
    return `Phone number must be at least ${minLength} digits`;
  }
  if (cleanNumber.length > maxLength) {
    return `Phone number must not exceed ${maxLength} digits`;
  }
  return true;
};

const phoneCountryFormat = (v: string) => {
  if (!v || !selectedCountry.value?.format) return true;

  const cleanNumber = v.replace(/\s|-|\(|\)/g, "");
  return (
    selectedCountry.value.format.test(cleanNumber) ||
    `Invalid ${selectedCountry.value.country} phone number format`
  );
};

const phoneValidationRules = computed(() => [
  phoneRequired,
  phoneDigitsOnly,
  phoneValidLength,
  phoneCountryFormat,
]);

const handlePhoneInput = (event: Event) => {
  const target = event.target as HTMLInputElement;
  const actualDialCode = selectedCountry.value?.dialCode || localDialCode.value;
  const formatted = formatPhoneNumber(target.value, actualDialCode);
  localPhoneNumber.value = formatted;
};

const isValid = computed(() => {
  if (!props.required && !localPhoneNumber.value) return true;

  return phoneValidationRules.value.every(
    (rule) => rule(localPhoneNumber.value) === true
  );
});

watch(localDialCode, (val) => {
  const actualDialCode = selectedCountry.value?.dialCode || val;
  emit("update:dialCode", actualDialCode);
});
watch(localPhoneNumber, (val) => emit("update:phoneNumber", val));
watch(isValid, (val) => emit("update:isValid", val));

watch(
  () => props.dialCode,
  (val) => {
    // Find the country with matching dialCode and set the label
    const matchingCountry = countries.find(
      (country) => country.dialCode === val
    );
    localDialCode.value = matchingCountry?.label || val;
  }
);
watch(
  () => props.phoneNumber,
  (val) => (localPhoneNumber.value = val)
);

watch(localDialCode, () => {
  if (localPhoneNumber.value) {
    const actualDialCode =
      selectedCountry.value?.dialCode || localDialCode.value;
    localPhoneNumber.value = formatPhoneNumber(
      localPhoneNumber.value,
      actualDialCode
    );
  }
});
</script>
