<script setup>
import { onMounted, ref, onUnmounted, nextTick, computed } from 'vue';
import { useI18n } from 'vue-i18n';
import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
import FetchedTags from 'components/ui/FetchedTags.vue';
import VnInput from 'src/components/common/VnInput.vue';
import VnSelect from 'src/components/common/VnSelect.vue';
import VnInputDate from 'src/components/common/VnInputDate.vue';
import EditTableCellValueForm from 'src/components/EditTableCellValueForm.vue';
import ItemFixedPriceFilter from './ItemFixedPriceFilter.vue';
import { useQuasar } from 'quasar';
import ItemDescriptorProxy from './Card/ItemDescriptorProxy.vue';
import { tMobile } from 'src/composables/tMobile';
import VnConfirm from 'components/ui/VnConfirm.vue';
import FetchData from 'src/components/FetchData.vue';
import { useStateStore } from 'stores/useStateStore';
import { toDate } from 'src/filters';
import { useVnConfirm } from 'composables/useVnConfirm';
import { useState } from 'src/composables/useState';
import useNotify from 'src/composables/useNotify.js';
import axios from 'axios';
import { isLower, isBigger } from 'src/filters/date.js';
import RightMenu from 'src/components/common/RightMenu.vue';
import VnTable from 'src/components/VnTable/VnTable.vue';
import { QCheckbox } from 'quasar';

const quasar = useQuasar();
const stateStore = useStateStore();
const { t } = useI18n();
const { openConfirmationModal } = useVnConfirm();
const state = useState();
const { notify } = useNotify();
const tableRef = ref();
const editTableCellDialogRef = ref(null);
const user = state.getUser();
const fixedPrices = ref([]);
const warehousesOptions = ref([]);
const rowsSelected = ref([]);
const itemFixedPriceFilterRef = ref();

onMounted(async () => {
    stateStore.rightDrawer = true;
});
onUnmounted(() => (stateStore.rightDrawer = false));

const defaultColumnAttrs = {
    align: 'left',
    sortable: true,
};
const columns = computed(() => [
    {
        label: t('item.fixedPrice.itemFk'),
        name: 'itemFk',
        ...defaultColumnAttrs,
        isId: true,
        columnField: {
            component: 'input',
            type: 'number',
        },
        columnClass: 'shrink',
    },
    {
        label: t('globals.name'),
        name: 'name',
        ...defaultColumnAttrs,
        create: true,
    },
    {
        label: t('item.fixedPrice.groupingPrice'),
        field: 'rate2',
        name: 'rate2',
        ...defaultColumnAttrs,
        component: 'input',
        type: 'number',
    },
    {
        label: t('item.fixedPrice.packingPrice'),
        field: 'rate3',
        name: 'rate3',
        ...defaultColumnAttrs,
        component: 'input',
        type: 'number',
    },

    {
        label: t('item.fixedPrice.minPrice'),
        field: 'minPrice',
        name: 'minPrice',
        ...defaultColumnAttrs,
        component: 'input',
        type: 'number',
    },
    {
        label: t('item.fixedPrice.started'),
        field: 'started',
        name: 'started',
        format: ({ started }) => toDate(started),
        ...defaultColumnAttrs,
        columnField: {
            component: 'date',
            class: 'shrink',
        },
        columnFilter: {
            component: 'date',
        },
        columnClass: 'expand',
    },
    {
        label: t('item.fixedPrice.ended'),
        field: 'ended',
        name: 'ended',
        ...defaultColumnAttrs,
        columnField: {
            component: 'date',
            class: 'shrink',
        },
        columnFilter: {
            component: 'date',
        },
        columnClass: 'expand',
        format: (row) => toDate(row.ended),
    },

    {
        label: t('globals.warehouse'),
        field: 'warehouseFk',
        name: 'warehouseFk',
        ...defaultColumnAttrs,
        columnClass: 'shrink',
        component: 'select',
        options: warehousesOptions,
        columnFilter: {
            name: 'warehouseFk',
            inWhere: true,
            component: 'select',
            attrs: {
                options: warehousesOptions,
                'option-label': 'name',
                'option-value': 'id',
            },
        },
    },
    {
        align: 'right',
        name: 'tableActions',
        actions: [
            {
                title: t('delete'),
                icon: 'delete',
                action: (row) => confirmRemove(row),
                isPrimary: true,
            },
        ],
    },
]);

