<template>
    <Teleport v-if="isHeaderMounted" to="#actions">
        <QInput
            :placeholder="$t('search')"
            v-model="search"
            debounce="500"
            class="search q-mr-sm"
            rounded
            dark
            dense
            standout
        >
            <template #prepend>
                <QIcon v-if="search === ''" name="search" />
                <QIcon
                    v-else
                    name="clear"
                    class="cursor-pointer"
                    @click="search = ''"
                />
            </template>
        </QInput>
        <QBtn
            :icon="$t(viewMode == 'list' ? 'view_list' : 'grid_on')"
            :label="$t(viewMode == 'list' ? 'listView' : 'gridView')"
            @click="onViewModeClick()"
            rounded
            no-caps
        />
    </Teleport>
    <div style="padding-bottom: 5em">
        <QDrawer v-model="$app.rightDrawerOpen" side="right" :width="250">
            <div class="q-pa-md">
                <div class="basket-info">
                    <p>{{ date(new Date()) }}</p>
                    <p>
                        {{ $t('warehouse') }}
                        {{ 'Algemesi' }}
                    </p>
                    <QBtn flat rounded no-caps>
                        {{ $t('modify') }}
                    </QBtn>
                </div>
                <div class="q-mt-md">
                    <div class="q-mb-xs text-grey-7">
                        {{ $t('category') }}
                        <QIcon
                            v-if="category"
                            style="font-size: 1.3em"
                            name="cancel"
                            class="cursor-pointer"
                            :title="$t('deleteFilter')"
                            @click="
                                $router.push({ params: { category: null } })
                            "
                        />
                    </div>
                    <div class="categories">
                        <QBtn
                            flat
                            round
                            class="category q-pa-sm"
                            v-for="cat in categories"
                            :class="{ active: category == cat.id }"
                            :key="cat.id"
                            :title="cat.name"
                            :to="{ params: { category: cat.id, type: null } }"
                        >
                            <img :src="`statics/category/${cat.code}.svg`" />
                        </QBtn>
                    </div>
                </div>
                <div class="q-mt-md" v-if="category || search">
                    <div class="q-mb-xs text-grey-7">
                        {{ $t('filterBy') }}
                    </div>
                    <QSelect
                        v-model="type"
                        option-value="id"
                        option-label="name"
                        :options="types"
                        :disable="!category"
                        clearable
                        :label="$t('family')"
                        @filter="filterType"
                        @input="
                            $router.push({ params: { type: type && type.id } })
                        "
                    />
                    <QSelect
                        v-model="order"
                        input-debounce="0"
                        :options="orderOptions"
                        :label="$t('orderBy')"
                    />
                </div>
            </div>
            <div class="q-pa-md" v-if="typeId || search">
                <div class="q-mb-md" v-for="tag in tags" :key="tag.uid">
                    <div class="q-mb-xs text-caption text-grey-7">
                        {{ tag.name }}
                        <QIcon
                            v-if="tag.hasFilter"
                            style="font-size: 1.3em"
                            name="cancel"
                            :title="$t('deleteFilter')"
                            class="cursor-pointer"
                            @click="onResetTagFilterClick(tag)"
                        />
                    </div>
                    <div v-if="!tag.useRange">
                        <div
                            v-for="value in tag.values.slice(0, tag.showCount)"
                            :key="value"
                        >
                            <QCheckbox
                                v-model="tag.filter"
                                :dense="true"
                                :val="value"
                                :label="value"
                                @input="onCheck(tag)"
                            />
                        </div>
                        <div v-if="tag.values.length > tag.showCount">
                            <span
                                class="cursor-pointer text-blue"
                                @click="tag.showCount = Infinity"
                            >
                                <QIcon name="keyboard_arrow_down" />
                                {{ $t('viewMore') }}
                            </span>
                        </div>
                        <div v-if="tag.showCount == Infinity">
                            <span
                                class="cursor-pointer text-blue"
                                @click="tag.showCount = tag.initialCount"
                            >
                                <QIcon name="keyboard_arrow_up" />
                                {{ $t('viewLess') }}
                            </span>
                        </div>
                    </div>
                    <div class="q-mx-md">
                        <QRange
                            class="q-mt-lg"
                            v-if="tag.useRange"
                            v-model="tag.filter"
                            :min="tag.min"
                            :max="tag.max"
                            :step="tag.step"
                            :color="tag.hasFilter ? 'primary' : 'grey-6'"
                            @input="onRangeChange(tag, true)"
                            @change="onRangeChange(tag)"
                            label-always
                            markers
                            snap
                        />
                    </div>
                </div>
            </div>
        </QDrawer>
        <QInfiniteScroll
            @load="onLoad"
            scroll-taget="html"
            :offset="800"
            :disable="disableScroll"
        >
            <div class="q-pa-md row justify-center q-gutter-md">
                <QSpinner v-if="isLoading" color="primary" size="50px" />
                <div
                    v-if="items && !items.length"
                    class="text-subtitle1 text-grey-7 q-pa-md"
                >
                    {{ $t('noItemsFound') }}
                </div>
                <div
                    v-if="!items && !isLoading"
                    class="text-subtitle1 text-grey-7 q-pa-md"
                >
                    {{ $t('pleaseSetFilter') }}
                </div>
                <QCard class="my-card" v-for="_item in items" :key="_item.id">
                    <img
                        :src="`${$imageBase}/catalog/200x200/${_item.image}`"
                    />
                    <QCardSection>
                        <div class="name text-subtitle1">
                            {{ _item.longName }}
                        </div>
                        <div
                            class="sub-name text-uppercase text-subtitle1 text-grey-7 ellipsize q-pt-xs"
                        >
                            {{ _item.subName }}
                        </div>
                        <div class="tags q-pt-xs">
                            <div v-for="tag in _item.tags" :key="tag.tagFk">
                                <span class="text-grey-7">{{
                                    tag.tag.name
                                }}</span>
                                {{ tag.value }}
                            </div>
                        </div>
                    </QCardSection>
                    <QCardActions class="actions justify-between">
                        <div class="q-pl-sm">
                            <span class="available bg-green text-white">{{
                                _item.available
                            }}</span>
                            {{ $t('from') }}
                            <span class="price">{{
                                currency(_item.buy?.price3)
                            }}</span>
                        </div>
                        <QBtn
                            icon="add_shopping_cart"
                            :title="$t('buy')"
                            @click="showItem(_item)"
                            flat
                        />
                    </QCardActions>
                </QCard>
            </div>
            <template #loading>
                <div class="row justify-center q-my-md">
                    <QSpinner color="primary" name="dots" size="40px" />
                </div>
            </template>
        </QInfiniteScroll>
        <QDialog v-model="showItemDialog">
            <QCard style="width: 25em">
                <QImg
                    :src="`${$imageBase}/catalog/200x200/${item.image}`"
                    :ratio="5 / 3"
                >
                    <div class="absolute-bottom text-center q-pa-xs">
                        <div class="text-subtitle1">
                            {{ item.longName }}
                        </div>
                    </div>
                </QImg>
                <QCardSection>
                    <div
                        class="text-uppercase text-subtitle1 text-grey-7 ellipsize"
                    >
                        {{ item.subName }}
                    </div>
                    <div class="text-grey-7">#{{ item.id }}</div>
                </QCardSection>
                <QCardSection>
                    <div v-for="tag in item.tags" :key="tag.tagFk">
                        <span class="text-grey-7">{{ tag.tag.name }}</span>
                        {{ tag.value }}
                    </div>
                </QCardSection>
                <QCardActions align="right">
                    <QBtn @click="showItemDialog = false" flat>
                        {{ $t('cancel') }}
                    </QBtn>
                    <QBtn @click="showItemDialog = false" flat>
                        {{ $t('accept') }}
                    </QBtn>
                </QCardActions>
            </QCard>
        </QDialog>
        <QPageSticky>
            <QBtn
                fab
                to="/ecomerce/basket"
                icon="shopping_cart"
                color="accent"
                :title="$t('shoppingCart')"
            />
        </QPageSticky>
    </div>
