'use strict';

/**
 * 期计量 数据模型
 *
 * @author Mai
 * @date 2018/8/13
 * @version
 */

const auditConst = require('../const/audit').stage;
const payConst = require('../const/deal_pay.js');

module.exports = app => {
    class Stage extends app.BaseService {
        /**
         * 构造函数
         *
         * @param {Object} ctx - egg全局变量
         * @return {void}
         */
        constructor(ctx) {
            super(ctx);
            this.tableName = 'stage';
        }

        /**
         * 获取 最新一期 期计量
         * @param tenderId
         * @param includeUnCheck
         * @returns {Promise<*>}
         */
        async getLastestStage(tenderId, includeUnCheck = false) {
            this.initSqlBuilder();
            this.sqlBuilder.setAndWhere('tid', {
                value: tenderId,
                operate: '=',
            });
            if (!includeUnCheck) {
                this.sqlBuilder.setAndWhere('status', {
                    value: auditConst.status.uncheck,
                    operate: '!=',
                });
            }
            this.sqlBuilder.orderBy = [['order', 'desc']];
            const [sql, sqlParam] = this.sqlBuilder.build(this.tableName);
            const stage = await this.db.queryOne(sql, sqlParam);
            return stage;
        }

        /**
         * 获取 最新一期 审批完成的 期计量
         * @param tenderId
         * @returns {Promise<*>}
         */
        async getLastestCompleteStage(tenderId) {
            this.initSqlBuilder();
            this.sqlBuilder.setAndWhere('tid', {
                value: tenderId,
                operate: '=',
            });
            this.sqlBuilder.setAndWhere('status', {
                value: auditConst.status.checked,
                operate: '=',
            });
            this.sqlBuilder.orderBy = [['order', 'desc']];
            const [sql, sqlParam] = this.sqlBuilder.build(this.tableName);
            const stage = await this.db.queryOne(sql, sqlParam);
            return stage;
        }

        /**
         * 获取标段下的全部计量期，按倒序
         * @param tenderId
         * @returns {Promise<void>}
         */
        async getValidStages(tenderId) {
            const stages = await this.db.select(this.tableName, {
                where: {tid: tenderId},
                orders: [['order', 'desc']],
            });
            for (const s of stages) {
                s.tp = this.ctx.helper.add(s.contract_tp, s.qc_tp);
                s.pre_tp = this.ctx.helper.add(s.pre_contract_tp, s.pre_qc_tp);
                s.end_tp = this.ctx.helper.add(s.pre_tp, s.tp);
            }
            if (stages.length !== 0) {
                const lastStage = stages[stages.length - 1];
                if (lastStage.status === auditConst.status.uncheck && lastStage.user_id !== this.ctx.session.sessionUser.accountId) {
                    stages.splice(stages.length - 1, 1);
                }
            }
            // 最新一期计量（未审批完成），当前操作人的期详细数据，应实时计算
            if (stages.length > 0 && stages[0].status !== auditConst.status.checked) {
                const stage = stages[0];
                const curAuditor = await this.ctx.service.stageAudit.getCurAuditor(stage.id, stage.times);
                const isActive = curAuditor ? curAuditor.id === this.ctx.session.sessionUser.accountId : stage.user_id === this.ctx.session.sessionUser.accountId;
                if (isActive) {
                    const tpData = await this.ctx.service.stageBills.getSumTotalPrice(stage);
                    stage.contract_tp = tpData.contract_tp;
                    stage.qc_tp = tpData.qc_tp;
                    stage.tp = this.ctx.helper.add(stage.contract_tp, stage.qc_tp);
                    stage.end_tp = this.ctx.helper.add(stage.pre_tp, stage.tp);
                }
            }
            return stages;
        }

        /**
         *
         * @param tenderId - 标段id
         * @param date - 计量年月
         * @param period - 开始-截止日期
         * @returns {Promise<void>}
         */
        async addStage(tenderId, date, period) {
            const stages = await this.getAllDataByCondition({
                where: {tid: tenderId},
                order: ['order'],
            });
            const preStage = stages[stages.length - 1];
            if (stages.length > 0 && stages[stages.length - 1].status !== auditConst.status.checked) {
                throw '上一期未审批通过，请等待上一期审批通过后，再新增数据';
            };
            const order = stages.length + 1;
            const newStage = {
                sid: this.uuid.v4(),
                tid: tenderId,
                order: order,
                in_time: new Date(),
                s_time: date,
                period: period,
                times: 1,
                status: auditConst.status.uncheck,
                user_id: this.ctx.session.sessionUser.accountId,
            };
            if (preStage) {
                newStage.pre_contract_tp = this.ctx.helper.add(preStage.pre_contract_tp, preStage.contract_tp);
                newStage.pre_qc_tp = this.ctx.helper.add(preStage.pre_qc_tp, preStage.qc_tp);
            }
            const transaction = await this.db.beginTransaction();
            try {
                // 新增期记录
                const result = await transaction.insert(this.tableName, newStage);
                if (result.affectedRows === 1) {
                    newStage.id = result.insertId;
                } else {
                    throw '新增期数据失败';
                }
                // 存在上一期时，复制上一期审批流程
                if (preStage) {
                    const auditResult = await this.ctx.service.stageAudit.copyPreStageAuditors(transaction, preStage, newStage);
                    if (!auditResult) {
                        throw '复制上一期审批流程失败';
                    }
                }
                // 新增期合同支付数据
                const dealResult = await this.ctx.service.stagePay.addInitialStageData(newStage, transaction);
                if (!dealResult) {
                    throw '新增期合同支付数据失败';
                }

                await transaction.commit();
                return newStage;
            } catch (err) {
                await transaction.rollback();
                throw err;
            }
        }

        /**
         * 编辑计量期
         *
         * @param {Number} tenderId - 标段Id
         * @param {Number} order - 第N期
         * @param {String} date - 计量年月
         * @param {String} period - 开始-截止时间
         * @returns {Promise<void>}
         */
        async saveStage(tenderId, order, date, period) {
            await this.db.update(this.tableName, {
                s_time: date,
                period: period,
            }, { where: { tid: tenderId, order: order } });
        }

        /**
         * 设置 中间计量 生成规则，并生成数据
         * @param {Number} tenderId - 标段id
         * @param {Number} order - 期序号
         * @param {Number} data - 中间计量生成规则
         * @returns {Promise<void>}
         */
        async buildDetailData(tenderId, order, data) {
            const conn = await this.db.beginTransaction();
            try {
                await conn.update(this.tableName, { im_type: data.im_type, im_pre: data.im_pre }, { where: { tid: tenderId, order: order } });
                // to do 生成中间计量数据
                await conn.commit();
            } catch (err) {
                await conn.rollback();
                throw err;
            }
        }

        /**
         * 获取 当期的 计算基数
         * @returns {Promise<any>}
         */
        async getStagePayCalcBase() {
            const calcBase = JSON.parse(JSON.stringify(payConst.calcBase));
            const param = this.ctx.tender.info.deal_param;
            for (const cb of calcBase) {
                switch (cb.code) {
                    case 'htj':
                        cb.value = param.contractPrice;
                        break;
                    case 'zlje':
                        cb.value = param.zanLiePrice;
                        break;
                    case 'htjszl':
                        cb.value = this.ctx.helper.sub(param.contractPrice, param.zanLiePrice);
                        break;
                    case 'kgyfk':
                        cb.value = param.startAdvance;
                        break;
                    case 'clyfk':
                        cb.value = param.materialAdvance;
                        break;
                    case 'bqwc':
                        const sum = await this.ctx.service.stageBills.getSumTotalPrice(this.ctx.stage);
                        cb.value = this.ctx.helper.add(sum.contract_tp, sum.qc_tp);
                        break;
                    case 'ybbqwc':
                        const sumGcl = await this.ctx.service.stageBills.getSumTotalPriceGcl(this.ctx.stage, '^1[0-9]{2}-');
                        cb.value = this.ctx.helper.add(sumGcl.contract_tp, sumGcl.qc_tp);
                        break;
                    default:
                        cb.value = 0;
                }
            }
            return calcBase;
        }

        /**
         * 更新 check_detail 标识
         * @param {Integer}sid - 期id
         * @param {Boolean}check - 标记
         * @returns {Promise<void>}
         */
        async updateCheckDetailFlag(sid, check) {
            const result = await this.db.update(this.tableName, {id: sid, check_detail: check});
            return result.affectedRows === 1;
        }
    }

    return Stage;
};