const editTableFieldsOptions = [
    {
        field: 'rate2',
        label: t('item.fixedPrice.groupingPrice'),
        component: 'input',
        attrs: {
            type: 'number',
        },
    },
    {
        field: 'rate3',
        label: t('item.fixedPrice.packingPrice'),
        component: 'input',
        attrs: {
            type: 'number',
        },
    },
    {
        field: 'minPrice',
        label: t('item.fixedPrice.minPrice'),
        component: 'input',
        attrs: {
            type: 'number',
        },
    },
    {
        field: 'started',
        label: t('item.fixedPrice.started'),
        component: 'date',
    },
    {
        field: 'ended',
        label: t('item.fixedPrice.ended'),
        component: 'date',
    },
    {
        field: 'warehouseFk',
        label: t('globals.warehouse'),
        component: 'select',
        attrs: {
            options: [],
            'option-label': 'name',
            'option-value': 'id',
        },
    },
];
const getRowUpdateInputEvents = (props, resetMinPrice, inputType = 'text') => {
    return inputType === 'text'
        ? {
              'keyup.enter': () => upsertPrice(props, resetMinPrice),
              blur: () => upsertPrice(props, resetMinPrice),
          }
        : { 'update:modelValue': () => upsertPrice(props, resetMinPrice) };
};

const updateMinPrice = async (value, props) => {
    props.row.hasMinPrice = value;
    await upsertPrice({
        row: props.row,
        col: { field: 'hasMinPrice' },
        rowIndex: props.rowIndex,
    });
};

const validations = ({ row }) => {
    const requiredFields = [
        'itemFk',
        'started',
        'ended',
        'rate2',
        'rate3',
        'warehouseFk',
    ];
    const isValid = requiredFields.every(
        (field) => row[field] !== null && row[field] !== undefined
    );
    return isValid;
};
const upsertPrice = async (props, resetMinPrice = false) => {
    const isValid = validations({ ...props });
    if (!isValid) {
        return;
    }
    const { row } = props;
    const changes = tableRef.value.CrudModelRef.getChanges();
    if (changes?.updates?.length > 0) {
        if (resetMinPrice) row.hasMinPrice = 0;
    }
    if (!changes.updates && !changes.creates) return;
    const data = await upsertFixedPrice(row);
    Object.assign(tableRef.value.CrudModelRef.formData[props.rowIndex], data);
    notify(t('globals.dataSaved'), 'positive');
    tableRef.value.reload();
};

async function upsertFixedPrice(row) {
    const { data } = await axios.patch('FixedPrices/upsertFixedPrice', row);
    data.hasMinPrice = data.hasMinPrice ? 1 : 0;
    return data;
}

function checkLastVisibleRow() {
    let lastVisibleRow = null;

    getTableRows().forEach((row, index) => {
        const rect = row.getBoundingClientRect();
        if (rect.top >= 0 && rect.bottom <= window.innerHeight) {
            lastVisibleRow = index;
        }
    });

    return lastVisibleRow;
}

const addRow = (original = null) => {
    let copy = null;
    const today = Date.vnNew();
    const millisecsInDay = 86400000;
    const daysInWeek = 7;
    const nextWeek = new Date(today.getTime() + daysInWeek * millisecsInDay);

    copy = {
        id: 0,
        started: today,
        ended: nextWeek,
        hasMinPrice: 0,
        $index: 0,
    };
    return { original, copy };
};

const getTableRows = () =>
    document.getElementsByClassName('q-table')[0].querySelectorAll('tr.cursor-pointer');

function highlightNewRow({ $index: index }) {
    const row = getTableRows()[index];
    if (row) {
        row.classList.add('highlight');
        setTimeout(() => {
            row.classList.remove('highlight');
        }, 3000);
    }
}
const openEditTableCellDialog = () => {
    editTableCellDialogRef.value.show();
};

const onEditCellDataSaved = async () => {
    rowsSelected.value = [];
    tableRef.value.reload();
};

const removeFuturePrice = async () => {
    rowsSelected.value.forEach(({ id }) => {
        const rowIndex = fixedPrices.value.findIndex(({ id }) => id === id);
        removePrice(id, rowIndex);
    });
};

