<script setup>
import { useStateStore } from 'stores/useStateStore';
import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
import { onMounted, ref, computed } from 'vue';

import { useState } from 'src/composables/useState';

import FetchData from 'src/components/FetchData.vue';
import VnTable from 'src/components/VnTable/VnTable.vue';
import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
import FetchedTags from 'src/components/ui/FetchedTags.vue';
import VnColor from 'src/components/common/VnColor.vue';
import VnSelect from 'src/components/common/VnSelect.vue';
import ItemDescriptor from 'src/pages/Item/Card/ItemDescriptor.vue';
import axios from 'axios';
import VnSelectEnum from 'src/components/common/VnSelectEnum.vue';
import { checkEntryLock } from 'src/composables/checkEntryLock';
import VnRow from 'src/components/ui/VnRow.vue';
import VnInput from 'src/components/common/VnInput.vue';
import VnInputNumber from 'src/components/common/VnInputNumber.vue';

const $props = defineProps({
    id: {
        type: Number,
        default: null,
    },
    editableMode: {
        type: Boolean,
        default: true,
    },
    tableHeight: {
        type: String,
        default: null,
    },
});

const state = useState();
const user = state.getUser().fn();
const stateStore = useStateStore();
const { t } = useI18n();
const route = useRoute();
const selectedRows = ref([]);
const entityId = ref($props.id ?? route.params.id);
const entryBuysRef = ref();
const footerFetchDataRef = ref();
const footer = ref({});
const dialogRef = ref(false);
const newEntryRef = ref(null);
const columns = [
    {
        align: 'center',
        labelAbbreviation: 'NV',
        label: t('Ignore'),
        toolTip: t('Ignored for available'),
        name: 'isIgnored',
        component: 'checkbox',
        attrs: {
            toggleIndeterminate: false,
        },
        create: true,
        createOrder: 12,
        width: '25px',
    },
    {
        name: 'id',
        isId: true,
        visible: false,
        isEditable: false,
        columnFilter: false,
    },
    {
        align: 'center',
        label: 'Id',
        name: 'itemFk',
        component: 'number',
        isEditable: false,
        width: '35px',
    },
    {
        labelAbbreviation: '',
        label: 'Color',
        name: 'hex',
        columnSearch: false,
        isEditable: false,
        width: '9px',
        component: 'select',
        attrs: {
            url: 'Inks',
            fields: ['id', 'name'],
        },
    },
    {
        align: 'left',
        label: t('Article'),
        component: 'input',
        name: 'name',
        width: '85px',
        isEditable: false,
    },
    {
        align: 'center',
        label: t('Article'),
        name: 'itemFk',
        visible: false,
        create: true,
        createOrder: 0,
        columnFilter: false,
    },
    {
        align: 'center',
        labelAbbreviation: t('Siz.'),
        label: t('Size'),
        toolTip: t('Size'),
        component: 'number',
        name: 'size',
        width: '35px',
        isEditable: false,
        style: () => {
            return { color: 'var(--vn-label-color)' };
        },
    },
    {
        align: 'center',
        labelAbbreviation: t('Sti.'),
        label: t('Stickers'),
        toolTip: t('Printed Stickers/Stickers'),
        name: 'stickers',
        component: 'input',
        create: true,

        createOrder: 1,
        attrs: {
            positive: false,
        },
        cellEvent: {
            'update:modelValue': async (value, oldValue, row) => {
                row['quantity'] = value * row['packing'];
                row['amount'] = row['quantity'] * row['buyingValue'];
            },
        },
        width: '35px',
    },
    {
        align: 'center',
        label: t('Bucket'),
        name: 'packagingFk',
        component: 'select',
        attrs: {
            url: 'packagings',
            fields: ['id'],
            optionLabel: 'id',
            optionValue: 'id',
        },
        create: true,
        width: '40px',
    },
    {
        align: 'center',
        label: 'Kg',
        name: 'weight',
        component: 'number',
        create: true,
        width: '35px',
        format: (row) => parseFloat(row['weight']).toFixed(1),
    },
    {
        labelAbbreviation: 'P',
        label: 'Packing',
        toolTip: 'Packing',
        name: 'packing',
        component: 'number',
        create: true,
        cellEvent: {
            'update:modelValue': async (value, oldValue, row) => {
                const oldPacking = oldValue === 1 || oldValue === null ? 1 : oldValue;
                row['weight'] = (row['weight'] * value) / oldPacking;
                row['quantity'] = row['stickers'] * value;
                row['amount'] = row['quantity'] * row['buyingValue'];
            },
        },
        width: '30px',
        style: (row) => {
            if (row.groupingMode === 'grouping')
                return { color: 'var(--vn-label-color)' };
        },
    },
    {
        labelAbbreviation: 'GM',
        label: t('Grouping selector'),
        toolTip: t('Grouping selector'),
        name: 'groupingMode',
        component: 'toggle',
        attrs: {
            'toggle-indeterminate': true,
            trueValue: 'grouping',
            falseValue: 'packing',
            indeterminateValue: null,
        },
        size: 'xs',
        width: '25px',
        create: true,
        rightFilter: false,
        getIcon: (value) => {
            switch (value) {
                case 'grouping':
                    return 'toggle_on';
                case 'packing':
                    return 'toggle_off';
                default:
                    return 'minimize';
            }
        },
    },
    {
        labelAbbreviation: 'G',
        label: 'Grouping',
        toolTip: 'Grouping',
        name: 'grouping',
        component: 'number',
        width: '30px',
        create: true,
        style: (row) => {
            if (row.groupingMode === 'packing') return { color: 'var(--vn-label-color)' };
        },
    },
    {
        align: 'center',
        label: t('Quantity'),
        name: 'quantity',
        component: 'number',
        attrs: {
            positive: false,
        },
        cellEvent: {
            'update:modelValue': async (value, oldValue, row) => {
                row['amount'] = value * row['buyingValue'];
            },
        },
        width: '45px',
        create: true,
        createOrder: 3,
        style: getQuantityStyle,
    },
    {
        align: 'center',
        labelAbbreviation: t('Cost'),
        label: t('Buying value'),
        toolTip: t('Buying value'),
        name: 'buyingValue',
        create: true,
        createOrder: 2,
        component: 'number',
        attrs: {
            positive: false,
            decimalPlaces: 3,
        },
        cellEvent: {
            'update:modelValue': async (value, oldValue, row) => {
                row['amount'] = row['quantity'] * value;
            },
        },
        width: '45px',
        format: (row) => parseFloat(row['buyingValue']).toFixed(3),
    },
    {
        align: 'center',
        label: t('Amount'),
        name: 'amount',
        width: '75px',
        component: 'number',
        attrs: {
            positive: false,
        },
        isEditable: false,
        format: (row) => parseFloat(row['amount']).toFixed(2),
        style: getAmountStyle,
    },
    {
        align: 'center',
        labelAbbreviation: t('Pack.'),
        label: t('Package'),
        toolTip: t('Package'),
        name: 'price2',
        component: 'number',
        createAttrs: {
            disable: true,
        },
        width: '35px',
        create: true,
        format: (row) => parseFloat(row['price2']).toFixed(2),
    },
    {
        align: 'center',
        label: t('Box'),
        name: 'price3',
        component: 'number',
        createAttrs: {
            disable: true,
        },
        cellEvent: {
            'update:modelValue': async (value, oldValue, row) => {
                row['price2'] = row['price2'] * (value / oldValue);
            },
        },
        width: '35px',
        create: true,
        format: (row) => parseFloat(row['price3']).toFixed(2),
    },
    {
        align: 'center',
        labelAbbreviation: 'CM',
        label: t('Check min price'),
        toolTip: t('Check min price'),
        name: 'hasMinPrice',
        attrs: {
            toggleIndeterminate: false,
        },
        component: 'checkbox',
        width: '25px',
    },
    {
        align: 'center',
        labelAbbreviation: 'Min.',
        label: t('Minimum price'),
        toolTip: t('Minimum price'),
        name: 'minPrice',
        component: 'number',
        width: '35px',
        style: (row) => {
            if (!row?.hasMinPrice) return { color: 'var(--vn-label-color)' };
        },
        format: (row) => parseFloat(row['minPrice']).toFixed(2),
    },
    {
        align: 'center',
        labelAbbreviation: t('P.Sen'),
        label: t('Packing sent'),
        toolTip: t('Packing sent'),
        name: 'packingOut',
        component: 'number',
        isEditable: false,
        width: '40px',
        style: () => {
            return { color: 'var(--vn-label-color)' };
        },
    },
    {
        align: 'center',
        labelAbbreviation: t('Com.'),
        label: t('Comment'),
        toolTip: t('Comment'),
        name: 'comment',
        component: 'input',
        isEditable: false,
        width: '50px',
    },
    {
        align: 'center',
        labelAbbreviation: 'Prod.',
        label: t('Producer'),
        toolTip: t('Producer'),
        name: 'subName',
        isEditable: false,
        width: '45px',
        style: () => {
            return { color: 'var(--vn-label-color)' };
        },
    },
    {
        align: 'center',
        label: t('Tags'),
        name: 'tags',
        width: '125px',
        columnSearch: false,
    },
    {
        align: 'center',
        labelAbbreviation: 'Comp.',
        label: t('Company'),
        toolTip: t('Company'),
        name: 'company_name',
        component: 'input',
        isEditable: false,
        width: '35px',
        style: () => {
            return { color: 'var(--vn-label-color)' };
        },
    },
];
const buyerFk = ref(null);
const itemTypeFk = ref(null);
const inkFk = ref(null);
const tag1 = ref(null);
const tag2 = ref(null);
const tag1Filter = ref(null);
const tag2Filter = ref(null);
const filter = computed(() => {
    const where = {};
    where.workerFk = buyerFk.value;
    where.itemTypeFk = itemTypeFk.value;
    where.inkFk = inkFk.value;
    where.tag1 = tag1.value;
    where.tag2 = tag2.value;

    return { where };
});

