<script setup>
import {
    ref,
    computed,
    markRaw,
    useTemplateRef,
    onBeforeMount,
    watch,
    onUnmounted,
} from 'vue';
import { useI18n } from 'vue-i18n';
import { toDate, toCurrency } from 'src/filters';
import { useArrayData } from 'src/composables/useArrayData';
import VnTable from 'src/components/VnTable/VnTable.vue';
import FetchData from 'src/components/FetchData.vue';
import VnSelectSupplier from 'src/components/common/VnSelectSupplier.vue';
import EntryDescriptorProxy from './Card/EntryDescriptorProxy.vue';
import SupplierDescriptorProxy from '../Supplier/Card/SupplierDescriptorProxy.vue';
import VnInputNumber from 'src/components/common/VnInputNumber.vue';
import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
import axios from 'axios';
import useNotify from 'src/composables/useNotify';
import VnConfirm from 'src/components/ui/VnConfirm.vue';
import VnDms from 'src/components/common/VnDms.vue';
import { useState } from 'src/composables/useState';
import { useQuasar } from 'quasar';
import InvoiceInDescriptorProxy from '../InvoiceIn/Card/InvoiceInDescriptorProxy.vue';
import { useStateStore } from 'src/stores/useStateStore';
import { downloadFile } from 'src/composables/downloadFile';
import { useRoute } from 'vue-router';
import { useAcl } from 'src/composables/useAcl';

const route = useRoute();
const { t } = useI18n();
const quasar = useQuasar();
const { notify } = useNotify();
const user = useState().getUser();
const stateStore = useStateStore();
const updateDialog = ref();
const uploadDialog = ref();
const dataKey = 'entryPreaccountingFilter';
const url = 'Entries/preAccountingFilter';
const arrayData = useArrayData(dataKey);
const daysAgo = ref();
const isBooked = ref();
const dmsData = ref();
const table = useTemplateRef('table');
const companies = ref([]);
const countries = ref([]);
const entryTypes = ref([]);
const supplierFiscalTypes = ref([]);
const warehouses = ref([]);
const defaultDmsDescription = ref();
const dmsTypeId = ref();
const selectedRows = ref([]);
const totalAmount = ref();
const hasDiferentDms = ref(false);
let maxDays;
let defaultDays;
let supplierRef;
let dmsFk;
const totalSelectedAmount = computed(() => {
    if (!selectedRows.value.length) return 0;
    return selectedRows.value.reduce((acc, entry) => acc + entry.amount, 0);
});

const columns = computed(() => [
    {
        name: 'id',
        label: t('entry.preAccount.id'),
        isId: true,
        chip: {
            condition: () => true,
        },
    },
    {
        name: 'invoiceNumber',
        label: t('entry.preAccount.invoiceNumber'),
        width: 'max-content',
    },
    {
        name: 'company',
        label: t('globals.company'),
        columnFilter: {
            component: 'select',
            name: 'companyFk',
            optionLabel: 'code',
            options: companies.value,
        },
        class: 'shrink',
    },
    {
        name: 'warehouse',
        label: t('globals.warehouse'),
        columnFilter: {
            component: 'select',
            name: 'warehouseInFk',
            options: warehouses.value,
        },
    },
    {
        name: 'gestDocFk',
        label: t('entry.preAccount.gestDocFk'),
    },
    {
        name: 'dmsType',
        label: t('entry.preAccount.dmsType'),
        columnFilter: {
            component: 'select',
            label: null,
            name: 'dmsTypeFk',
            url: 'DmsTypes',
            fields: ['id', 'name'],
        },
    },
    {
        name: 'reference',
        label: t('entry.preAccount.reference'),
        width: 'max-content',
    },
    {
        name: 'shipped',
        label: t('entry.preAccount.shipped'),
        format: ({ shipped }, dashIfEmpty) => dashIfEmpty(toDate(shipped)),
        columnFilter: {
            component: 'date',
            name: 'shipped',
        },
    },
    {
        name: 'landed',
        label: t('entry.preAccount.landed'),
        format: ({ landed }, dashIfEmpty) => dashIfEmpty(toDate(landed)),
        columnFilter: {
            component: 'date',
            name: 'landed',
        },
    },
    {
        name: 'invoiceInFk',
        label: t('entry.preAccount.invoiceInFk'),
    },
    {
        name: 'supplier',
        label: t('globals.supplier'),
        format: (row) => row.supplier,
        columnFilter: {
            component: markRaw(VnSelectSupplier),
            label: null,
            name: 'supplierFk',
            class: 'fit',
            event: 'update',
        },
        width: 'max-content',
    },
    {
        name: 'country',
        label: t('globals.country'),
        columnFilter: {
            component: 'select',
            name: 'countryFk',
            options: countries.value,
        },
        class: 'shrink',
    },
    {
        name: 'description',
        label: t('entry.preAccount.entryType'),
        columnFilter: {
            component: 'select',
            label: null,
            name: 'typeFk',
            options: entryTypes.value,
            optionLabel: 'description',
            optionValue: 'code',
        },
    },
    {
        name: 'payDem',
        label: t('entry.preAccount.payDem'),
        columnFilter: {
            component: 'number',
            name: 'payDem',
        },
        class: 'shrink',
    },
    {
        name: 'fiscalCode',
        label: t('entry.preAccount.fiscalCode'),
        format: ({ fiscalCode }) => t(fiscalCode),
        columnFilter: {
            component: 'select',
            name: 'fiscalCode',
            options: supplierFiscalTypes.value,
            optionLabel: 'locale',
            optionValue: 'code',
            sortBy: 'code',
        },
    },
    {
        name: 'amount',
        label: t('globals.amount'),
        format: ({ amount }) => toCurrency(amount),
        columnFilter: {
            component: 'number',
            name: 'amount',
        },
    },
    {
        name: 'isAgricultural',
        label: t('entry.preAccount.isAgricultural'),
        component: 'checkbox',
        isEditable: false,
    },
    {
        name: 'isBooked',
        label: t('entry.preAccount.isBooked'),
        component: 'checkbox',
    },
    {
        name: 'isReceived',
        label: t('entry.preAccount.isReceived'),
        component: 'checkbox',
        isEditable: false,
    },
]);