function confirmRemove(item, isFuture) {
    const promise = async () =>
        isFuture ? removeFuturePrice(item.id) : removePrice(item.id);
    quasar.dialog({
        component: VnConfirm,
        componentProps: {
            title: t('globals.rowWillBeRemoved'),
            message: t('globals.confirmDeletion'),
            promise,
        },
    });
}

const removePrice = async (id) => {
    await axios.delete(`FixedPrices/${id}`);
    notify(t('globals.dataSaved'), 'positive');
    tableRef.value.reload({});
};
const dateStyle = (date) =>
    date
        ? {
              'bg-color': 'warning',
              'is-outlined': true,
          }
        : {};

function handleOnDataSave({ CrudModelRef }) {
    const { original, copy } = addRow(CrudModelRef.formData[checkLastVisibleRow()]);
    if (original) {
        CrudModelRef.formData.splice(original?.$index ?? 0, 0, copy);
    } else {
        CrudModelRef.insert(copy);
    }
    nextTick(() => {
        highlightNewRow(original ?? { $index: 0 });
    });
}
</script>

<template>
    <FetchData
        @on-fetch="(data) => (warehousesOptions = data)"
        auto-load
        url="Warehouses"
        :filter="{ fields: ['id', 'name'], order: 'name ASC' }"
    />
    <RightMenu>
        <template #right-panel>
            <ItemFixedPriceFilter
                data-key="ItemFixedPrices"
                ref="itemFixedPriceFilterRef"
            />
        </template>
    </RightMenu>
    <VnSubToolbar>
        <template #st-data>
            <QBtn
                v-if="rowsSelected.length"
                @click="openEditTableCellDialog()"
                color="primary"
                icon="edit"
            >
                <QTooltip>
                    {{ t('Edit fixed price(s)') }}
                </QTooltip>
            </QBtn>
            <QBtn
                :label="tMobile('globals.remove')"
                color="primary"
                icon="delete"
                flat
                @click="(row) => confirmRemove(row, true)"
                :title="t('globals.remove')"
                v-if="rowsSelected.length"
            />
        </template>
    </VnSubToolbar>
    <VnTable
        :default-remove="false"
        :default-reset="false"
        :default-save="false"
        data-key="ItemFixedPrices"
        url="FixedPrices/filter"
        :order="['name DESC', 'itemFk DESC']"
        save-url="FixedPrices/crud"
        ref="tableRef"
        dense
        :filter="{
            where: {
                warehouseFk: user.warehouseFk,
            },
        }"
        :columns="columns"
        default-mode="table"
        auto-load
        :is-editable="true"
        :right-search="false"
        :table="{
            'row-key': 'id',
            selection: 'multiple',
        }"
        :use-model="true"
        v-model:selected="rowsSelected"
        :create-as-dialog="false"
        :create="{
            onDataSaved: handleOnDataSave,
        }"
        :disable-option="{ card: true }"
    >
        <template #header-selection="scope">
            <QCheckbox v-model="scope.selected" />
        </template>
        <template #body-selection="scope">
            {{ scope }}
            <QCheckbox flat v-model="scope.selected" />
        </template>

        <template #column-itemFk="props">
            <VnSelect
                style="max-width: 100px"
                url="Items/withName"
                hide-selected
                option-label="id"
                option-value="id"
                v-model="props.row.itemFk"
                v-on="getRowUpdateInputEvents(props, true, 'select')"
            >
                <template #option="scope">
                    <QItem v-bind="scope.itemProps">
                        <QItemSection>
                            <QItemLabel> #{{ scope.opt?.id }} </QItemLabel>
                            <QItemLabel caption>{{ scope.opt?.name }}</QItemLabel>
                        </QItemSection>
                    </QItem>
                </template>
            </VnSelect>
        </template>
        <template #column-name="{ row }">
            <span class="link">
                {{ row.name }}
            </span>
            <span class="subName">{{ row.subName }}</span>
            <ItemDescriptorProxy :id="row.itemFk" />
            <FetchedTags :item="row" :columns="3" />
        </template>
        <template #column-rate2="props">
            <QTd class="col">
                <VnInput
                    type="currency"
                    style="width: 75px"
                    v-model.number="props.row.rate2"
                    v-on="getRowUpdateInputEvents(props)"
                >
                    <template #append>€</template>
                </VnInput>
            </QTd>
        </template>
        <template #column-rate3="props">
            <QTd class="col">
                <VnInput
                    style="width: 75px"
                    type="currency"
                    v-model.number="props.row.rate3"
                    v-on="getRowUpdateInputEvents(props)"
                >
                    <template #append>€</template>
                </VnInput>
            </QTd>
        </template>
        <template #column-minPrice="props">
            <QTd class="col">
                <div class="row" style="align-items: center">
                    <QCheckbox
                        :model-value="props.row.hasMinPrice"
                        @update:model-value="updateMinPrice($event, props)"
                        :false-value="0"
                        :true-value="1"
                        :toggle-indeterminate="false"
                    />
                    <VnInput
                        class="col"
                        type="currency"
                        mask="###.##"
                        :disable="props.row.hasMinPrice === 0"
                        v-model.number="props.row.minPrice"
                        v-on="getRowUpdateInputEvents(props)"
                    >
                        <template #append>€</template>
                    </VnInput>
                </div>
            </QTd>
        </template>
        <template #column-started="props">
            <VnInputDate
                class="vnInputDate"
                :show-event="true"
                v-model="props.row.started"
                v-on="getRowUpdateInputEvents(props, false, 'date')"
                v-bind="dateStyle(isBigger(props.row.started))"
            />
        </template>
        <template #column-ended="props">
            <VnInputDate
                class="vnInputDate"
                :show-event="true"
                v-model="props.row.ended"
                v-on="getRowUpdateInputEvents(props, false, 'date')"
                v-bind="dateStyle(isLower(props.row.ended))"
            />
        </template>
        <template #column-warehouseFk="props">
            <QTd class="col">
                <VnSelect
                    style="max-width: 150px"
                    :options="warehousesOptions"
                    hide-selected
                    option-label="name"
                    option-value="id"
                    v-model="props.row.warehouseFk"
                    v-on="getRowUpdateInputEvents(props, false, 'select')"
                />
            </QTd>
        </template>
        <template #column-deleteAction="{ row, rowIndex }">
            <QIcon
                name="delete"
                size="sm"
                class="cursor-pointer fill-icon-on-hover"
                color="primary"
                @click.stop="
                    openConfirmationModal(
                        t('globals.rowWillBeRemoved'),
                        t('Do you want to clone this item?'),
                        () => removePrice(row.id, rowIndex)
                    )
                "
            >
                <QTooltip class="text-no-wrap">
                    {{ t('globals.delete') }}
                </QTooltip>
            </QIcon>
        </template>
    </VnTable>

    <QDialog ref="editTableCellDialogRef">
        <EditTableCellValueForm
            edit-url="FixedPrices/editFixedPrice"
            :rows="rowsSelected"
            :fields-options="editTableFieldsOptions"
            @on-data-saved="onEditCellDataSaved()"
        />
    </QDialog>
</template>
<style lang="scss">
.q-table th,
.q-table td {
    padding-inline: 5px !important;
}
.q-table tr td {
    font-size: 10pt;
    border-top: none;
    border-collapse: collapse;
}
.q-table tbody td {
    max-width: none;
    .q-td.col {
        & .vnInputDate {
            min-width: 90px;
        }
        & div.row {
            & .q-checkbox {
                & .q-checkbox__inner {
                    position: relative !important;
                    &.q-checkbox__inner--truthy {
                        color: var(--q-primary);
                    }
                }
            }
        }
    }
}
.q-field__after,
.q-field__append {
    padding: 0;
}

tbody tr.highlight .q-td {
    animation: highlight-animation 4s ease-in-out;
}
@keyframes highlight-animation {
    0% {
        background-color: $primary-light;
    }
    100% {
        background-color: transparent;
    }
}
.subName {
    margin-left: 5%;
    font-size: 0.75rem;
    text-transform: uppercase;
    color: var(--vn-label-color);
}
</style>
<i18n>
es:
    Add fixed price: Añadir precio fijado
    Edit fixed price(s): Editar precio(s) fijado(s)
</i18n>