</template>

<style lang="scss" scoped>
.search {
    max-width: 250px;
}
.basket-info {
    background-color: #8cc63f;
    color: white;
    padding: 17px 28px;
    border-radius: 7px;
    text-align: center;

    & > p {
        margin: 0;
        padding: 0.4em 0;
        text-overflow: ellipsis;
        white-space: nowrap;
        overflow: hidden;
    }
}
.categories {
    margin: 0 auto;
    width: 220px;

    .category {
        width: 55px;

        &.active {
            background: rgba(0, 0, 0, 0.08);
        }
        & > img {
            height: 40px;
            width: 40px;
        }
    }
}
.tags {
    max-height: 4.6em;
    overflow: hidden;
}
.available {
    padding: 0.15em;
    border-radius: 0.2em;
    font-size: 1.3em;
}
.price {
    font-size: 1.3em;
}
.my-card {
    width: 100%;
    max-width: 17.5em;
    height: 32.5em;
    overflow: hidden;
    .name,
    .sub-name {
        line-height: 1.3em;
    }
    .ellipsize {
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }
    .description {
        height: 40px;
        overflow: hidden;
    }
}
</style>

<script>
import { date, currency, formatDate } from 'src/lib/filters.js';
import axios from 'axios';
import { useAppStore } from 'stores/app';
import { storeToRefs } from 'pinia';

