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

import FetchData from 'components/FetchData.vue';
import VnInput from 'src/components/common/VnInput.vue';
import VnSelect from 'src/components/common/VnSelect.vue';
import TicketDescriptorProxy from 'src/pages/Ticket/Card/TicketDescriptorProxy.vue';
import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
import VnProgress from 'src/components/common/VnProgressModal.vue';
import RightMenu from 'src/components/common/RightMenu.vue';
import TicketAdvanceFilter from './TicketAdvanceFilter.vue';

import { dashIfEmpty, toCurrency } from 'src/filters';
import { useVnConfirm } from 'composables/useVnConfirm';
import { useArrayData } from 'composables/useArrayData';
import useNotify from 'src/composables/useNotify.js';
import { useState } from 'src/composables/useState';
import { toDateFormat } from 'src/filters/date.js';
import axios from 'axios';

const state = useState();
const { t } = useI18n();
const { openConfirmationModal } = useVnConfirm();
const { notify } = useNotify();
const user = state.getUser();

const itemPackingTypesOptions = ref([]);
const zonesOptions = ref([]);
const selectedTickets = ref([]);

const exprBuilder = (param, value) => {
    switch (param) {
        case 'id':
        case 'futureId':
        case 'liters':
        case 'futureLiters':
        case 'lines':
        case 'futureLines':
        case 'totalWithVat':
        case 'futureTotalWithVat':
        case 'futureZone':
        case 'notMovableLines':
        case 'futureZoneFk':
            return { [param]: value };
        case 'iptColFilter':
            return { ipt: { like: `%${value}%` } };
        case 'futureIptColFilter':
            return { futureIpt: { like: `%${value}%` } };
    }
};

const userParams = reactive({});

const arrayData = useArrayData('AdvanceTickets', {
    url: 'Tickets/getTicketsAdvance',
    userParams: userParams,
    exprBuilder: exprBuilder,
    limit: 0,
});
const { store } = arrayData;
const tickets = computed(() =>
    (store.data || []).map((ticket, index) => ({ ...ticket, index: index }))
);

const applyColumnFilter = async (col) => {
    try {
        const paramKey = col.columnFilter?.filterParamKey || col.field;
        userParams[paramKey] = col.columnFilter.filterValue;
        await arrayData.addFilter({ params: userParams });
    } catch (err) {
        console.error('Error applying column filter', err);
    }
};

const getInputEvents = (col) => {
    return col.columnFilter.type === 'select'
        ? { 'update:modelValue': () => applyColumnFilter(col) }
        : {
              'keyup.enter': () => applyColumnFilter(col),
          };
};

