const print = require('vn-print');
const path = require('path');
const UserError = require('vn-loopback/util/user-error');

module.exports = Self => {
    require('../methods/invoiceOut/filter')(Self);
    require('../methods/invoiceOut/summary')(Self);
    require('../methods/invoiceOut/getTickets')(Self);
    require('../methods/invoiceOut/download')(Self);
    require('../methods/invoiceOut/downloadZip')(Self);
    require('../methods/invoiceOut/delete')(Self);
    require('../methods/invoiceOut/book')(Self);
    require('../methods/invoiceOut/createPdf')(Self);
    require('../methods/invoiceOut/createManualInvoice')(Self);
    require('../methods/invoiceOut/clientsToInvoice')(Self);
    require('../methods/invoiceOut/invoiceClient')(Self);
    require('../methods/invoiceOut/makePdfList')(Self);
    require('../methods/invoiceOut/makePdfAndNotify')(Self);
    require('../methods/invoiceOut/refund')(Self);
    require('../methods/invoiceOut/invoiceEmail')(Self);
    require('../methods/invoiceOut/exportationPdf')(Self);
    require('../methods/invoiceOut/invoiceCsv')(Self);
    require('../methods/invoiceOut/invoiceCsvEmail')(Self);
    require('../methods/invoiceOut/invoiceOutPdf')(Self);
    require('../methods/invoiceOut/getInvoiceDate')(Self);
    require('../methods/invoiceOut/negativeBases')(Self);
    require('../methods/invoiceOut/negativeBasesCsv')(Self);
    require('../methods/invoiceOut/transferInvoice')(Self);

    Self.filePath = async function(id, options) {
        const fields = ['ref', 'issued'];
        const invoiceOut = await Self.findById(id, {fields}, options);

        const issued = invoiceOut.issued;
        const year = issued.getFullYear().toString();
        const month = (issued.getMonth() + 1).toString();
        const day = issued.getDate().toString();

        return {
            path: path.join(year, month, day),
            name: `${year}${invoiceOut.ref}.pdf`,
            year
        };
    };

    Self.makePdf = async function(id, options) {
        const fields = ['id', 'hasPdf', 'ref'];
        const invoiceOut = await Self.findById(id, {fields}, options);
        const invoiceReport = new print.Report('invoice', {
            reference: invoiceOut.ref
        });
        const buffer = await invoiceReport.toPdfStream();

        const pdfFile = await Self.filePath(id, options);

        // Store invoice

        await invoiceOut.updateAttributes({
            hasPdf: true
        }, options);

        if (process.env.NODE_ENV !== 'test') {
            await print.storage.write(buffer, {
                type: 'invoice',
                path: pdfFile.path,
                fileName: pdfFile.name
            });
        }
    };

    Self.getSerial = async function(clientId, companyId, addressId, type, myOptions) {
        const [{serial}] = await Self.rawSql(
            `SELECT vn.invoiceSerial(?, ?, ?) AS serial`,
            [
                clientId,
                companyId,
                type
            ],
            myOptions);

        const invoiceOutSerial = await Self.app.models.InvoiceOutSerial.findById(serial);
        if (invoiceOutSerial?.taxAreaFk == 'WORLD') {
            const address = await Self.app.models.Address.findById(addressId);
            if (!address || !address.customsAgentFk || !address.incotermsFk)
                throw new UserError('The address of the customer must have information about Incoterms and Customs Agent');
        }

        return serial;
    };
};