<script setup>
import { reactive, ref } from 'vue';
import { useI18n } from 'vue-i18n';

import FetchData from 'components/FetchData.vue';
import VnRow from 'components/ui/VnRow.vue';
import VnSelect from 'src/components/common/VnSelect.vue';
import VnSelectProvince from 'src/components/VnSelectProvince.vue';
import VnInput from 'src/components/common/VnInput.vue';
import CreateNewCityForm from './CreateNewCityForm.vue';
import VnSelectDialog from 'components/common/VnSelectDialog.vue';
import FormModelPopup from './FormModelPopup.vue';

const emit = defineEmits(['onDataSaved']);

const { t } = useI18n();

const postcodeFormData = reactive({
    code: null,
    countryFk: null,
    provinceFk: null,
    townFk: null,
});
const townsFetchDataRef = ref(false);
const townFilter = ref({});

const countriesRef = ref(false);
const provincesFetchDataRef = ref(false);
const provincesOptions = ref([]);
const townsOptions = ref([]);
const town = ref({});
const countryFilter = ref({});

function onDataSaved(formData) {
    const newPostcode = {
        ...formData,
    };
    newPostcode.town = town.value.name;
    newPostcode.townFk = town.value.id;
    const provinceObject = provincesOptions.value.find(
        ({ id }) => id === formData.provinceFk
    );
    newPostcode.province = provinceObject?.name;
    const countryObject = countriesRef.value.opts.find(
        ({ id }) => id === formData.countryFk
    );
    newPostcode.country = countryObject?.name;
    emit('onDataSaved', newPostcode);
}

async function setCountry(countryFk, data) {
    data.townFk = null;
    data.provinceFk = null;
    data.countryFk = countryFk;
    await fetchTowns();
}

// Province

async function handleProvinces(data) {
    provincesOptions.value = data;
    if (postcodeFormData.countryFk) {
        await fetchTowns();
    }
}
async function setProvince(id, data) {
    if (data.provinceFk === id) return;
    const newProvince = provincesOptions.value.find((province) => province.id == id);
    if (newProvince) data.countryFk = newProvince.countryFk;
    postcodeFormData.provinceFk = id;
    await fetchTowns();
}
async function onProvinceCreated(data) {
    await provincesFetchDataRef.value.fetch({
        where: { countryFk: postcodeFormData.countryFk },
    });
    postcodeFormData.provinceFk = data.id;
}
function provinceByCountry(countryFk = postcodeFormData.countryFk) {
    return provincesOptions.value
        .filter((province) => province.countryFk === countryFk)
        .map(({ id }) => id);
}

// Town
async function handleTowns(data) {
    townsOptions.value = data;
}
function setTown(newTown, data) {
    town.value = newTown;
    data.provinceFk = newTown?.provinceFk ?? newTown;
    data.countryFk = newTown?.province?.countryFk ?? newTown;
}
async function onCityCreated(newTown, formData) {
    await provincesFetchDataRef.value.fetch();
    newTown.province = provincesOptions.value.find(
        (province) => province.id === newTown.provinceFk
    );
    formData.townFk = newTown;
    setTown(newTown, formData);
}
async function fetchTowns(countryFk = postcodeFormData.countryFk) {
    if (!countryFk) return;
    const provinces = postcodeFormData.provinceFk
        ? [postcodeFormData.provinceFk]
        : provinceByCountry();
    townFilter.value.where = {
        provinceFk: {
            inq: provinces,
        },
    };
    await townsFetchDataRef.value?.fetch();
}

async function filterTowns(name) {
    if (name !== '') {
        townFilter.value.where = {
            name: {
                like: `%${name}%`,
            },
        };
        await townsFetchDataRef.value?.fetch();
    }
}
</script>

<template>
    <FetchData
        ref="provincesFetchDataRef"
        @on-fetch="handleProvinces"
        :sort-by="['name ASC']"
        :limit="30"
        auto-load
        url="Provinces/location"
    />
    <FetchData
        ref="townsFetchDataRef"
        :sort-by="['name ASC']"
        :limit="30"
        :filter="townFilter"
        @on-fetch="handleTowns"
        auto-load
        url="Towns/location"
    />

    <FormModelPopup
        url-create="postcodes"
        model="postcode"
        :title="t('New postcode')"
        :subtitle="t('Please, ensure you put the correct data!')"
        :form-initial-data="postcodeFormData"
        :mapper="(data) => (data.townFk = data.townFk.id) && data"
        @on-data-saved="onDataSaved"
    >
        <template #form-inputs="{ data, validate }">
            <VnRow>
                <VnInput
                    :label="t('Postcode')"
                    v-model="data.code"
                    :rules="validate('postcode.code')"
                    clearable
                    required
                    data-cy="locationPostcode"
                />
                <VnSelectDialog
                    :label="t('City')"
                    @update:model-value="(value) => setTown(value, data)"
                    @filter="filterTowns"
                    :tooltip="t('Create city')"
                    v-model="data.townFk"
                    :options="townsOptions"
                    option-label="name"
                    option-value="id"
                    :rules="validate('postcode.city')"
                    :acls="[{ model: 'Town', props: '*', accessType: 'WRITE' }]"
                    :emit-value="false"
                    required
                    data-cy="locationTown"
                >
                    <template #option="{ itemProps, opt }">
                        <QItem v-bind="itemProps">
                            <QItemSection>
                                <QItemLabel>{{ opt.name }}</QItemLabel>
                                <QItemLabel caption>
                                    {{ opt.province.name }},
                                    {{ opt.province.country.name }}
                                </QItemLabel>
                            </QItemSection>
                        </QItem>
                    </template>
                    <template #form>
                        <CreateNewCityForm
                            :country-fk="data.countryFk"
                            :province-selected="data.provinceFk"
                            @on-data-saved="
                                (_, requestResponse) =>
                                    onCityCreated(requestResponse, data)
                            "
                        />
                    </template>
                </VnSelectDialog>
            </VnRow>
            <VnRow>
                <VnSelectProvince
                    :country-fk="data.countryFk"
                    :province-selected="data.provinceFk"
                    @update:model-value="(value) => setProvince(value, data)"
                    v-model="data.provinceFk"
                    @on-province-created="onProvinceCreated"
                    required
                />
                <VnSelect
                    ref="countriesRef"
                    :limit="30"
                    :filter="countryFilter"
                    :sort-by="['name ASC']"
                    auto-load
                    url="Countries"
                    required
                    :label="t('Country')"
                    hide-selected
                    option-label="name"
                    option-value="id"
                    v-model="data.countryFk"
                    :rules="validate('postcode.countryFk')"
                    @update:model-value="(value) => setCountry(value, data)"
                    data-cy="locationCountry"
                />
            </VnRow>
        </template>
    </FormModelPopup>
</template>

<i18n>
es:
    New postcode: Nuevo código postal
    Create city: Crear población
    Please, ensure you put the correct data!: ¡Por favor, asegúrese de poner los datos correctos!
    City: Población
    Province: Provincia
    Country: País
    Postcode: Código postal
</i18n>
