'use strict';

/**
 *
 *
 * @author Mai
 * @date
 * @version
 */

module.exports = app => {

    const paramConst = app.paramConst;

    class TenderParam extends app.BaseService {
        /**
         * 构造函数
         *
         * @param {Object} ctx - egg全局context
         * @return {void}
         */
        constructor(ctx) {
            super(ctx);
            this.tableName = 'tender_param';
        }

        async getParams(libId, billsId) {
            const sql = 'Select p.*, n.bills_id From ' + this.tableName + ' p' +
                '  LEFT JOIN ' + this.ctx.service.tenderNode.tableName + ' n' +
                '  On p.node_id = n.node_id and p.lib_id = n.lib_id' +
                '  Where p.lib_id = ? and n.bills_id = ?';
            const sqlParam = [libId, billsId];
            return await this.db.query(sql, sqlParam);
        }

        /**
         * 计算指标节点下全部指标
         * @param transaction - 事务
         * @param {Object} condition - 计算范围
         * @param {Array} globalParams - 可用全局参数
         * @param {Object} newParam - 更新的节点参数
         * @returns {Promise<void>}
         * @private
         */
        async _calculateNodeIndex(transaction, condition, globalParams, newParam, gRelaParam) {
            // let time1 = new Date();
            const nodeParams = await this.ctx.service.tenderParam.getAllDataByCondition({where: condition});
            // await this.ctx.service.log.addLog('node' + this.serialNo + ':select tenderParam', new Date() - time1);
            //
            // time1 = new Date();
            const nodeIndexes = await this.ctx.service.tenderIndex.getAllDataByCondition({where: condition});
            // await this.ctx.service.log.addLog('node' + this.serialNo + ':select tenderIndex', new Date() - time1);
            //
            // time1 = new Date();
            let relaParam;
            if (newParam) {
                for (const np of nodeParams) {
                    if (np.code === newParam.code) {
                        np.calc_value = newParam.value;
                        relaParam = np;
                        break;
                    }
                }
            } else {
                relaParam = gRelaParam;
            }
            this.ctx.service.indexCalc.calculate(nodeIndexes, globalParams, nodeParams, relaParam);
            for (const u of this.ctx.service.indexCalc.updateArr) {
                await transaction.update(this.ctx.service.tenderIndex.tableName, {
                    id: u.id,
                    eval_rule: u.eval_rule,
                    value: u.value,
                });
            }
            // await this.ctx.service.log.addLog('node' + this.serialNo + ':update tenderIndex', new Date() - time1);
        }

        /**
         * 计算标段内全部指标
         * @param transaction - 事务
         * @param {Object} condition - 计算范围
         * @param {Object} newParam - 更新的全局参数
         * @returns {Promise<void>}
         * @private
         */
        async _calculateAllIndex(transaction, condition, newParam) {
            const globalParams = await this.ctx.service.tenderParam.getAllDataByCondition({
                where: {lib_id: condition.lib_id, node_id: paramConst.globalParamNodeId}
            });
            let relaParam;
            if (newParam) {
                for (const gp of globalParams) {
                    if (gp.code === newParam.code) {
                        gp.calc_value = newParam.value;
                        relaParam = gp;
                        break;
                    }
                }
            }
            const nodes = await this.ctx.service.tenderNode.getAllDataByCondition({where: condition});
            const indexes = await this.ctx.service.tenderIndex.getAllDataByCondition({where: condition});
            const params = await this.ctx.service.tenderParam.getAllDataByCondition({where: condition});

            // this.serialNo = 1;
            for (const node of nodes) {
                // condition.node_id = node.node_id;
                // await this._calculateNodeIndex(transaction, condition, globalParams);
                // this.serialNo += 1;
                node.indexes = indexes.filter(function (a) {
                    return a.node_id === node.node_id;
                });
                node.params = params.filter(function (a) {
                    return a.node_id === node.node_id;
                });
                this.ctx.service.indexCalc.calculate(node.indexes, globalParams, node.params, relaParam);
                for (const u of this.ctx.service.indexCalc.updateArr) {
                    await transaction.update(this.ctx.service.tenderIndex.tableName, {
                        id: u.id,
                        eval_rule: u.eval_rule,
                        value: u.value,
                    });
                }
            }
        }

        /**
         * 更新参数取值
         * @param data
         * @returns {Promise<boolean>}
         */
        async updateCalcValue(data) {
            const transaction = await this.db.beginTransaction();
            try {
                const condition = {
                    lib_id: parseInt(data.lib_id),
                    node_id: data.node_id,
                    code: data.code
                };
                if (condition.lib_id < 0 || condition.node_id < 0) {
                    throw '提交数据错误';
                }
                data.value = parseFloat(data.value);
                const updateData = {
                    calc_value: (isNaN(data.value) ? null : data.value),
                };
                await transaction.update(this.tableName, updateData, {where: condition});
                if (condition.node_id === paramConst.globalParamNodeId) {
                    const calcCondition = { lib_id: condition.lib_id };
                    const calcData = { code: data.code, value: updateData.calc_value };
                    await this._calculateAllIndex(transaction, calcCondition, calcData);
                } else {
                    const globalParams = await this.ctx.service.tenderParam.getAllDataByCondition({
                        where: {lib_id: condition.lib_id, node_id: paramConst.globalParamNodeId}
                    });
                    const calcCondition = { lib_id: condition.lib_id, node_id: data.node_id };
                    const calcData = { code: data.code, value: updateData.calc_value };
                    await this._calculateNodeIndex(transaction, calcCondition, globalParams, calcData);
                }
                await transaction.commit();
                return true;
            } catch (err) {
                await transaction.rollback();
                throw err;
            }
        }

        /**
         * 重置参数取值
         * @param data
         * @returns {Promise<boolean>}
         */
        async resetCalcValue(data) {
            try {
                const condition = {
                    lib_id: parseInt(data.lib_id),
                    node_id: data.node_id,
                    code: data.code,
                };
                if (condition.lib_id < 0 || condition.node_id < 0) {
                    throw '提交数据错误';
                }
                const param = await this.getDataByCondition(condition);
                data.value = param.match_value;
                await this.updateCalcValue(data);
                return true;
            } catch (err) {
                throw err;
            }

        }
    };

    return TenderParam;
};