'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';
        }

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

        /**
         * 计算标段内全部指标
         * @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}
            });
            if (newParam) {
                for (const gp of globalParams) {
                    if (gp.code === newParam.code) {
                        gp.calc_value = newParam.value;
                        break;
                    }
                }
            }
            const nodes = await this.ctx.service.tenderNode.getAllDataByCondition({where: condition});
            for (const node of nodes) {
                condition.node_id = node.node_id;
                await this._calculateNodeIndex(transaction, condition, globalParams);
            }
        }

        /**
         * 更新参数取值
         * @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;
};