module.exports = Self => {
    Self.remoteMethod('upsertFixedPrice', {
        description: 'Inserts or updates a fixed price for an item',
        accessType: 'WRITE',
        accepts: [
            {
                arg: 'ctx',
                type: 'object',
                http: {source: 'context'}
            },
            {
                arg: 'id',
                type: 'number',
                description: 'The fixed price id'
            },
            {
                arg: 'itemFk',
                type: 'number'
            },
            {
                arg: 'warehouseFk',
                type: 'number'
            },
            {
                arg: 'started',
                type: 'date'
            },
            {
                arg: 'ended',
                type: 'date'
            },
            {
                arg: 'rate2',
                type: 'number'
            },
            {
                arg: 'rate3',
                type: 'number'
            },
            {
                arg: 'minPrice',
                type: 'number'
            },
            {
                arg: 'hasMinPrice',
                type: 'any'
            }
        ],
        returns: {
            type: 'object',
            root: true
        },
        http: {
            path: `/upsertFixedPrice`,
            verb: 'PATCH'
        }
    });

    Self.upsertFixedPrice = async(ctx, options) => {
        const models = Self.app.models;
        const args = ctx.args;
        let tx;
        const myOptions = {};

        if (typeof options == 'object')
            Object.assign(myOptions, options);

        if (!myOptions.transaction) {
            tx = await Self.beginTransaction({});
            myOptions.transaction = tx;
        }

        try {
            delete args.ctx; // removed unwanted data

            if (args.id) {
                const beforeFixedPrice = await models.FixedPrice.findById(args.id, {fields: ['rate3']}, myOptions);
                const [result] = await Self.rawSql(`SELECT vn.priceFixed_getRate2(?, ?) as rate2`,
                    [args.id, args.rate3], myOptions);

                if (beforeFixedPrice.rate3 != args.rate3 && result && result.rate2)
                    args.rate2 = result.rate2;
            }

            const fixedPrice = await models.FixedPrice.upsert(args, myOptions);
            const targetItem = await models.Item.findById(args.itemFk, null, myOptions);

            await targetItem.updateAttributes({
                minPrice: args.minPrice,
                hasMinPrice: args.hasMinPrice
            }, myOptions);

            const itemFields = [
                'minPrice',
                'hasMinPrice',
                'name',
                'subName',
                'tag5',
                'value5',
                'tag6',
                'value6',
                'tag7',
                'value7',
                'tag8',
                'value8',
                'tag9',
                'value9',
                'tag10',
                'value10'
            ];

            const fieldsCopy = [].concat(itemFields);
            const filter = {
                include: {
                    relation: 'item',
                    scope: {
                        fields: fieldsCopy
                    }
                }
            };

            const result = await models.FixedPrice.findById(fixedPrice.id, filter, myOptions);
            const item = result.item();

            for (let key of itemFields)
                result[key] = item[key];

            if (tx) await tx.commit();

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