<template>
  <q-select
    v-model="selectedState"
    v-bind="$attrs"
    use-input
    hide-selected
    fill-input
    clearable
    :options="stateOptions"
    :label="label"
    :loading="loading"
    :placeholder="$t('common.actions.search') + ' ' + $t('ui.navigation.state')"
    :rules="rules"
    label-color="primary"
    @filter="filterFn"
  >
    <template #no-option>
      <q-item>
        <q-item-section class="text-grey">
          {{ $t("http.errors.no_records_found") }}
        </q-item-section>
      </q-item>
    </template>
  </q-select>
</template>

<script setup>
import { getStates } from "src/api/state";
import { ref, onMounted, watch } from "vue";
import { useI18n } from "vue-i18n";

const emit = defineEmits(["selectedCountryId"]);

const { country, label, rules, initialId } = defineProps({
  country: {
    type: Object,
    required: false,
    default: () => {
      return {
        label: "Brasil",
        value: 1,
      };
    },
  },
  label: {
    type: String,
    default: () => useI18n().t("ui.navigation.state"),
  },
  rules: {
    type: Array,
    default: () => [],
  },
  initialId: {
    type: Number,
    required: false,
    default: null,
  },
});

const selectedState = defineModel();

const loading = ref(false);
const filteredStates = ref([]);
const baseStates = ref([]);
const stateOptions = ref([]);

const filterFn = (val, update) => {
  if (!val) {
    stateOptions.value = filteredStates.value.map((state) => ({
      label: state.name,
      value: state.id,
      code: state.code,
      country_id: state.country_id,
    }));
  } else {
    const needle = val.toLowerCase();
    filteredStates.value = filteredStates.value.filter(
      (v) => v.name.toLowerCase().indexOf(needle) > -1,
    );
    stateOptions.value = filteredStates.value.map((state) => ({
      label: state.name,
      value: state.id,
      code: state.code,
      country_id: state.country_id,
    }));
  }

  update();
};

const selectStateById = async (id) => {
  if (selectedState.value?.value === id) {
    return;
  }
  selectedState.value = stateOptions.value.find((state) => state.value === id);
};

const selectStateByName = (name) => {
  if (selectedState.value?.label === name) {
    return;
  }
  selectedState.value = stateOptions.value.find(
    (state) => state.label === name,
  );
};

const selectStateByCode = (code) => {
  if (selectedState.value?.code === code) {
    return;
  }
  selectedState.value = stateOptions.value.find((state) => state.code === code);
};

watch(
  () => country,
  (value, oldValue) => {
    if (
      value?.value != oldValue?.value &&
      value?.value != selectedState.value?.country_id
    ) {
      selectedState.value = null;
    }
    if (value) {
      filteredStates.value = baseStates.value.filter(
        (state) => state.country_id === value.value,
      );
      stateOptions.value = filteredStates.value.map((state) => ({
        label: state.name,
        value: state.id,
        code: state.code,
        country_id: state.country_id,
      }));
    } else {
      filteredStates.value = baseStates.value;
      stateOptions.value = baseStates.value.map((state) => ({
        label: state.name,
        value: state.id,
        code: state.code,
        country_id: state.country_id,
      }));
    }
  },
  { immediate: true },
);

watch(selectedState, () => {
  if (selectedState.value?.country_id) {
    emit("selectedCountryId", selectedState.value.country_id);
  }
});

onMounted(async () => {
  try {
    loading.value = true;
    baseStates.value = await getStates();
    filteredStates.value = baseStates.value;
    stateOptions.value = baseStates.value.map((state) => ({
      label: state.name,
      value: state.id,
      code: state.code,
      country_id: state.country_id,
    }));
    if (initialId) {
      selectStateById(initialId);
    }
  } catch (e) {
    console.error(e);
  } finally {
    loading.value = false;
  }
});

defineExpose({
  selectStateById,
  selectStateByName,
  selectStateByCode,
});
</script>
