'use strict';

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

const stdDataAddType = {
    withParent: 1,
    child: 2,
    next: 3,
};
const audit = require('../const/audit');
const tenderMenu = require('../../config/menu').tenderMenu;
const measureType = require('../const/tender').measureType;
const spreadConst = require('../const/spread');
const fs = require('fs');
const LzString = require('lz-string');
const accountGroup = require('../const/account_group').group;

module.exports = app => {

    class ReviseController extends app.BaseController {

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

        /**
         * 是否可以新增修订
         * @param ctx
         * @returns {Promise<boolean>}
         * @private
         */
        async _getAddReviseValid(ctx) {
            const stage  = await ctx.service.stage.getLastestStage(ctx.tender.id, true);
            const revise = await ctx.service.ledgerRevise.getLastestRevise(ctx.tender.id);
            return (ctx.tender.data.user_id === ctx.session.sessionUser.accountId) &&
                (ctx.tender.data.ledger_status === audit.ledger.status.checked) &&
                (!stage || stage.status === audit.stage.status.checked) &&
                (!revise || !revise.valid || revise.status === audit.revise.status.checked);
        }

        /**
         * 台账修订页面 (Get)
         *
         * @param {object} ctx - egg全局变量
         * @return {void}
         */
        async index(ctx) {
            try {
                // 分页相关
                const count = await ctx.service.ledgerRevise.count({tid: ctx.tender.id});
                const ledgerRevise = await ctx.service.ledgerRevise.getReviseList(ctx.tender.id);
                const addValid = await this._getAddReviseValid(ctx);
                const renderData = {
                    tender: ctx.tender.data,
                    tenderMenu: this.menu.tenderMenu,
                    preUrl: '/tender/' + ctx.tender.id,
                    pageInfo: {
                        page: ctx.page,
                        total: Math.ceil(count/app.config.pageSize),
                        queryData: JSON.stringify(ctx.urlInfo.query),
                    },
                    ledgerRevise,
                    addValid,
                    auditConst: audit.revise,
                };
                await this.layout('revise/index.ejs', renderData, 'revise/modal.ejs');
            } catch (err) {
                this.log(err);
                ctx.redirect(ctx.request.header.referer);
            }
        }

        /**
         * 新增 修订 (Post)
         * @param ctx
         * @returns {Promise<void>}
         */
        async add(ctx) {
            try {
                const addValid = await this._getAddReviseValid(ctx);
                if (!addValid) {
                    throw '无法新增修订';
                }
                const revise = await ctx.service.ledgerRevise.add(ctx.tender.id, ctx.session.sessionUser.accountId);

                ctx.redirect('/tender/' + ctx.tender.id + '/revise/info');
            } catch(err) {
                this.log(err);
                ctx.redirect(ctx.request.header.referer);
            }
        }

        /**
         * 作废 修订 (Post)
         * @param ctx
         * @returns {Promise<void>}
         */
        async cancel(ctx) {
            try {
                const revise = await ctx.service.ledgerRevise.getLastestRevise(ctx.tender.id);
                if (revise.uid !== ctx.session.sessionUser.accountId) {
                    throw '您无权作废该修订';
                }
                if (revise.status === audit.revise.checking) {
                    throw '修订审批中，不可作废';
                } else if (revise.status === audit.revise.checked) {
                    throw '修订已审批通过，不可作废';
                }
                if (revise.valid) {
                    const result = await ctx.service.ledgerRevise.cancelRevise(revise.id);
                }

                ctx.redirect('/tender/' + ctx.tender.id + '/revise/');
            } catch(err) {
                this.log(err);
                ctx.redirect(ctx.request.header.referer);
            }
        }

        /**
         * 保存 修订详情 (Ajax-post)
         * @param ctx
         * @returns {Promise<void>}
         */
        async save(ctx) {
            try {
                const revise = await ctx.service.ledgerRevise.getLastestRevise(ctx.tender.id);
                if (!revise.valid) {
                    throw '该修订已作废';
                } else if (revise.status === audit.revise.status.uncheck || revise.status === audit.revise.status.checkNo) {
                    if (ctx.session.sessionUser.accountId !== revise.uid) {
                        throw '您无权修改';
                    }
                } else if (revise.status === audit.revise.status.checking) {
                    throw '修订在审批中，不可修改修订数据';
                } else if (revise.staut === audit.revise.status.checked) {
                    throw '修订已经审批通过，不可修改修订数据，请新增下一修订';
                }
                const data = JSON.parse(ctx.request.body.data);
                if (data.content === undefined) {
                    throw '保存数据有误'
                }
                const result = await ctx.service.ledgerRevise.defaultUpdate({id: revise.id, content: data.content});
                if (result.affectedRows !== 1) {
                    throw '保存数据失败，请重试';
                }
                ctx.body = {err: 0, msg: '', data: null};
            } catch(err) {
                this.log(err);
                ctx.body = this.ajaxErrorBody(err, '保存数据失败，请重试');
            }
        }

        /**
         * 获取SpreadSetting
         * @private
         */
        _getSpreadSetting(revise) {
            const _ = this.app._;
            function removeFieldCols(setting, cols) {
                _.remove(setting.cols, function(c) {
                    return cols.indexOf(c.field) > -1;
                });
            }
            const tender = this.ctx.tender;
            const setting = tender.info.display.ledger.clQty ? spreadConst.withCl : spreadConst.withoutCl;
            const ledger = JSON.parse(JSON.stringify(setting.ledger));
            const pos = JSON.parse(JSON.stringify(setting.pos));

            if (revise.status === audit.revise.status.checking || revise.status === audit.revise.status.checked) {
                ledger.readOnly = true;
                pos.readOnly = true;
            }
            if (tender.data.measure_type === measureType.tz.value) {
                removeFieldCols(ledger, spreadConst.filterCols.tzWithoutCols);
            }
            if (!tender.info.display.ledger.dgnQty) {
                removeFieldCols(ledger, spreadConst.filterCols.dgnCols);
            }
            return [ledger, pos];
        }

        async _getDefaultReviseInfoData(ctx, revise) {
            const reviseBills = await ctx.service.reviseBills.getData(ctx.tender.id, revise.id);
            const revisePos = await ctx.service.revisePos.getData(ctx.tender.id, revise.id);
            const [ledgerSpread, posSpread] = this._getSpreadSetting(revise);
            return {
                revise: revise, tender: ctx.tender.data,
                reviseBills, revisePos, ledgerSpread, posSpread, tenderMenu, measureType,
                preUrl: '/tender/' + ctx.tender.id,
                audit: audit.revise,
                jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.ledger.revise),
            };
        }

        /**
         * 历史修订页面(修订完成后，用于查看)
         * @param ctx
         * @param revise
         * @returns {Promise<void>}
         * @private
         */
        async _getHistoryReviseInfo(ctx, revise) {
            const renderData = await this._getDefaultReviseInfoData(ctx, revise);
            renderData.ledgerSpread.readOnly = true;
            renderData.posSpread.readOnly = true;
            renderData.readOnly = true;
            renderData.history = true;
            renderData.historyRevise = await ctx.service.ledgerRevise.getReviseList(ctx.tender.id);
            await this.layout('revise/info.ejs', renderData, 'revise/info_modal.ejs');
        }

        /**
         * 修订页面(草稿，审批中)
         * @param ctx
         * @param revise
         * @returns {Promise<void>}
         * @private
         */
        async _getReviseInfo(ctx, revise) {
            const renderData = await this._getDefaultReviseInfoData(ctx, revise);
            const readOnly = (revise.status === audit.revise.status.checking || revise.status === audit.revise.status.checked || revise.uid !== ctx.session.sessionUser.accountId);
            if (readOnly) {
                renderData.ledgerSpread.readOnly = true;
                renderData.posSpread.readOnly = true;
            }
            renderData.readOnly = readOnly;
            renderData.history = false;
            renderData.historyRevise = [];
            await this.layout('revise/info.ejs', renderData, 'revise/info_modal.ejs');
        }

        /**
         * 修订 详细页面(Get)
         * @param ctx
         * @returns {Promise<void>}
         */
        async info(ctx) {
            try {
                const revise = await ctx.service.ledgerRevise.getLastestRevise(ctx.tender.id);
                if (revise.status === audit.revise.status.checked) {
                    await this._getHistoryReviseInfo(ctx);
                } else {
                    await this._getReviseInfo(ctx, revise);
                }
            } catch (err) {
                this.log(err);
                ctx.redirect(ctx.request.header.referer);
            }
        }

        async _checkRevise() {
            const revise = await this.ctx.service.ledgerRevise.getLastestRevise(this.ctx.tender.id);
            if (revise.uid !== this.ctx.session.sessionUser.accountId) {
                throw '修订数据错误';
            } else if (revise.status === audit.revise.status.checking) {
                throw '修订审批中，不可修改';
            } else if (revise.status === audit.revise.status.checked) {
                throw '修订已完成，如需修订台账，请新增修订';
            }
            this.ctx.revise = revise;
        }

        /**
         * 增、删、上下移、升降级
         * @param ctx
         * @returns {Promise<void>}
         */
        async baseOpr(ctx) {
            try {
                await this._checkRevise();
                const data = JSON.parse(ctx.request.body.data);
                let result;

                switch (data.postType) {
                    case 'add':
                        result = await ctx.service.reviseBills.addNode(ctx.tender.id, ctx.revise.id, data.id);
                        break;
                    // case 'delete':
                    //     result = await ctx.service.reviseBills.deleteNode(ctx.revise.id, data.id);
                    //     break;
                    case 'up-move':
                        result = await ctx.service.reviseBills.upMoveNode(ctx.tender.id, data.id);
                        break;
                    case 'down-move':
                        result = await ctx.service.reviseBills.downMoveNode(ctx.tender.id, data.id);
                        break;
                    // case 'up-level':
                    //     result = await ctx.service.reviseBills.upLevelNode(ctx.revise.id, data.id);
                    //     break;
                    // case 'down-level':
                    //     result = await ctx.service.reviseBills.downLevelNode(ctx.revise.id, data.id);
                    //     break;
                    default:
                        throw '未知操作';
                }
                ctx.body = {err: 0, msg: '', data: result};
            } catch (err) {
                this.log(err);
                ctx.body = this.ajaxErrorBody(err, '数据错误');
            }
        }

        /**
         * 批量插入数据 (Ajax)
         *
         * data = {id, batchData, batchType}
         * data.batchType = 'batchInsertChild'/'batchInsertNext'
         * data.batchData = [{name, children}] -- 项目节列表
         * data.batchData.children = [{code, name, unit, unit_price, quantity}] -- 工程量清单列表
         *
         * @param ctx
         * @return {Promise<void>}
         */
        async batchInsert(ctx) {
            try {
                await this._checkRevise();
                const data = JSON.parse(ctx.request.body.data);
                if ((isNaN(data.id) || data.id <= 0) || !data.batchType) {
                    throw '参数错误';
                }

                let result;
                switch (data.batchType) {
                    case 'child':
                        result = await ctx.service.reviseBills.batchInsertChild(ctx.tender.id, ctx.revise.id, data.id, data.batchData);
                        break;
                    case 'next':
                        result = await ctx.service.reviseBills.batchInsertNext(ctx.tender.id, ctx.revise.id, data.id, data.batchData);
                        break;
                    default:
                        throw '参数错误';
                }
                ctx.body = {err: 0, msg: '', data: result};
            } catch (err) {
                this.log(err);
                ctx.body = this.ajaxErrorBody(err, '数据错误');
            }
        }
    }

    return ReviseController;
};