const ticketColumns = computed(() => [
    {
        label: '',
        name: 'icons',
        align: 'left',
        columnFilter: null,
    },
    {
        label: t('advanceTickets.ticketId'),
        name: 'ticketId',
        align: 'center',
        sortable: true,
        columnFilter: {
            component: VnInput,
            type: 'text',
            filterValue: null,
            filterParamKey: 'id',
            event: getInputEvents,
            attrs: {
                dense: true,
            },
        },
    },
    {
        label: t('advanceTickets.ipt'),
        name: 'ipt',
        field: 'ipt',
        align: 'left',
        sortable: true,
        columnFilter: {
            component: VnSelect,
            filterParamKey: 'iptColFilter',
            type: 'select',
            filterValue: null,
            event: getInputEvents,
            attrs: {
                options: itemPackingTypesOptions.value,
                'option-value': 'code',
                'option-label': 'description',
                dense: true,
            },
        },
        format: (val) => dashIfEmpty(val),
    },
    {
        label: t('advanceTickets.state'),
        name: 'state',
        align: 'left',
        sortable: true,
        columnFilter: null,
    },
    {
        label: t('advanceTickets.preparation'),
        name: 'preparation',
        field: 'preparation',
        align: 'left',
        sortable: true,
        columnFilter: null,
    },
    {
        label: t('advanceTickets.liters'),
        name: 'liters',
        field: 'liters',
        align: 'left',
        sortable: true,
        columnFilter: {
            component: VnInput,
            type: 'text',
            filterValue: null,
            event: getInputEvents,
            attrs: {
                dense: true,
            },
        },
    },
    {
        label: t('advanceTickets.lines'),
        name: 'lines',
        field: 'lines',
        align: 'left',
        sortable: true,
        columnFilter: {
            component: VnInput,
            type: 'text',
            filterValue: null,
            event: getInputEvents,
            attrs: {
                dense: true,
            },
        },
        format: (val) => dashIfEmpty(val),
    },
    {
        label: t('advanceTickets.import'),
        field: 'import',
        name: 'import',
        align: 'left',
        sortable: true,
    },
    {
        label: t('advanceTickets.futureId'),
        name: 'futureId',
        align: 'left',
        sortable: true,
        columnFilter: {
            component: VnInput,
            type: 'text',
            filterValue: null,
            filterParamKey: 'futureId',
            event: getInputEvents,
            attrs: {
                dense: true,
            },
        },
    },
    {
        label: t('advanceTickets.futureIpt'),
        name: 'futureIpt',
        field: 'futureIpt',
        align: 'left',
        sortable: true,
        columnFilter: {
            component: VnSelect,
            filterParamKey: 'futureIptColFilter',
            type: 'select',
            filterValue: null,
            event: getInputEvents,
            attrs: {
                options: itemPackingTypesOptions.value,
                'option-value': 'code',
                'option-label': 'description',
                dense: true,
            },
        },
        format: (val) => dashIfEmpty(val),
    },
    {
        label: t('advanceTickets.futureState'),
        name: 'futureState',
        align: 'left',
        sortable: true,
        columnFilter: null,
        format: (val) => dashIfEmpty(val),
    },
    {
        label: t('advanceTickets.futureLiters'),
        name: 'futureLiters',
        field: 'futureLiters',
        align: 'left',
        sortable: true,
        columnFilter: {
            component: VnInput,
            type: 'text',
            filterValue: null,
            event: getInputEvents,
            attrs: {
                dense: true,
            },
        },
        format: (val) => dashIfEmpty(val),
    },
    {
        label: t('advanceTickets.futureZone'),
        name: 'futureZoneName',
        field: 'futureZoneName',
        align: 'left',
        sortable: true,
        columnFilter: {
            component: VnSelect,
            type: 'select',
            filterValue: null,
            filterParamKey: 'futureZoneFk',
            event: getInputEvents,
            attrs: {
                options: zonesOptions.value,
                'option-value': 'id',
                'option-label': 'name',
                dense: true,
            },
        },
        format: (val) => dashIfEmpty(val),
    },
    {
        label: t('advanceTickets.notMovableLines'),
        name: 'notMovableLines',
        field: 'notMovableLines',
        align: 'left',
        sortable: true,
        columnFilter: {
            component: VnInput,
            type: 'text',
            filterValue: null,
            event: getInputEvents,
            attrs: {
                dense: true,
            },
        },
        format: (val) => dashIfEmpty(val),
    },
    {
        label: t('advanceTickets.futureLines'),
        name: 'futureLines',
        field: 'futureLines',
        align: 'left',
        sortable: true,
        columnFilter: {
            component: VnInput,
            type: 'text',
            filterValue: null,
            event: getInputEvents,
            attrs: {
                dense: true,
            },
        },
        format: (val) => dashIfEmpty(val),
    },
    {
        label: t('advanceTickets.futureImport'),
        name: 'futureImport',
        align: 'left',
        sortable: true,
        columnFilter: null,
    },
]);

const isLessThan50 = (totalWithVat) =>
    parseInt(totalWithVat) > 0 && parseInt(totalWithVat) < 50;

const totalPriceColor = (totalWithVat) =>
    isLessThan50(totalWithVat) ? 'warning' : 'transparent';

const getLanded = async (params) => {
    try {
        const query = `Agencies/getLanded`;
        const { data } = await axios.get(query, { params });
        if (!data) return;
        return data;
    } catch (error) {
        notify(t('advanceTickets.noDeliveryZone'), 'negative');
        console.error('Error getting landed', error);
    }
};