function getQuantityStyle(row) {
    if (row?.quantity !== row?.stickers * row?.packing)
        return { color: 'var(--q-negative)' };
}
function getAmountStyle(row) {
    if (row?.isChecked) return { color: 'var(--q-positive)' };
    return { color: 'var(--vn-label-color)' };
}

async function beforeSave(data, getChanges) {
    try {
        const changes = data.updates;
        if (!changes) return data;
        const patchPromises = [];

        for (const change of changes) {
            let patchData = {};

            if ('hasMinPrice' in change.data) {
                patchData.hasMinPrice = change.data?.hasMinPrice;
                delete change.data.hasMinPrice;
            }
            if ('minPrice' in change.data) {
                patchData.minPrice = change.data?.minPrice;
                delete change.data.minPrice;
            }

            if (Object.keys(patchData).length > 0) {
                const promise = axios
                    .get('Buys/findOne', {
                        params: {
                            filter: {
                                fields: ['itemFk'],
                                where: { id: change.where.id },
                            },
                        },
                    })
                    .then((buy) => {
                        return axios.patch(`Items/${buy.data.itemFk}`, patchData);
                    })
                    .catch((error) => {
                        console.error('Error processing change: ', change, error);
                    });

                patchPromises.push(promise);
            }
        }

        await Promise.all(patchPromises);

        data.updates = changes.filter((change) => Object.keys(change.data).length > 0);

        return data;
    } catch (error) {
        console.error('Error in beforeSave:', error);
        throw error;
    }
}

