<script setup>
import { ref, computed } from 'vue';
import { useI18n } from 'vue-i18n';
import { useArrayData } from 'composables/useArrayData';
import toDate from 'filters/toDate';
import VnFilterPanelChip from 'components/ui/VnFilterPanelChip.vue';
import { useFilterParams } from 'src/composables/useFilterParams';
import { useRoute } from 'vue-router';

const { t, te } = useI18n();
const route = useRoute();
const $props = defineProps({
    modelValue: {
        type: Object,
        default: () => {},
    },
    dataKey: {
        type: String,
        required: true,
    },
    searchButton: {
        type: Boolean,
        default: false,
    },
    showAll: {
        type: Boolean,
        default: true,
    },
    unremovableParams: {
        type: Array,
        required: false,
        default: () => [],
        description: `Some filters come with default search parameters and require a value.
            This prop helps us determine which filters can be removed and which cannot.`,
    },
    exprBuilder: {
        type: Function,
        default: null,
    },
    hiddenTags: {
        type: Array,
        default: () => ['filter', 'or', 'and'],
    },
    customTags: {
        type: Array,
        default: () => [],
    },
    disableSubmitEvent: {
        type: Boolean,
        default: false,
    },
    searchUrl: {
        type: String,
        default: 'table',
    },
    redirect: {
        type: Boolean,
        default: true,
    },
    arrayData: {
        type: Object,
        default: null,
    },
});

const emit = defineEmits([
    'update:modelValue',
    'refresh',
    'clear',
    'search',
    'init',
    'remove',
    'setUserParams',
]);

const arrayData =
    $props.arrayData ??
    useArrayData($props.dataKey, {
        exprBuilder: $props.exprBuilder,
        searchUrl: $props.searchUrl,
        navigate: $props.redirect ? {} : null,
    });

const store = arrayData.store;
const userParams = ref(useFilterParams($props.dataKey).params);
const userOrders = ref(useFilterParams($props.dataKey).orders);

defineExpose({ search, params: userParams, remove });

const isLoading = ref(false);
async function search(evt) {
    try {
        if (evt && $props.disableSubmitEvent) return;

        store.filter.where = {};
        isLoading.value = true;
        const filter = { ...userParams.value, ...$props.modelValue };
        store.userParamsChanged = true;
        await arrayData.addFilter({
            params: filter,
        });

        if (!$props.showAll && !Object.values(filter).length) store.data = [];
        emit('search');
    } finally {
        isLoading.value = false;
    }
}

async function clearFilters() {
    try {
        isLoading.value = true;
        store.userParamsChanged = true;
        arrayData.resetPagination();
        // Filtrar los params no removibles
        const removableFilters = Object.keys(userParams.value).filter((param) =>
            $props.unremovableParams.includes(param)
        );
        const newParams = {};
        // Conservar solo los params que no son removibles
        for (const key of removableFilters) {
            newParams[key] = userParams.value[key];
        }

        await arrayData.applyFilter({ params: { ...newParams } });

        if (!$props.showAll) {
            store.data = [];
        }
        emit('clear');
        emit('update:modelValue', userParams.value);
    } finally {
        isLoading.value = false;
    }
}

const tagsList = computed(() => {
    const tagList = [];
    for (const key of Object.keys(userParams.value)) {
        const value = userParams.value[key];
        if (value == null || ($props.hiddenTags || []).includes(key)) continue;
        tagList.push({ label: key, value });
    }
    return tagList;
});

const formatTags = (tags) => {
    const formattedTags = [];
    tags.forEach((tag) => {
        if (tag.label === 'and') {
            tag.value.forEach((item) => {
                for (const key in item) {
                    formattedTags.push({ label: key, value: item[key] });
                }
            });
        } else {
            formattedTags.push(tag);
        }
    });
    return formattedTags;
};

const tags = computed(() => {
    const filteredTags = tagsList.value.filter(
        (tag) => !($props.customTags || []).includes(tag.label)
    );
    return formatTags(filteredTags);
});

const customTags = computed(() =>
    tagsList.value.filter((tag) => ($props.customTags || []).includes(tag.label))
);

async function remove(key) {
    userParams.value[key] = undefined;
    await search();
    emit('remove', key);
    emit('update:modelValue', userParams.value);
}

function formatValue(value) {
    if (typeof value === 'boolean') return value ? t('Yes') : t('No');
    if (isNaN(value) && !isNaN(Date.parse(value))) return toDate(value);

    return `"${value}"`;
}

const getLocale = (label) => {
    const param = label.split('.').at(-1);
    const globalLocale = `globals.params.${param}`;
    if (te(globalLocale)) return t(globalLocale);
    else if (te(t(`params.${param}`)));
    else return t(`${route.meta.moduleName}.params.${param}`);
};
</script>

<template>
    <QBtn
        class="q-mt-lg q-mr-xs q-mb-lg"
        round
        color="primary"
        style="position: fixed; z-index: 1; right: 0; bottom: 0"
        icon="search"
        @click="search()"
    ></QBtn>
    <QForm @submit="search" id="filterPanelForm" @keyup.enter="search()">
        <QList dense>
            <QItem class="q-mt-xs">
                <QItemSection top>
                    <QItemLabel header lines="1" class="text-uppercase q-py-xs q-px-none">
                        {{ t('Applied filters') }}
                    </QItemLabel>
                </QItemSection>
                <QItemSection top side>
                    <QBtn
                        @click="clearFilters"
                        color="primary"
                        dense
                        flat
                        icon="filter_list_off"
                        padding="none"
                        round
                        size="sm"
                    >
                        <QTooltip>{{ t('Remove filters') }}</QTooltip>
                    </QBtn>
                </QItemSection>
            </QItem>
            <QItem class="q-mb-sm">
                <div
                    v-if="tagsList.length === 0"
                    class="text-grey font-xs text-center full-width"
                >
                    {{ t(`No filters applied`) }}
                </div>
                <div>
                    <VnFilterPanelChip
                        v-for="chip of tags"
                        :key="chip.label"
                        :removable="!unremovableParams?.includes(chip.label)"
                        @remove="remove(chip.label)"
                        data-cy="vnFilterPanelChip"
                    >
                        <slot
                            name="tags"
                            :tag="chip"
                            :format-fn="formatValue"
                            :get-locale="getLocale"
                        >
                            <div class="q-gutter-x-xs">
                                <strong>{{ chip.label }}:</strong>
                                <span>"{{ formatValue(chip.value) }}"</span>
                            </div>
                        </slot>
                    </VnFilterPanelChip>
                    <slot
                        v-if="$slots.customTags"
                        name="customTags"
                        :params="userParams"
                        :tags="customTags"
                        :format-fn="formatValue"
                        :get-locale="getLocale"
                        :search-fn="search"
                    />
                </div>
            </QItem>
            <QSeparator />
        </QList>
        <QList dense class="list q-gutter-y-sm q-mt-sm">
            <slot
                name="body"
                :get-locale="getLocale"
                :params="userParams"
                :orders="userOrders"
                :search-fn="search"
            ></slot>
        </QList>
    </QForm>
    <QInnerLoading
        :label="t('globals.pleaseWait')"
        :showing="isLoading"
        color="primary"
    />
</template>
<style scoped lang="scss">
.list {
    width: 256px;
}
</style>

<i18n>
es:
    No filters applied: No se han aplicado filtros
    Applied filters: Filtros aplicados
    Remove filters: Eliminar filtros
    Refresh: Refrescar
    Search: Buscar
    Yes: Si
    No: No
</i18n>