const requestComponentUpdate = async (ticket, isWithoutNegatives) => {
    const query = `tickets/${ticket.futureId}/componentUpdate`;
    if (!ticket.landed) {
        const newLanded = await getLanded({
            shipped: userParams.dateToAdvance,
            addressFk: ticket.futureAddressFk,
            agencyModeFk: ticket.agencyModeFk ?? ticket.futureAgencyModeFk,
            warehouseFk: ticket.futureWarehouseFk,
        });

        if (!newLanded) {
            notify(t('advanceTickets.noDeliveryZone'), 'negative');
            return;
        }

        ticket.landed = newLanded.landed;
        ticket.zoneFk = newLanded.zoneFk;
    }

    const params = {
        clientFk: ticket.futureClientFk,
        nickname: ticket.nickname,
        agencyModeFk: ticket.agencyModeFk ?? ticket.futureAgencyModeFk,
        addressFk: ticket.futureAddressFk,
        zoneFk: ticket.zoneFk ?? ticket.futureZoneFk,
        warehouseFk: ticket.futureWarehouseFk,
        companyFk: ticket.futureCompanyFk,
        shipped: userParams.dateToAdvance,
        landed: ticket.landed,
        isDeleted: false,
        isWithoutNegatives,
        newTicket: ticket.id ?? undefined,
        keepPrice: true,
    };

    return { query, params };
};

const moveTicketsAdvance = async () => {
    try {
        let ticketsToMove = [];
        for (const ticket of selectedTickets.value) {
            if (!ticket.id) {
                try {
                    const { query, params } = await requestComponentUpdate(ticket, false);
                    axios.post(query, params);
                } catch (e) {
                    console.error('Error moving ticket', e);
                }
                continue;
            }
            ticketsToMove.push({
                originId: ticket.futureId,
                destinationId: ticket.id,
                originShipped: ticket.futureShipped,
                destinationShipped: ticket.shipped,
                workerFk: ticket.workerFk,
            });
        }

        const params = { tickets: ticketsToMove };
        await axios.post('Tickets/merge', params);
        arrayData.fetch({ append: false });
        selectedTickets.value = [];
        if (ticketsToMove.length)
            notify(t('advanceTickets.moveTicketSuccess'), 'positive');
    } catch (error) {
        console.error('Error moving tickets', error);
    }
};

const progressLength = ref(0);
const progressPercentage = computed(() => {
    if (progressLength.value === 0 || selectedTickets.value.length === 0) return 0;
    return progressLength.value / selectedTickets.value.length;
});
const splitErrors = ref([]);
const showProgressDialog = ref(false);
const cancelProgress = ref(false);

const progressAdd = () => {
    progressLength.value++;
    if (progressLength.value === selectedTickets.value.length) {
        notify(
            t('advanceTickets.moveTicketSuccess', {
                ticketsNumber: progressLength.value - splitErrors.value.length,
            }),
            'positive'
        );
    }
};

const splitTickets = async () => {
    try {
        showProgressDialog.value = true;
        for (const ticket of selectedTickets.value) {
            if (cancelProgress.value) break;
            try {
                const { query, params } = await requestComponentUpdate(ticket, true);
                await axios.post(query, params);
                progressAdd(ticket.futureId);
            } catch (error) {
                splitErrors.value.push({
                    id: ticket.futureId,
                    reason: error.response?.data?.error?.message,
                });
                progressAdd(ticket.futureId);
            }
        }
    } catch (error) {
        console.error('Error splitting tickets', error);
    } finally {
        arrayData.fetch({ append: false });
    }
};

const resetProgressData = () => {
    if (cancelProgress.value) cancelProgress.value = false;
    progressLength.value = 0;
    splitErrors.value = [];
    selectedTickets.value = [];
};

const handleCloseProgressDialog = () => {
    showProgressDialog.value = false;
    resetProgressData();
};

const handleCancelProgress = () => (cancelProgress.value = true);