function invertQuantitySign(rows, sign) {
    for (const row of rows) {
        if (sign > 0) row.quantity = Math.abs(row.quantity);
        else if (row.quantity > 0) row.quantity = -row.quantity;
    }
}
function setIsChecked(rows, value) {
    for (const row of rows) {
        row.isChecked = value;
    }
    footerFetchDataRef.value.fetch();
}

async function setBuyUltimate(itemFk, data) {
    if (!itemFk) return;
    const buyUltimate = await axios.get(`Entries/getBuyUltimate`, {
        params: {
            itemFk,
            warehouseFk: user.warehouseFk,
            date: Date.vnNew(),
        },
    });
    const buyUltimateData = buyUltimate.data[0];
    if (!buyUltimateData) return;

    const allowedKeys = columns
        .filter((col) => col.create === true)
        .map((col) => col.name);

    allowedKeys.forEach((key) => {
        if (buyUltimateData?.hasOwnProperty(key) && key !== 'entryFk') {
            if (!['stickers', 'quantity'].includes(key)) data[key] = buyUltimateData[key];
        }
    });
}

async function transferBuys(rows, newEntry) {
    if (!newEntry) return;

    const promises = rows.map((row) => {
        return axios.patch('Buys', { id: row.id, entryFk: newEntry });
    });

    await Promise.all(promises);

    await axios.post(`Entries/${newEntry}/recalcEntryPrices`);
    await axios.post(`Entries/${entityId.value}/recalcEntryPrices`);

    entryBuysRef.value.reload();
    newEntryRef.value = null;
    dialogRef.value = false;
}