const CancelToken = axios.CancelToken;

export default {
    name: 'HederaCatalog',
    setup() {
        const appStore = useAppStore();
        const { isHeaderMounted } = storeToRefs(appStore);
        return { isHeaderMounted };
    },
    data() {
        return {
            uid: 0,
            search: '',
            orderDate: formatDate(new Date(), 'YYYY/MM/DD'),
            category: null,
            categories: [],
            type: null,
            typeId: null,
            types: [],
            orgTypes: [],
            item: {},
            showItemDialog: false,
            tags: [],
            isLoading: false,
            items: null,
            limit: null,
            pageSize: 30,
            maxTags: 5,
            disableScroll: true,
            viewMode: 'list',
            order: {
                label: this.$t('relevancy'),
                value: 'relevancy DESC, longName'
            },
            orderOptions: [
                {
                    label: this.$t('relevancy'),
                    value: 'relevancy DESC, longName'
                },
                {
                    label: this.$t('name'),
                    value: 'longName'
                },
                {
                    label: this.$t('siceAsc'),
                    value: 'size ASC'
                },
                {
                    label: this.$t('sizeDesc'),
                    value: 'size DESC'
                },
                {
                    label: this.$t('priceAsc'),
                    value: 'price ASC'
                },
                {
                    label: this.$t('priceDesc'),
                    value: 'price DESC'
                },
                {
                    label: this.$t('available'),
                    value: 'available'
                }
            ]
        };
    },
    created() {
        this.$app.useRightDrawer = true;
    },
    async mounted() {
        this.categories = await this.$jApi.query(
            `SELECT c.id, l.name, c.color, c.code
        FROM vn.itemCategory c
          JOIN vn.itemCategoryL10n l ON l.id = c.id
        WHERE c.display
        ORDER BY display`
        );
        this.onRouteChange(this.$route);
    },
    beforeUnmount() {
        this.clearTimeoutAndRequest();
    },
    beforeRouteUpdate(to, from, next) {
        this.onRouteChange(to);
        next();
    },
    watch: {
        categories() {
            this.refreshTitle();
        },
        orgTypes() {
            this.refreshTitle();
        },
        order() {
            this.loadItems();
        },
        date() {
            this.loadItems();
        },
        async category(value) {
            this.orgTypes = [];
            if (!value) return;

            const res = await this.$jApi.execQuery(
                `CALL myOrder_getAvailable(${this.appStore.basketOrderId});
        SELECT DISTINCT t.id, l.name
          FROM vn.item i
            JOIN vn.itemType t ON t.id = i.typeFk
            JOIN tmp.itemAvailable a ON a.id = i.id
            JOIN vn.itemTypeL10n l ON l.id = t.id
          WHERE t.\`order\` >= 0
            AND t.categoryFk = #category
          ORDER BY t.\`order\`, l.name;
        DROP TEMPORARY TABLE tmp.itemAvailable;`,
                { category: value }
            );
            res.fetch();
            this.orgTypes = res.fetchData();
        },
        search(value) {
            const location = { params: this.$route.params };
            if (value) location.query = { search: value };
            this.$router.push(location);
        }
    },
    methods: {
        date,
        currency,
        onViewModeClick() {
            this.viewMode = this.viewMode === 'list' ? 'grid' : 'list';
        },
        onRouteChange(route) {
            let { category, type } = route.params;

            category = parseInt(category) || null;
            type = parseInt(type) || null;

            this.category = category;
            this.typeId = category ? type : null;
            this.search = route.query.search || '';
            this.tags = [];

            this.refreshTitle();
            this.loadItems();
        },
        refreshTitle() {
            let title = this.$t(this.$router.currentRoute.value.name);
            let subtitle;

            if (this.category) {
                const category =
                    this.categories.find(i => i.id === this.category) || {};
                title = category.name;
            }

            if (this.typeId) {
                this.type = this.orgTypes.find(i => i.id === this.typeId);
                subtitle = title;
                title = this.type && this.type.name;
            } else {
                this.type = null;
            }

            this.$app.$patch({ title, subtitle });
        },
        clearTimeoutAndRequest() {
            if (this.timeout) {
                clearTimeout(this.timeout);
                this.timeout = null;
            }
            if (this.source) {
                this.source.cancel();
                this.source = null;
            }
        },
        loadItemsDelayed() {
            this.clearTimeoutAndRequest();
            this.timeout = setTimeout(() => this.loadItems(), 500);
        },
        loadItems() {
            this.items = null;
            this.isLoading = true;
            this.limit = this.pageSize;
            this.disableScroll = false;
            this.isLoading = false;
            // this.loadItemsBase().finally(() => (this.isLoading = false))
        },
        onLoad(index, done) {
            if (this.isLoading) return done();
            this.limit += this.pageSize;
            done();
            // this.loadItemsBase().finally(done)
        },
        loadItemsBase() {
            this.clearTimeoutAndRequest();

            if (!(this.category || this.typeId || this.search)) {
                this.tags = [];
                return Promise.resolve(true);
            }

            const tagFilter = [];

            for (const tag of this.tags) {
                if (tag.hasFilter) {
                    tagFilter.push({
                        tagFk: tag.id,
                        values: tag.filter
                    });
                }
            }

            this.source = CancelToken.source();

            const params = {
                dated: this.orderDate,
                typeFk: this.typeId,
                categoryFk: this.category,
                search: this.search,
                order: this.order.value,
                limit: this.limit,
                tagFilter
            };
            const config = {
                params,
                cancelToken: this.source.token
            };
            return this.$axios
                .get('Items/catalog', config)
                .then(res => this.onItemsGet(res))
                .catch(err => this.onItemsError(err))
                .finally(() => (this.cancel = null));
        },
        onItemsError(err) {
            if (err.__CANCEL__) return;
            this.disableScroll = true;
            throw err;
        },
        onItemsGet(res) {
            for (const tag of res.data.tags) {
                tag.uid = this.uid++;

                if (tag.filter) {
                    tag.hasFilter = true;
                    tag.useRange = tag.filter.max || tag.filter.min;
                } else {
                    tag.useRange =
                        tag.isQuantitative && tag.values.length > this.maxTags;
                    this.resetTagFilter(tag);
                }

                if (tag.values) {
                    tag.initialCount = this.maxTags;
                    if (Array.isArray(tag.filter)) {
                        tag.initialCount = Math.max(
                            tag.initialCount,
                            tag.filter.length
                        );
                    }
                    tag.showCount = tag.initialCount;
                }
            }

            this.items = res.data.items;
            this.tags = res.data.tags;
            this.disableScroll = this.items.length < this.limit;
        },
        onRangeChange(tag, delay) {
            tag.hasFilter = true;

            if (!delay) this.loadItems();
            else this.loadItemsDelayed();
        },
        onCheck(tag) {
            tag.hasFilter = tag.filter.length > 0;
            this.loadItems();
        },
        resetTagFilter(tag) {
            tag.hasFilter = false;

            if (tag.useRange) {
                tag.filter = {
                    min: tag.min,
                    max: tag.max
                };
            } else {
                tag.filter = [];
            }
        },
        onResetTagFilterClick(tag) {
            this.resetTagFilter(tag);
            this.loadItems();
        },
        filterType(val, update) {
            if (val === '') {
                update(() => {
                    this.types = this.orgTypes;
                });
            } else {
                update(() => {
                    const needle = val.toLowerCase();
                    this.types = this.orgTypes.filter(
                        type => type.name.toLowerCase().indexOf(needle) > -1
                    );
                });
            }
        },
        showItem(item) {
            this.item = item;
            this.showItemDialog = true;

            const conf = this.$state.catalogConfig;
            const params = {
                dated: this.orderDate,
                addressFk: conf.addressFk,
                agencyModeFk: conf.agencyModeFk
            };
            this.$axios
                .get(`Items/${item.id}/calcCatalog`, { params })
                .then(res => (this.lots = res.data));
        }
    }
};
</script>

<i18n lang="yaml">
es-ES:
    gridView: Vista de rejilla
    listView: Vista de lista
    shoppingCart: Cesta de la compra
    warehouse: Almacén
    agency: Agencia
    modify: Modificar
    category: Categoría
    deleteFilter: Quitar filtro
    filterBy: Filtrar por
    family: Familia
    orderBy: Ordernar por
    pleaseSetFilter: Elige un filtro en el menú de la derecha
    search: Buscar
</i18n>