onMounted(async () => {
    let today = Date.vnNew();
    const tomorrow = new Date(today);
    tomorrow.setDate(tomorrow.getDate() + 1);
    userParams.dateFuture = tomorrow;
    userParams.dateToAdvance = today;
    userParams.scopeDays = 1;
    userParams.warehouseFk = user.value.warehouseFk;
    userParams.ipt = 'H';
    userParams.futureIpt = 'H';
    userParams.isFullMovable = true;
    const filter = { limit: 0 };
    await arrayData.addFilter({ filter, userParams });
});
</script>

<template>
    <FetchData
        url="itemPackingTypes"
        :filter="{
            fields: ['code', 'description'],
            order: 'description ASC',
            where: { isActive: true },
        }"
        auto-load
        @on-fetch="(data) => (itemPackingTypesOptions = data)"
    />
    <FetchData
        url="Zones"
        :filter="{
            fields: ['id', 'name'],
            order: 'name ASC',
        }"
        auto-load
        @on-fetch="(data) => (zonesOptions = data)"
    />
    <VnSearchbar
        data-key="WeeklyTickets"
        :label="t('weeklyTickets.search')"
        :info="t('weeklyTickets.searchInfo')"
    />
    <VnSubToolbar>
        <template #st-data>
            <QBtn
                icon="keyboard_double_arrow_left"
                color="primary"
                class="q-mr-sm"
                :disable="!selectedTickets.length"
                @click.stop="
                    openConfirmationModal(
                        t('advanceTickets.advanceTicketTitle'),
                        t(`advanceTickets.advanceTitleSubtitle`, {
                            selectedTickets: selectedTickets.length,
                        }),
                        moveTicketsAdvance
                    )
                "
            >
                <QTooltip>
                    {{ t('advanceTickets.advanceTickets') }}
                </QTooltip>
            </QBtn>
            <QBtn
                icon="alt_route"
                color="primary"
                :disable="!selectedTickets.length"
                @click.stop="
                    openConfirmationModal(
                        t('advanceTickets.advanceWithoutNegativeTitle'),
                        t(`advanceTickets.advanceWithoutNegativeSubtitle`, {
                            selectedTickets: selectedTickets.length,
                        }),
                        splitTickets
                    )
                "
            >
                <QTooltip>
                    {{ t('advanceTickets.advanceTicketsWithoutNegatives') }}
                </QTooltip>
            </QBtn>
        </template>
    </VnSubToolbar>
    <RightMenu>
        <template #right-panel>
            <TicketAdvanceFilter data-key="AdvanceTickets" />
        </template>
    </RightMenu>
    <QPage class="column items-center q-pa-md">
        <QTable
            :rows="tickets"
            :columns="ticketColumns"
            row-key="index"
            selection="multiple"
            v-model:selected="selectedTickets"
            :pagination="{ rowsPerPage: 0 }"
            :no-data-label="t('globals.noResults')"
            style="max-width: 99%"
        >
            <template #header="props">
                {{ userParams.scopeDays }}
                <QTr :props="props">
                    <QTh
                        class="horizontal-separator text-uppercase color-vn-label"
                        colspan="7"
                        translate
                    >
                        {{ t('advanceTickets.destination') }}
                        {{ toDateFormat(userParams.dateToAdvance) }}
                    </QTh>
                    <QTh
                        class="horizontal-separator text-uppercase color-vn-label"
                        colspan="9"
                        translate
                    >
                        {{ t('advanceTickets.origin') }}
                        {{ toDateFormat(userParams.dateFuture) }}
                    </QTh>
                </QTr>
                <QTr>
                    <QTh>
                        <QCheckbox v-model="props.selected" />
                    </QTh>
                    <QTh
                        v-for="(col, index) in ticketColumns"
                        :key="index"
                        :class="{ 'vertical-separator': col.name === 'futureId' }"
                    >
                        {{ col.label }}
                    </QTh>
                </QTr>
            </template>
            <template #top-row="{ cols }">
                <QTr>
                    <QTd />
                    <QTd
                        v-for="(col, index) in cols"
                        :key="index"
                        style="max-width: 100px"
                    >
                        <component
                            :is="col.columnFilter.component"
                            v-if="col.columnFilter"
                            v-model="col.columnFilter.filterValue"
                            v-bind="col.columnFilter.attrs"
                            v-on="col.columnFilter.event(col)"
                            dense
                        />
                    </QTd>
                </QTr>
            </template>
            <template #header-cell-availableLines="{ col }">
                <QTh class="vertical-separator">
                    {{ col.label }}
                </QTh>
            </template>
            <template #body-cell-icons="{ row }">
                <QTd class="q-gutter-x-xs">
                    <QIcon
                        v-if="row.futureAgency !== row.agency && row.agency"
                        color="primary"
                        name="vn:agency-term"
                        size="xs"
                    >
                        <QTooltip class="column">
                            <span>
                                {{
                                    t('advanceTickets.originAgency', {
                                        agency: row.futureAgency,
                                    })
                                }}
                            </span>
                            <span>
                                {{
                                    t('advanceTickets.destinationAgency', {
                                        agency: row.agency,
                                    })
                                }}
                            </span>
                        </QTooltip>
                    </QIcon>
                </QTd>
            </template>

            <template #body-cell-ticketId="{ row }">
                <QTd>
                    <QBtn flat class="link">
                        {{ row.id }}
                        <TicketDescriptorProxy :id="row.id" />
                    </QBtn>
                </QTd>
            </template>
            <template #body-cell-state="{ row }">
                <QTd>
                    <QBadge
                        v-if="row.state"
                        text-color="black"
                        :color="row.classColor"
                        class="q-ma-none"
                        dense
                    >
                        {{ row.state }}
                    </QBadge>
                    <span v-else> {{ dashIfEmpty(row.state) }}</span>
                </QTd>
            </template>
            <template #body-cell-import="{ row }">
                <QTd>
                    <QBadge
                        :text-color="isLessThan50(row.totalWithVat) ? 'black' : 'white'"
                        :color="totalPriceColor(row.totalWithVat)"
                        class="q-ma-none"
                        dense
                    >
                        {{ toCurrency(row.totalWithVat || 0) }}
                    </QBadge>
                </QTd>
            </template>
            <template #body-cell-futureId="{ row }">
                <QTd class="vertical-separator">
                    <QBtn flat class="link" dense>
                        {{ row.futureId }}
                        <TicketDescriptorProxy :id="row.futureId" />
                    </QBtn>
                </QTd>
            </template>
            <template #body-cell-futureState="{ row }">
                <QTd>
                    <QBadge
                        text-color="black"
                        :color="row.futureClassColor"
                        class="q-ma-none"
                        dense
                    >
                        {{ row.futureState }}
                    </QBadge>
                </QTd>
            </template>
            <template #body-cell-futureImport="{ row }">
                <QTd>
                    <QBadge
                        :text-color="
                            isLessThan50(row.futureTotalWithVat) ? 'black' : 'white'
                        "
                        :color="totalPriceColor(row.futureTotalWithVat)"
                        class="q-ma-none"
                        dense
                    >
                        {{ toCurrency(row.futureTotalWithVat || 0) }}
                    </QBadge>
                </QTd>
            </template>
        </QTable>
        <VnProgress
            :progress="progressPercentage"
            :cancelled="cancelProgress"
            v-model:show-dialog="showProgressDialog"
            @cancel="handleCancelProgress()"
            @close="handleCloseProgressDialog()"
        >
            <div v-if="splitErrors.length" class="column">
                <span>{{ t('advanceTickets.errorsList') }}:</span>
                <span v-for="(error, index) in splitErrors" :key="index">
                    {{ error.id }}: {{ error.reason }}
                </span>
            </div>
        </VnProgress>
    </QPage>
</template>

<style scoped lang="scss">
.vertical-separator {
    border-left: 4px solid white !important;
}

.horizontal-separator {
    border-bottom: 4px solid white !important;
}
</style>