onMounted(() => {
    stateStore.rightDrawer = false;
    if ($props.editableMode) checkEntryLock(entityId.value, user.id);
});
</script>
<template>
    <Teleport to="#st-data" v-if="stateStore?.isSubToolbarShown() && editableMode">
        <QBtnGroup push style="column-gap: 1px">
            <QBtnDropdown
                label="+/-"
                color="primary"
                flat
                :title="t('Invert quantity value')"
                :disable="!selectedRows.length"
                data-cy="change-quantity-sign"
            >
                <QList>
                    <QItem>
                        <QItemSection>
                            <QBtn
                                flat
                                @click="invertQuantitySign(selectedRows, -1)"
                                data-cy="set-negative-quantity"
                            >
                                <span style="font-size: large">-</span>
                            </QBtn>
                        </QItemSection>
                    </QItem>
                    <QItem>
                        <QItemSection>
                            <QBtn
                                flat
                                @click="invertQuantitySign(selectedRows, 1)"
                                data-cy="set-positive-quantity"
                            >
                                <span style="font-size: large">+</span>
                            </QBtn>
                        </QItemSection>
                    </QItem>
                </QList>
            </QBtnDropdown>
            <QBtnDropdown
                icon="price_check"
                color="primary"
                flat
                :title="t('Check buy amount')"
                :disable="!selectedRows.length"
                data-cy="check-buy-amount"
            >
                <QList>
                    <QItem>
                        <QItemSection>
                            <QBtn
                                size="sm"
                                icon="check"
                                flat
                                @click="setIsChecked(selectedRows, true)"
                                data-cy="check-amount"
                            />
                        </QItemSection>
                    </QItem>
                    <QItem>
                        <QItemSection>
                            <QBtn
                                size="sm"
                                icon="close"
                                flat
                                @click="setIsChecked(selectedRows, false)"
                                data-cy="uncheck-amount"
                            />
                        </QItemSection>
                    </QItem>
                </QList>
            </QBtnDropdown>
            <QBtn
                icon="move_group"
                color="primary"
                :title="t('Transfer buys')"
                data-cy="transferBuys"
                flat
                @click="dialogRef = true"
                :disable="!selectedRows.length"
            />
            <QDialog v-model="dialogRef">
                <QCard>
                    <QCardSection>
                        <span>{{ t('Transfer buys') }}</span>
                    </QCardSection>
                    <QCardSection>
                        <VnInputNumber
                            v-model="newEntryRef"
                            :label="t('Entry')"
                            type="number"
                            data-cy="entryDestinyInput"
                        />
                    </QCardSection>
                    <QCardSection>
                        <QCardActions>
                            <QBtn
                                label="Cancel"
                                flat
                                color="primary"
                                @click="dialogRef = false"
                            />
                            <QBtn
                                label="Transfer"
                                data-cy="transferBuysBtn"
                                flat
                                color="primary"
                                @click="transferBuys(selectedRows, newEntryRef)"
                            />
                        </QCardActions>
                    </QCardSection>
                </QCard>
            </QDialog>
        </QBtnGroup>
    </Teleport>
    <FetchData
        ref="footerFetchDataRef"
        :url="`Entries/${entityId}/getBuyList`"
        :params="{ groupBy: 'GROUP BY b.entryFk' }"
        @on-fetch="(data) => (footer = data[0])"
        auto-load
    />
    <VnTable
        ref="entryBuysRef"
        data-key="EntryBuys"
        :url="`Entries/${entityId}/getBuyList`"
        search-url="EntryBuys"
        save-url="Buys/crud"
        :filter="editableMode ? filter : {}"
        :disable-option="{ card: true }"
        v-model:selected="selectedRows"
        @on-fetch="() => footerFetchDataRef.fetch()"
        :table="
            editableMode
                ? {
                      'row-key': 'id',
                      selection: 'multiple',
                  }
                : {}
        "
        :create="
            editableMode
                ? {
                      urlCreate: 'Buys',
                      title: t('Create buy'),
                      onDataSaved: () => {
                          entryBuysRef.reload();
                      },
                      formInitialData: { entryFk: entityId, isIgnored: false },
                      showSaveAndContinueBtn: true,
                  }
                : null
        "
        :create-complement="{
            isFullWidth: true,
            containerStyle: {
                display: 'flex',
                gap: '16px',
                position: 'relative',
            },
            columnGridStyle: {
                'max-width': '50%',
                'margin-right': '5%',
                flex: 1,
            },
            previousStyle: {
                'max-width': '30%',
                height: '500px',
            },
            displayPrevious: true,
        }"
        :is-editable="editableMode"
        :without-header="!editableMode"
        :with-filters="editableMode"
        :right-search="false"
        :row-click="false"
        :columns="columns"
        :beforeSaveFn="beforeSave"
        class="buyList"
        :table-height="$props.tableHeight ?? '84vh'"
        auto-load
        footer
        data-cy="entry-buys"
        overlay
    >
        <template #top-left>
            <VnRow>
                <VnSelect
                    :label="t('Buyer')"
                    v-model="buyerFk"
                    url="TicketRequests/getItemTypeWorker"
                    :fields="['id', 'nickname']"
                    option-label="nickname"
                    sort-by="nickname ASC"
                    :use-like="false"
                />
                <VnSelect
                    :label="t('Family')"
                    v-model="itemTypeFk"
                    url="ItemTypes"
                    :fields="['id', 'name']"
                    option-label="name"
                    sort-by="name ASC"
                />
                <VnSelect
                    :label="t('Color')"
                    v-model="inkFk"
                    url="Inks"
                    :fields="['id', 'name']"
                    option-label="name"
                    sort-by="name ASC"
                />
                <VnInput
                    v-model="tag1Filter"
                    :label="t('Tag')"
                    @keyup.enter="tag1 = tag1Filter"
                    @remove="tag1 = null"
                />
                <VnInput
                    v-model="tag2Filter"
                    :label="t('Tag')"
                    @keyup.enter="tag2 = tag2Filter"
                    @remove="tag2 = null"
                />
            </VnRow>
        </template>
        <template #column-hex="{ row }">
            <VnColor :colors="row?.hexJson" style="height: 100%; min-width: 2000px" />
        </template>
        <template #column-name="{ row }">
            <span class="link">
                {{ row?.name }}
                <ItemDescriptorProxy :id="row?.itemFk" />
            </span>
        </template>
        <template #column-tags="{ row }">
            <FetchedTags :item="row" :columns="3" />
        </template>
        <template #column-stickers="{ row }">
            <span :class="editableMode ? 'editable-text' : ''">
                <span style="color: var(--vn-label-color)">
                    {{ row.printedStickers }}
                </span>
                <span>/{{ row.stickers }}</span>
            </span>
        </template>
        <template #column-footer-stickers>
            <div>
                <span style="color: var(--vn-label-color)">
                    {{ footer?.printedStickers }}</span
                >
                <span>/</span>
                <span data-cy="footer-stickers">{{ footer?.stickers }}</span>
            </div>
        </template>
        <template #column-footer-weight>
            <span class="q-pr-xs">{{ footer?.weight }}</span>
        </template>
        <template #column-footer-quantity>
            <span :style="getQuantityStyle(footer)" data-cy="footer-quantity">
                {{ footer?.quantity }}
            </span>
        </template>
        <template #column-footer-amount>
            <span data-cy="footer-amount">{{ footer?.amount }} / </span>
            <span style="color: var(--q-positive)">{{ footer?.checkedAmount }}</span>
        </template>
        <template #column-create-itemFk="{ data }">
            <VnSelect
                url="Items/search"
                v-model="data.itemFk"
                :label="t('Article')"
                :fields="['id', 'name', 'size', 'producerName']"
                :filter-options="['id', 'name', 'size', 'producerName']"
                option-label="name"
                option-value="id"
                @update:modelValue="
                    async (value) => {
                        await setBuyUltimate(value, data);
                    }
                "
                :required="true"
                data-cy="itemFk-create-popup"
                sort-by="nickname DESC"
            >
                <template #option="scope">
                    <QItem v-bind="scope.itemProps">
                        <QItemSection>
                            <QItemLabel>
                                {{ scope.opt.name }}
                            </QItemLabel>
                            <QItemLabel caption>
                                #{{ scope.opt.id }}, {{ scope.opt?.size }},
                                {{ scope.opt?.producerName }}
                            </QItemLabel>
                        </QItemSection>
                    </QItem>
                </template>
            </VnSelect>
        </template>
        <template #column-create-groupingMode="{ data }">
            <VnSelectEnum
                :label="t('Grouping mode')"
                v-model="data.groupingMode"
                schema="vn"
                table="buy"
                column="groupingMode"
                option-value="groupingMode"
                option-label="groupingMode"
            />
        </template>
        <template #previous-create-dialog="{ data }">
            <div
                style="position: absolute"
                :class="{ 'centered-container': !data.itemFk }"
            >
                <ItemDescriptor :id="data.itemFk" v-if="data.itemFk" />
                <div v-else>
                    <span>{{ t('globals.noData') }}</span>
                </div>
            </div>
        </template>
    </VnTable>
