'use strict';

/**
 * 计量相关控制器
 *
 * @author olym
 * @date 2018/2/11
 * @version
 */

const spreadConst = require('../const/spread');
const codeRuleConst = require('../const/code_rule');
const auditConst = require('../const/audit').flow;
const moment = require('moment');
const measureType = require('../const/tender').measureType;

module.exports = app => {

    class MeasureController extends app.BaseController {

        /**
         * 构造函数
         *
         * @param {Object} ctx - egg全局变量
         * @return {void}
         */
        constructor(ctx) {
            super(ctx);
            ctx.showProject = true;
            ctx.showTender = true;
            ctx.showTitle = true;
        }

        /**
         * 期计量(Get)
         * @param ctx
         * @returns {Promise<void>}
         */
        async stage(ctx) {
            try {
                const renderData = {
                    tender: ctx.tender.data,
                    tenderMenu: this.menu.tenderMenu,
                    preUrl: '/tender/' + ctx.tender.id,
                    auditConst,
                };
                renderData.stages = await ctx.service.stage.getValidStages(ctx.tender.id);
                for (const s of renderData.stages) {
                    s.curAuditor = null;
                }
                await this.layout('measure/stage.ejs', renderData, 'measure/stage_modal.ejs');
            } catch (err) {
                this.log(err);
                ctx.redirect(this.menu.menu.dashboard.url);
            }
        }

        /**
         * 新增期(Post)
         * @param ctx
         * @returns {Promise<void>}
         */
        async addStage(ctx) {
            try {
                if (ctx.session.sessionUser.accountId !== ctx.tender.data.user_id) {
                    throw '您无权创建计量期';
                }
                const date = ctx.request.body.date;
                const period = ctx.request.body.period;
                const newStage = await ctx.service.stage.addStage(ctx.tender.id, date, period);
                if (!newStage) {
                    throw '新增计量期失败，请重试';
                }
                ctx.redirect('/tender/' + ctx.tender.id + '/measure/stage/' + newStage.order);
            } catch (err) {
                this.log(err);
                ctx.redirect(ctx.request.header.referer)
            }
        }

        async saveStage(ctx) {
            try {
                const data = JSON.parse(ctx.request.body.data);
                const stage = await ctx.service.stage.getDataByCondition({
                    tid: ctx.tender.id,
                    order: data.order,
                });
                if (!stage) {
                    throw '提交数据错误';
                }
                if (stage.status !== auditConst.status.uncheck) {
                    throw '该计量期当前不可编辑';
                }
                if (ctx.session.sessionUser.accountId !== stage.user_id) {
                    throw '您无权修改该数据';
                }
                await this.ctx.service.stage.saveStage(ctx.tender.id, data.order, data.date, data.period);
                ctx.body = {err: 0, msg: '', data: null};
            } catch (err) {
                this.log(err);
                ctx.body = {err: 1, msg: err.toString(), data: null};
            }
        }

        /**
         * 清单汇总
         * @param ctx
         * @returns {Promise<void>}
         */
        async gather(ctx) {
            try {
                const renderData = {
                    tender: ctx.tender.data,
                    tenderMenu: this.menu.tenderMenu,
                    preUrl: '/tender/' + ctx.tender.id,
                }
                await this.layout('measure/gather.ejs', renderData);
            } catch (err) {
                this.log(err);
                ctx.redirect(this.menu.menu.dashboard.url);
            }
        }

        async compare(ctx) {
            try {
                const renderData = {
                    tender: ctx.tender.data,
                    tenderMenu: this.menu.tenderMenu,
                    preUrl: '/tender/' + ctx.tender.id,
                }
                await this.layout('measure/compare.ejs', renderData, 'measure/compare_modal.ejs');
            } catch (err) {
                this.log(err);
                ctx.redirect(this.menu.menu.dashboard.url);
            }
        }

        async list(ctx) {
            try {
                const tenderList = ctx.tenderList;
                const tenderData = ctx.tenderData;

                const codeRule = tenderData.m_rule ? JSON.parse(tenderData.m_rule) : [];
                for (const rule of codeRule) {
                    switch (rule.rule_type) {
                        case codeRuleConst.measure.ruleType.tenderName:
                            rule.preview = tenderData.name;
                            break;
                        case codeRuleConst.measure.ruleType.inDate:
                            rule.preview = moment().format('YYYYMM');
                            break;
                        case codeRuleConst.measure.ruleType.text:
                            rule.preview = rule.text;
                            break;
                        case codeRuleConst.measure.ruleType.addNo:
                            const s = '0000000000';
                            rule.preview = s.substr(s.length - rule.format);
                            break;
                    }
                }
                const works = await ctx.service.measure.measureList({
                    tender_id: tenderData.id,
                    user_id: ctx.session.sessionUser.accountId,
                    valid: true,
                });
                const renderData = {
                    tenderData,
                    tenderList,
                    ruleType: codeRuleConst.ruleType.measure,
                    ruleConst: codeRuleConst.measure,
                    codeRule,
                    works,
                    auditConst,
                };
                await this.layout('measure/wlist.ejs', renderData, 'measure/wlist_modal.ejs');
            } catch (err) {
                this.log(err);
                ctx.redirect(ctx.menuList.dashboard.url);
            }
        }

        /**
         * 中间计量--计量编制 页面 (Get)
         *
         * @param {Object} ctx - egg全局变量
         * @return {void}
         */
        async work(ctx) {
            try {
                const tenderList = ctx.tenderList;
                const tenderData = ctx.tenderData;
                const codeRule = tenderData.m_rule ? JSON.parse(tenderData.m_rule) : [];
                for (const rule of codeRule) {
                    switch (rule.rule_type) {
                        case codeRuleConst.measure.ruleType.tenderName:
                            rule.preview = tenderData.name;
                            break;
                        case codeRuleConst.measure.ruleType.inDate:
                            rule.preview = moment().format('YYYYMM');
                            break;
                        case codeRuleConst.measure.ruleType.text:
                            rule.preview = rule.text;
                            break;
                        case codeRuleConst.measure.ruleType.addNo:
                            const s = '0000000000';
                            rule.preview = s.substr(s.length - rule.format);
                            break;
                    }
                }

                const mid = ctx.params.mid
                const measure = await ctx.service.measure.getDataByCondition({mid: mid, valid: true});
                if (!measure) {
                    throw '该数据已被删除'
                }
                const renderData = {
                    tenderData,
                    tenderList,
                    auditConst,
                    measure,
                    measureSpreadSetting: JSON.stringify(spreadConst.measureSpread),
                };
                await this.layout('measure/work.ejs', renderData, 'measure/work_modal.ejs');
            } catch (err) {
                this.log(err);
                ctx.redirect(ctx.menuList.dashboard.url);
            }
        }

        /**
         * 中间计量 -- 获取新编号 (Ajax)
         *
         * @param {Object} ctx - egg全局变量
         * @returns {Promise<void>}
         */
        async newCode(ctx) {
            const responseData = {
                err: 0,
                msg: '',
                data: '',
            };
            try {
                const tenderId = ctx.session.sessionUser.tenderId;
                if (!tenderId) {
                    throw '当前未打开标段';
                }
                const tenderData = await ctx.service.tender.getDataById(tenderId);
                const mCodeRule = JSON.parse(tenderData.m_rule);

                const code = [];
                for (const rule of mCodeRule) {
                    switch (rule.rule_type) {
                        case codeRuleConst.measure.ruleType.tenderName:
                            code.push(tenderData.name);
                            break;
                        case codeRuleConst.measure.ruleType.text:
                            code.push(rule.text);
                            break;
                        case codeRuleConst.measure.ruleType.inDate:
                            code.push(moment().format('YYYYMM'));
                            break;
                        case codeRuleConst.measure.ruleType.addNo:
                            let s = '0000000000';
                            const count = rule.start + await ctx.service.measure.count({tender_id: tenderId});
                            s = s + count;
                            code.push(s.substr(s.length - rule.format));
                            break;
                    }
                }
                responseData.data = code.join('');
            } catch (err) {
                responseData.err = 1;
                responseData.msg = err;
            }

            ctx.body = responseData;
        }

        /**
         * 中间计量 -- 新增中间计量 (Ajax)
         *
         * @param {Object} ctx - egg全局变量
         * @returns {Promise<void>}
         */
        async addMeasure(ctx) {
            const responseData = {
                err: 0,
                msg: '',
                data: '',
            };
            try {
                const tenderId = ctx.session.sessionUser.tenderId;
                if (!tenderId) {
                    throw '当前未打开标段';
                }
                const tenderData = await ctx.service.tender.getDataById(tenderId);

                const data = JSON.parse(ctx.request.body.data);
                await ctx.service.measure.add(tenderId, data.code, ctx.session.sessionUser.accountId, data.date, data.stage);

                responseData.data = await ctx.service.measure.measureData({
                    tender_id: tenderId, code: data.code,
                });
            } catch (err) {
                this.log(err);
                responseData.err = 1;
                responseData.msg = err.toString();
            }
            ctx.body = responseData;
        }

        async deleteMeasure(ctx) {
            const responseData = {
                err: 0,
                msg: '',
                data: '',
            };
            try {
                const tenderId = ctx.session.sessionUser.tenderId;
                if (!tenderId) {
                    throw '当前未打开标段';
                }

                const data = JSON.parse(ctx.request.body.data);
                responseData.data = await ctx.service.measure.invalid(tenderId, data.code, ctx.session.sessionUser.accountId);
            } catch (err) {
                this.log(err);
                responseData.err = 1;
                responseData.msg = err.toString();
            }
            ctx.body = responseData;
        }

        /**
         * 获取中间计量详细数据(包括部位和清单) (Ajax)
         * @param ctx - egg全局变量
         * @returns {Promise<void>}
         */
        async measureDetail(ctx) {
            const responseData = {
                err: 0,
                msg: '',
                data: '',
            };
            try {
                const tenderId = ctx.session.sessionUser.tenderId;
                if (!tenderId) {
                    throw '当前未打开标段';
                }
                const tenderData = await ctx.service.tender.getDataById(tenderId);

                const data = JSON.parse(ctx.request.body.data);
                if (!data.mid) {
                    throw '查询数据有误';
                }
                const measure = await ctx.service.measure.getDataByCondition({
                    tender_id: tenderId,
                    mid: data.mid,
                });
                if (!measure.times) {
                    measure.times = 1;
                }

                measure.pos = await ctx.service.measurePos.getPosDetail(tenderId, data.mid);
                measure.bills = await ctx.service.measureBills.getBillsDetail(tenderId, data.mid);
                measure.billsTree = await ctx.service.measureBills.getBillsDetailWithParent(tenderId, data.mid);
                measure.curAuditor = await ctx.service.measureAudit.getCurAuditor(data.mid, measure.times);
                if (measure.times > 1 && measure.status === auditConst.status.checkNo) {
                    measure.auditors = await ctx.service.measureAudit.getAuditors(data.mid, measure.times-1);
                } else {
                    measure.auditors = await ctx.service.measureAudit.getAuditors(data.mid, measure.times);
                }

                responseData.data = measure;
            } catch (err) {
                this.log(err);
                responseData.err = 1;
                responseData.msg = err.toString();
            }

            ctx.body = responseData;
        }

        /**
         * 查询部位或者清单 (Ajax)
         *
         * @param ctx - egg全局变量
         * @returns {Promise<void>}
         */
        async search(ctx) {
            const responseData = {
                err: 0,
                msg: '',
                data: '',
            };

            try {
                const tenderId = ctx.session.sessionUser.tenderId;
                if (!tenderId) {
                    throw '当前未打开标段';
                }
                const tenderData = await ctx.service.tender.getDataById(tenderId);

                const data = JSON.parse(ctx.request.body.data);
                if (!data.mid || !data.searchType) {
                    throw '查询数据有误';
                }

                if (data.searchType === 'pos') {
                    const key = {
                        value: app.mysql.escape('%' + data.keyword + '%'),
                        operate: 'Like',
                        fields: ['code', 'name'],
                    };
                    responseData.data = await ctx.service.ledger.search(tenderId, key);
                } else if (data.searchType === 'bills') {
                    const key = {
                        value: app.mysql.escape('%' + data.keyword + '%'),
                        operate: 'Like',
                        fields: ['b_code', 'name'],
                    };

                    const range = [];
                    const pos = await ctx.service.measurePos.getPosDetail(tenderId, data.mid);
                    const posFullPath = [];
                    for (const p of pos) {
                        posFullPath.push(app.mysql.escape(p.full_path + '.%'));
                    }

                    responseData.data = await ctx.service.ledger.searchRange(tenderId, key, [{
                        value: posFullPath,
                        operate: 'Like',
                        fields: ['full_path'],
                    }, {
                        value: true,
                        operate: '=',
                        fields: ['is_leaf'],
                    }]);
                } else {
                    throw '查询数据有误';
                }
            } catch (err) {
                this.log(err);
                responseData.err = 1;
                responseData.msg = err.toString();
            }

            ctx.body = responseData;
        }

        /**
         * 操作部位 -- 增删 (Ajax)
         *
         * @param ctx - egg全局变量
         * @returns {Promise<void>}
         */
        async pos(ctx) {
            const responseData = {
                err: 0,
                msg: '',
                data: {},
            };
            try {
                const tenderId = ctx.session.sessionUser.tenderId;
                if (!tenderId) {
                    throw '当前未打开标段';
                }

                const data = JSON.parse(ctx.request.body.data);
                if (!data.mid || !data.operate || !data.pid) {
                    throw '计量范围数据有误';
                }

                if (data.operate === 'add') {
                    responseData.data = await ctx.service.measurePos.addPos(tenderId, data.mid, data.pid);
                } else if (data.operate === 'remove') {
                    await ctx.service.measurePos.removePos(tenderId, data.mid, data.pid);
                } else {
                    throw '未知操作';
                }
            } catch(err) {
                this.log(err);
                responseData.err = 1;
                responseData.msg = err.toString();
            }
            ctx.body = responseData;
        }

        /**
         * 操作清单 -- 增删 (Ajax)
         * @param ctx
         * @returns {Promise<void>}
         */
        async bills(ctx) {
            const responseData = {
                err: 0,
                msg: '',
                data: {},
            };
            try {
                const tenderId = ctx.session.sessionUser.tenderId;
                if (!tenderId) {
                    throw '当前未打开标段';
                }

                const data = JSON.parse(ctx.request.body.data);
                if (!data.mid || !data.operate || !data.bid) {
                    throw '计量清单数据有误';
                }

                if (data.operate === 'add') {
                    await ctx.service.measureBills.addBills(tenderId, data.mid, data.bid);
                    responseData.data = await ctx.service.measureBills.getBillsDataWithParent(tenderId, data.mid, data.bid);
                } else if (data.operate === 'remove') {
                    responseData.data = await ctx.service.measureBills.getBillsDataWithParent(tenderId, data.mid, data.bid);
                    await ctx.service.measureBills.removeBills(tenderId, data.mid, data.bid);
                } else {
                    throw '未知操作';
                }
            } catch(err) {
                this.log(err);
                responseData.err = 1;
                responseData.msg = err.toString();
                responseData.data = {};
            }
            ctx.body = responseData;
        }

        /**
         * 清单 -- 计量 (Ajax)
         * @param ctx
         * @returns {Promise<void>}
         */
        async billsUpdate (ctx) {
            const responseData = { err: 0, msg: '', data: {} };
            try {
                const tenderId = ctx.session.sessionUser.tenderId;
                if (!tenderId) {
                    throw '当前未打开标段';
                }

                const data = JSON.parse(ctx.request.body.data);
                if (!data.mid || !data.bid || !data.update) {
                    throw '计量清单数据有误';
                }

                responseData.data = await ctx.service.measureBills.updateBills(tenderId, data.mid, data.bid, data.update);
            } catch(err) {
                this.log(err);
                responseData.err = 1;
                responseData.msg = err.toString();
                responseData.data = {};
            }

            ctx.body = responseData;
        }
    }

    return MeasureController;
};