onBeforeMount(async () => {
    const filter = JSON.parse(route.query.entryPreaccountingFilter ?? '{}');
    const { data } = await axios.get('EntryConfigs/findOne', {
        params: { filter: JSON.stringify({ fields: ['maxDays', 'defaultDays'] }) },
    });
    maxDays = data.maxDays;
    defaultDays = data.defaultDays;
    daysAgo.value = filter.daysAgo || defaultDays;
    isBooked.value = filter.isBooked || false;
    stateStore.leftDrawer = false;
});

onUnmounted(() => (stateStore.leftDrawer = true));

watch(selectedRows, async (nVal, oVal) => {
    if (nVal.length > oVal.length && nVal.at(-1).invoiceInFk)
        quasar.dialog({
            component: VnConfirm,
            componentProps: { title: t('entry.preAccount.hasInvoice') },
        });
});

function filterByDaysAgo(val) {
    if (!val) val = defaultDays;
    else if (val > maxDays) val = maxDays;
    daysAgo.value = val;
    table.value.reload({
        userParams: { ...arrayData.store.userParams, daysAgo: daysAgo.value },
    });
}

async function preAccount() {
    const entries = selectedRows.value;
    const { companyFk, isAgricultural, landed } = entries.at(0);
    supplierRef = null;
    dmsFk = undefined;
    hasDiferentDms.value = false;
    try {
        entries.forEach(({ gestDocFk }) => {
            if (!dmsFk) dmsFk = gestDocFk;
            if (gestDocFk && dmsFk && dmsFk !== gestDocFk) hasDiferentDms.value = true;
        });
        if (isAgricultural) {
            const year = new Date(landed).getFullYear();
            supplierRef = (
                await axios.get('InvoiceIns/getMaxRef', { params: { companyFk, year } })
            ).data;
            return createInvoice();
        } else if (dmsFk) {
            supplierRef = (
                await axios.get(`Dms/${dmsFk}`, {
                    params: { filter: JSON.stringify({ fields: ['reference'] }) },
                })
            ).data?.reference;
            updateDialog.value.show();
        } else {
            uploadFile();
        }
    } catch (e) {
        throw e;
    }
}

async function updateFile() {
    await axios.post(`Dms/${dmsFk}/updateFile`, { dmsTypeId: dmsTypeId.value });
    await createInvoice();
}

async function uploadFile() {
    const firstSelectedEntry = selectedRows.value.at(0);
    const { supplier, companyFk, invoiceNumber } = firstSelectedEntry;
    dmsData.value = {
        dmsTypeFk: dmsTypeId.value,
        warehouseFk: user.value.warehouseFk,
        companyFk: companyFk,
        description: supplier + defaultDmsDescription.value + invoiceNumber,
        hasFile: false,
    };
    uploadDialog.value.show();
}

async function afterUploadFile({ reference }, res) {
    supplierRef = reference;
    dmsFk = res.data[0].id;
    await createInvoice();
}