</template>
<i18n>
es:
    Buyer: Comprador
    Family: Familia
    Article: Artículo
    Siz.: Med.
    Size: Medida
    Sti.: Eti.
    Bucket: Cubo
    Quantity: Cantidad
    Amount: Importe
    Pack.: Paq.
    Package: Paquete
    Box: Caja
    P.Sen: P.Env
    Packing sent: Packing envíos
    Com.: Ref.
    Comment: Referencia
    Minimum price: Precio mínimo
    Stickers: Etiquetas
    Printed Stickers/Stickers: Etiquetas impresas/Etiquetas
    Cost: Cost.
    Buying value: Coste
    Producer: Productor
    Company: Compañia
    Tags: Etiquetas
    Grouping mode: Modo de agrupación
    C.min: P.min
    Ignore: Ignorar
    Ignored for available: Ignorado para disponible
    Grouping selector: Selector de grouping
    Check min price: Marcar precio mínimo
    Create buy: Crear compra
    Invert quantity value: Invertir valor de cantidad
    Check buy amount: Marcar como correcta la cantidad de compra
    Transfer buys: Transferir compras
    Entry: Entrada
</i18n>
<style lang="scss" scoped>
.centered-container {
    display: flex;
    justify-content: center;
    align-items: center;
    position: absolute;
    width: 40%;
    height: 100%;
}
</style>
