<script setup>
import { onMounted, ref, computed, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import { useArrayData } from 'composables/useArrayData';
import { useRoute } from 'vue-router';
import toDate from 'filters/toDate';

import VnFilterPanelChip from 'components/ui/VnFilterPanelChip.vue';

const { t } = useI18n();
const props = defineProps({
    dataKey: {
        type: String,
        required: true,
    },
    searchButton: {
        type: Boolean,
        required: false,
        default: false,
    },
    params: {
        type: Object,
        required: false,
        default: null,
    },
    showAll: {
        type: Boolean,
        default: true,
    },
    unremovableParams: {
        type: Array,
        required: false,
        default: () => [],
        description:
            'Algunos filtros vienen con parametros de búsqueda por default y necesitan tener si o si un valor, por eso de ser necesario, esta prop nos sirve para saber que filtros podemos remover y cuales no',
    },
    exprBuilder: {
        type: Function,
        default: null,
    },
    hiddenTags: {
        type: Array,
        default: () => [],
    },
    customTags: {
        type: Array,
        default: () => [],
    },
});

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

const arrayData = useArrayData(props.dataKey, {
    exprBuilder: props.exprBuilder,
});
const route = useRoute();
const store = arrayData.store;
const userParams = ref({});

onMounted(() => {
    if (props.params) userParams.value = JSON.parse(JSON.stringify(props.params));
    if (Object.keys(store.userParams).length > 0) {
        userParams.value = JSON.parse(JSON.stringify(store.userParams));
    }
    emit('init', { params: userParams.value });
});

watch(
    () => route.query.params,
    (val) => {
        if (!val) {
            userParams.value = {};
        } else {
            const parsedParams = JSON.parse(val);
            userParams.value = { ...parsedParams };
        }
    }
);

const isLoading = ref(false);
async function search() {
    isLoading.value = true;
    const params = { ...userParams.value };
    store.userParamsChanged = true;
    store.filter.skip = 0;
    store.skip = 0;
    const { params: newParams } = await arrayData.addFilter({ params });
    userParams.value = newParams;

    if (!props.showAll && !Object.values(params).length) store.data = [];

    isLoading.value = false;
    emit('search');
}

async function reload() {
    isLoading.value = true;
    const params = Object.values(userParams.value).filter((param) => param);

    await arrayData.fetch({ append: false });
    if (!props.showAll && !params.length) store.data = [];
    isLoading.value = false;
    emit('refresh');
}

async function clearFilters() {
    isLoading.value = true;
    store.userParamsChanged = true;
    store.filter.skip = 0;
    store.skip = 0;
    // 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];
    }
    userParams.value = { ...newParams }; // Actualizar los params con los removibles
    await arrayData.applyFilter({ params: userParams.value });

    if (!props.showAll) {
        store.data = [];
    }

    isLoading.value = false;
    emit('clear');
}

const tagsList = computed(() =>
    Object.entries(userParams.value)
        .filter(([key, value]) => value && !(props.hiddenTags || []).includes(key))
        .map(([key, value]) => ({
            label: key,
            value: value,
        }))
);

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

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

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}"`;
}
</script>

<template>
    <QForm @submit="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>
                    <div class="q-gutter-xs">
                        <QBtn
                            @click="clearFilters"
                            color="primary"
                            dense
                            flat
                            icon="filter_list_off"
                            padding="none"
                            round
                            size="sm"
                        >
                            <QTooltip>{{ t('Remove filters') }}</QTooltip>
                        </QBtn>
                        <QBtn
                            @click="reload"
                            color="primary"
                            dense
                            flat
                            icon="refresh"
                            padding="none"
                            round
                            size="sm"
                        >
                            <QTooltip>{{ t('Refresh') }}</QTooltip>
                        </QBtn>
                    </div>
                </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)"
                    >
                        <slot name="tags" :tag="chip" :format-fn="formatValue">
                            <div class="q-gutter-x-xs">
                                <strong>{{ chip.label }}:</strong>
                                <span>"{{ chip.value }}"</span>
                            </div>
                        </slot>
                    </VnFilterPanelChip>
                    <slot
                        v-if="$slots.customTags"
                        name="customTags"
                        :params="userParams"
                        :tags="customTags"
                        :format-fn="formatValue"
                        :search-fn="search"
                    />
                </div>
            </QItem>
            <QSeparator />
        </QList>
        <QList dense class="list q-gutter-y-sm q-mt-sm">
            <slot name="body" :params="userParams" :search-fn="search"></slot>
        </QList>
        <template v-if="props.searchButton">
            <QItem>
                <QItemSection class="q-py-sm">
                    <QBtn
                        :label="t('Search')"
                        class="full-width"
                        color="primary"
                        dense
                        icon="search"
                        rounded
                        type="submit"
                        unelevated
                    />
                </QItemSection>
            </QItem>
            <QSeparator />
        </template>
    </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>
