module.exports = Self => {
    Self.remoteMethodCtx('importToNewRefundTicket', {
        description: 'Imports lines from claimBeginning to a new ticket with specific shipped, landed dates, agency and company',
        accessType: 'WRITE',
        accepts: [{
            arg: 'id',
            type: 'number',
            required: true,
            description: 'the claim id',
            http: {source: 'path'}
        }],
        returns: {
            type: 'string',
            root: true
        },
        http: {
            path: `/:id/importToNewRefundTicket`,
            verb: 'POST'
        }
    });

    Self.importToNewRefundTicket = async(ctx, id) => {
        const models = Self.app.models;
        const token = ctx.req.accessToken;
        const userId = token.userId;
        const tx = await Self.beginTransaction({});
        const filter = {
            where: {id: id},
            include: [
                {
                    relation: 'ticket',
                    scope: {
                        fields: ['id', 'clientFk', 'warehouseFk', 'companyFk', 'addressFk'],
                        include: {
                            relation: 'address',
                            scope: {
                                fields: ['nickname']
                            }
                        }
                    }
                }
            ]
        };
        const salesFilter = {
            where: {claimFk: id},
            include: [
                {
                    relation: 'sale',
                    scope: {
                        fields: [
                            'id',
                            'itemFk',
                            'concept',
                            'price',
                            'discount',
                            'reserved',
                            'isPicked',
                            'created',
                            'priceFixed',
                            'isPriceFixed']
                    }
                }
            ]
        };

        try {
            let options = {transaction: tx};
            const worker = await models.Worker.findOne({
                where: {userFk: userId}
            }, options);

            const obsevationType = await models.ObservationType.findOne({
                where: {description: 'comercial'}
            }, options);

            const agencyMode = await models.AgencyMode.findOne({
                where: {code: 'refund'}
            }, options);

            const state = await models.State.findOne({
                where: {code: 'DELIVERED'}
            }, options);

            const zone = await models.Zone.findOne({
                where: {agencyModeFk: agencyMode.id}
            }, options);

            const claim = await models.Claim.findOne(filter, options);
            const today = new Date();

            const newRefundTicket = await models.Ticket.create({
                clientFk: claim.ticket().clientFk,
                shipped: today,
                landed: today,
                nickname: claim.ticket().address().nickname,
                warehouseFk: claim.ticket().warehouseFk,
                companyFk: claim.ticket().companyFk,
                addressFk: claim.ticket().addressFk,
                agencyModeFk: agencyMode.id,
                zoneFk: zone.id
            }, options);

            await saveObservation({
                description: `Reclama ticket: ${claim.ticketFk}`,
                ticketFk: newRefundTicket.id,
                observationTypeFk: obsevationType.id
            }, options);

            await models.TicketTracking.create({
                ticketFk: newRefundTicket.id,
                stateFk: state.id,
                workerFk: worker.id
            }, options);

            const salesToRefund = await models.ClaimBeginning.find(salesFilter, options);
            const createdSales = await addSalesToTicket(salesToRefund, newRefundTicket.id, options);
            await insertIntoClaimEnd(createdSales, id, worker.id, options);

            await Self.rawSql('CALL vn.ticketCalculateClon(?, ?)', [
                newRefundTicket.id, claim.ticketFk
            ], options);

            await tx.commit();

            return newRefundTicket;
        } catch (e) {
            await tx.rollback();
            throw e;
        }
    };

    async function addSalesToTicket(salesToRefund, ticketId, options) {
        let formatedSales = [];
        salesToRefund.forEach(sale => {
            let formatedSale = {
                itemFk: sale.sale().itemFk,
                ticketFk: ticketId,
                concept: sale.sale().concept,
                quantity: -Math.abs(sale.quantity),
                price: sale.sale().price,
                discount: sale.sale().discount,
                reserved: sale.sale().reserved,
                isPicked: sale.sale().isPicked,
                created: sale.sale().created
            };
            formatedSales.push(formatedSale);
        });
        return await Self.app.models.Sale.create(formatedSales, options);
    }

    async function insertIntoClaimEnd(createdSales, claimId, workerId, options) {
        const formatedSales = [];
        createdSales.forEach(sale => {
            let formatedSale = {
                saleFk: sale.id,
                claimFk: claimId,
                workerFk: workerId
            };
            formatedSales.push(formatedSale);
        });
        await Self.app.models.ClaimEnd.create(formatedSales, options);
    }

    async function saveObservation(observation, options) {
        const query = `INSERT INTO vn.ticketObservation (ticketFk, observationTypeFk, description) VALUES(?, ?, ?)
                        ON DUPLICATE KEY 
                            UPDATE description = CONCAT(vn.ticketObservation.description, VALUES(description),' ')`;
        await Self.rawSql(query, [
            observation.ticketFk,
            observation.observationTypeFk,
            observation.description
        ], options);
    }
};