async function createInvoice() {
    try {
        await axios.post(`Entries/addInvoiceIn`, {
            ids: selectedRows.value.map((entry) => entry.id),
            supplierRef,
            dmsFk,
        });
        notify(t('entry.preAccount.success'), 'positive');
    } catch (e) {
        throw e;
    } finally {
        selectedRows.value.length = 0;
        table.value.reload();
    }
}
</script>
<template>
    <FetchData
        url="Countries"
        :filter="{ fields: ['id', 'name'] }"
        @on-fetch="(data) => (countries = data)"
        auto-load
    />
    <FetchData
        url="Companies"
        :filter="{ fields: ['id', 'code'] }"
        @on-fetch="(data) => (companies = data)"
        auto-load
    />
    <FetchData
        url="Warehouses"
        :filter="{ fields: ['id', 'name'] }"
        @on-fetch="(data) => (warehouses = data)"
        auto-load
    />
    <FetchData
        url="EntryTypes"
        :filter="{ fields: ['code', 'description'] }"
        @on-fetch="(data) => (entryTypes = data)"
        auto-load
    />
    <FetchData
        url="supplierFiscalTypes"
        :filter="{ fields: ['code'] }"
        @on-fetch="
            (data) =>
                (supplierFiscalTypes = data.map((x) => ({ locale: t(x.code), ...x })))
        "
        auto-load
    />
    <FetchData
        url="InvoiceInConfigs/findOne"
        :filter="{ fields: ['defaultDmsDescription'] }"
        @on-fetch="(data) => (defaultDmsDescription = data?.defaultDmsDescription)"
        auto-load
    />
    <FetchData
        url="DmsTypes/findOne"
        :filter="{ fields: ['id'] }"
        :where="{ code: 'invoiceIn' }"
        @on-fetch="(data) => (dmsTypeId = data?.id)"
        auto-load
    />
    <VnSearchbar
        :data-key
        :url
        :label="t('entry.preAccount.search')"
        :info="t('entry.preAccount.searchInfo')"
        :search-remove-params="false"
    />
    <VnTable
        v-if="isBooked !== undefined && daysAgo !== undefined"
        v-model:selected="selectedRows"
        :data-key
        :columns
        :url
        :search-url="dataKey"
        ref="table"
        :disable-option="{ card: true }"
        redirect="Entry"
        :order="['landed DESC']"
        :right-search="false"
        :user-params="{ daysAgo, isBooked }"
        :row-click="false"
        :table="{ selection: 'multiple' }"
        :limit="0"
        :footer="true"
        @on-fetch="
            (data) => (totalAmount = data?.reduce((acc, entry) => acc + entry.amount, 0))
        "
        :selection-fn="(rows) => rows.filter((row) => !row.isBooked)"
    >
        <template #top-left>
            <QBtn
                v-if="useAcl().hasAcl('Entry', 'addInvoiceIn', 'WRITE')"
                data-cy="preAccount_btn"
                icon="account_balance"
                color="primary"
                class="q-mr-sm"
                :disable="!selectedRows.length"
                @click="preAccount"
            >
                <QTooltip>{{ t('entry.preAccount.btn') }}</QTooltip>
            </QBtn>
            <VnInputNumber
                v-model="daysAgo"
                :label="$t('globals.daysAgo')"
                dense
                :step="1"
                :decimal-places="0"
                @update:model-value="filterByDaysAgo"
                debounce="500"
                :title="t('entry.preAccount.daysAgo')"
            />
        </template>
        <template #column-id="{ row }">
            <span class="link" @click.stop>
                {{ row.id }}
                <EntryDescriptorProxy :id="row.id" />
            </span>
        </template>
        <template #column-company="{ row }">
            <QBadge :color="row.color ?? 'transparent'" :label="row.company" />
        </template>
        <template #column-gestDocFk="{ row }">
            <span class="link" @click.stop="downloadFile(row.gestDocFk)">
                {{ row.gestDocFk }}
            </span>
        </template>
        <template #column-supplier="{ row }">
            <span class="link" @click.stop>
                {{ row.supplier }}
                <SupplierDescriptorProxy :id="row.supplierFk" />
            </span>
        </template>
        <template #column-invoiceInFk="{ row }">
            <span class="link" @click.stop>
                {{ row.invoiceInFk }}
                <InvoiceInDescriptorProxy :id="row.invoiceInFk" />
            </span>
        </template>
        <template #column-footer-amount>
            <div v-text="toCurrency(totalSelectedAmount)" />
            <div v-text="toCurrency(totalAmount)" />
        </template>
    </VnTable>
    <VnConfirm
        ref="updateDialog"
        :title="t('entry.preAccount.dialog.title')"
        :message="t('entry.preAccount.dialog.message')"
    >
        <template #customHTML v-if="hasDiferentDms">
            <p class="text-negative">
                {{ t('differentGestdoc') }}
            </p>
        </template>
        <template #actions>
            <QBtn
                data-cy="updateFileYes"
                :label="t('globals.yes')"
                color="primary"
                @click="updateFile"
                autofocus
                v-close-popup
            />
            <QBtn
                data-cy="updateFileNo"
                :label="t('globals.no')"
                color="primary"
                flat
                @click="uploadFile"
                v-close-popup
            />
            <QBtn :label="t('globals.cancel')" color="primary" flat v-close-popup />
        </template>
    </VnConfirm>
    <QDialog ref="uploadDialog">
        <VnDms
            model="dms"
            :form-initial-data="dmsData"
            url="Dms/uploadFile"
            @on-data-saved="afterUploadFile"
        />
    </QDialog>
</template>
<i18n>
en:
    IntraCommunity: Intra-community
    NonCommunity: Non-community
    CanaryIslands: Canary Islands
    differentGestdoc: The entries have different gestdoc
es:
    IntraCommunity: Intracomunitaria
    NonCommunity: Extracomunitaria
    CanaryIslands: Islas Canarias
    National: Nacional
    differentGestdoc: Las entradas tienen diferentes gestdoc
</i18n>
