<script setup>
import { onBeforeMount, reactive, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import { useRoute } from 'vue-router';
import axios from 'axios';
import { useDialogPluginComponent } from 'quasar';

import { getClientRisk } from '../composables/getClientRisk';
import { usePrintService } from 'composables/usePrintService';
import useNotify from 'src/composables/useNotify.js';

import FormModelPopup from 'components/FormModelPopup.vue';
import FetchData from 'components/FetchData.vue';
import VnRow from 'components/ui/VnRow.vue';
import VnInputDate from 'components/common/VnInputDate.vue';
import VnInputNumber from 'components/common/VnInputNumber.vue';
import VnSelect from 'src/components/common/VnSelect.vue';
import VnInput from 'src/components/common/VnInput.vue';
import VnAccountNumber from 'src/components/common/VnAccountNumber.vue';

const { t } = useI18n();
const route = useRoute();
const { notify } = useNotify();
const { sendEmail, openReport } = usePrintService();
const { dialogRef } = useDialogPluginComponent();

const $props = defineProps({
    companyId: {
        type: Number,
        required: true,
    },
    totalCredit: {
        type: Number,
        required: true,
    },
    promise: {
        type: Function,
        default: null,
    },
});

const closeButton = ref(null);
const urlCreate = ref([]);
const companyOptions = ref([]);
const bankOptions = ref([]);
const clientFindOne = ref([]);
const viewReceipt = ref();
const shouldSendEmail = ref(false);
const maxAmount = ref();
const accountingType = ref({});
const isCash = ref(false);
const formModelRef = ref(false);
const amountToReturn = ref();
const filterBanks = {
    fields: ['id', 'bank', 'accountingTypeFk'],
    include: { relation: 'accountingType' },
    order: 'id',
    limit: 30,
};

const filterClientFindOne = {
    fields: ['email'],
    where: {
        id: route.params.id,
    },
};

const initialData = reactive({
    amountPaid: $props.totalCredit,
    clientFk: route.params.id,
    companyFk: $props.companyId,
    email: clientFindOne.value.email,
});

onBeforeMount(() => {
    urlCreate.value = `Clients/${route.params.id}/createReceipt`;
});

function setPaymentType(data, accounting) {
    data.bankFk = accounting.id;
    if (!accounting) return;
    accountingType.value = accounting.accountingType;
    data.description = [];
    data.payed = Date.vnNew();
    isCash.value = accountingType.value.code == 'cash';
    viewReceipt.value = isCash.value;
    if (accountingType.value.daysInFuture)
        data.payed.setDate(data.payed.getDate() + accountingType.value.daysInFuture);
    maxAmount.value = accountingType.value && accountingType.value.maxAmount;
    if (accountingType.value.code == 'compensation') return (data.description = '');

    let descriptions = [];
    if (accountingType.value.receiptDescription)
        descriptions.push(accountingType.value.receiptDescription);
    if (data.description > 0) descriptions.push(data.description);
    data.description = descriptions.join(', ');
}

const calculateFromAmount = (event) => {
    initialData.amountToReturn =
        parseFloat(initialData.deliveredAmount) + parseFloat(event) * -1;
};

const calculateFromDeliveredAmount = (event) => {
    amountToReturn.value = event - initialData.amountPaid;
};

function onBeforeSave(data) {
    const exceededAmount = data.amountPaid > maxAmount.value;
    if (isCash.value && exceededAmount)
        return notify(t('Amount exceeded', { maxAmount: maxAmount.value }), 'negative');

    if (isCash.value && shouldSendEmail.value && !data.email)
        return notify(t('There is no assigned email for this client'), 'negative');

    return data;
}

async function onDataSaved(formData, { id }) {
    try {
        if (shouldSendEmail.value && isCash.value)
            await sendEmail(`Receipts/${id}/receipt-email`, {
                recipient: formData.email,
            });

        if (viewReceipt.value) openReport(`Receipts/${id}/receipt-pdf`, {}, '_blank');
    } finally {
        if ($props.promise) $props.promise();
        if (closeButton.value) closeButton.value.click();
    }
}

async function getSupplierClientReferences(value) {
    if (!value) return (initialData.description = '');
    const params = { bankAccount: value };
    const { data } = await axios(`Clients/getClientOrSupplierReference`, { params });
    if (!data.clientId) {
        initialData.description = t('Supplier Compensation Reference', {
            supplierId: data.supplierId,
            supplierName: data.supplierName,
        });
        return;
    }
    initialData.description = t('Client Compensation Reference', {
        clientId: data.clientId,
        clientName: data.clientName,
    });
}

async function getAmountPaid() {
    const filter = {
        where: {
            clientFk: route.params.id,
            companyFk: initialData.companyFk,
        },
    };

    const { data } = await getClientRisk(filter);
    initialData.amountPaid = (data?.length && data[0].amount) || undefined;
}
</script>

<template>
    <QDialog ref="dialogRef" persistent>
        <FetchData
            @on-fetch="(data) => (companyOptions = data)"
            auto-load
            url="Companies"
        />
        <FetchData
            :filter="filterBanks"
            @on-fetch="(data) => (bankOptions = data)"
            auto-load
            url="Accountings"
        />
        <FetchData
            :filter="filterClientFindOne"
            @on-fetch="({ email }) => (initialData.email = email)"
            auto-load
            url="Clients/findOne"
        />
        <FormModelPopup
            ref="formModelRef"
            :form-initial-data="initialData"
            :url-create="urlCreate"
            :mapper="onBeforeSave"
            @on-data-saved="onDataSaved"
            :prevent-submit="true"
        >
            <template #form-inputs="{ data, validate }">
                <h5 class="q-mt-none">{{ t('New payment') }}</h5>
                <VnRow>
                    <VnSelect
                        autofocus
                        :label="t('Bank')"
                        v-model="data.bankFk"
                        url="Accountings"
                        option-label="bank"
                        :include="{ relation: 'accountingType' }"
                        sort-by="id"
                        :limit="0"
                        @update:model-value="
                            (value, options) => setPaymentType(data, value, options)
                        "
                        :emit-value="false"
                        data-cy="paymentBank"
                    >
                        <template #option="scope">
                            <QItem v-bind="scope.itemProps">
                                <QItemSection>
                                    <QItemLabel>
                                        {{ scope.opt.id }}:&ensp;{{ scope.opt.bank }}
                                    </QItemLabel>
                                </QItemSection>
                            </QItem>
                        </template>
                    </VnSelect>
                    <VnInputNumber
                        :label="t('Amount')"
                        :required="true"
                        @update:model-value="calculateFromAmount($event)"
                        clearable
                        v-model.number="data.amountPaid"
                        data-cy="paymentAmount"
                    />
                </VnRow>
                <VnRow>
                    <VnInputDate
                        :label="t('Date')"
                        v-model="data.payed"
                        :required="true"
                    />
                    <VnSelect
                        :label="t('Company')"
                        :options="companyOptions"
                        :required="true"
                        :rules="validate('entry.companyFk')"
                        hide-selected
                        option-label="code"
                        option-value="id"
                        v-model="data.companyFk"
                        @update:model-value="getAmountPaid()"
                    />
                </VnRow>
                <div v-if="accountingType.code == 'compensation'">
                    <div class="text-h6">
                        {{ t('Compensation') }}
                    </div>
                    <VnRow>
                        <VnAccountNumber
                            :label="t('Compensation account')"
                            clearable
                            v-model="data.compensationAccount"
                            @blur="getSupplierClientReferences(data.compensationAccount)"
                        />
                    </VnRow>
                </div>
                <VnInput
                    :label="t('Reference')"
                    :required="true"
                    clearable
                    v-model="data.description"
                />
                <div v-if="accountingType.code == 'cash'">
                    <div class="text-h6">{{ t('Cash') }}</div>
                    <VnRow>
                        <VnInputNumber
                            :label="t('Delivered amount')"
                            @update:model-value="calculateFromDeliveredAmount($event)"
                            clearable
                            v-model="data.deliveredAmount"
                        />
                        <VnInputNumber
                            :label="t('Amount to return')"
                            disable
                            v-model="amountToReturn"
                        />
                    </VnRow>
                    <VnRow>
                        <QCheckbox v-model="viewReceipt" :label="t('View recipt')" />
                        <QCheckbox v-model="shouldSendEmail" :label="t('Send email')" />
                    </VnRow>
                </div>
            </template>
        </FormModelPopup>
    </QDialog>
</template>

<i18n>
es:
    New payment: Añadir pago
    Date: Fecha
    Company: Empresa
    Bank: Caja
    Amount: Importe
    Reference: Referencia
    Cash: Efectivo
    Delivered amount: Cantidad entregada
    Amount to return: Cantidad a devolver
    View recipt: Ver recibido
    Send email: Enviar correo
    Compensation: Compensación
    Compensation account: Cuenta para compensar
    Supplier Compensation Reference: ({supplierId}) Ntro Proveedor {supplierName}
    Client Compensation Reference: ({clientId}) Ntro Cliente {clientName}
    There is no assigned email for this client: No hay correo asignado para este cliente
    Amount exceeded: Según ley contra el fraude no se puede recibir cobros por importe igual o superior a {maxAmount}
</i18n>
