'use strict';

/**
 * 台账相关控制器
 *
 * @author CaiAoLin
 * @date 2017/11/30
 * @version
 */

const stdDataAddType = {
    self: 1,
    withParent: 2
}
const auditConst = require('../const/audit');
const spreadConst = require('../const/spread');

module.exports = app => {

    class LedgerController extends app.BaseController {

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

        /**
         * 台账分解页面
         *
         * @param {Object} ctx - egg全局变量
         * @return {void}
         */
        async explode(ctx) {
            if (ctx.request.query.tenderId) {
                const tenderId = parseInt(ctx.request.query.tenderId);
                const tender = await ctx.service.tender.getDataById(tenderId);
                ctx.session.sessionUser.tenderId = tender.id;
                ctx.session.sessionUser.tenderName = tender.name;

                ctx.redirect('/ledger/explode');
            } else {
                let tenderId = ctx.session.sessionUser.tenderId;
                const tenderList = await ctx.service.tender.getList();
                for (const tender of tenderList) {
                    tender.url = ctx.menuList.ledger.children.explode.url + '?tenderId=' + tender.id;
                }

                if (!tenderId) {
                    // 根据标段列表获取默认tenderId
                    if (tenderList && tenderList.length > 0) {
                        tenderId = tenderList[0].id;
                        ctx.session.sessionUser.tenderId = tenderId;
                        ctx.session.sessionUser.tenderName = tenderList[0].name;
                    } else {
                        throw '项目无标段数据';
                    }
                }

                const tenderData = await ctx.service.tender.getDataById(tenderId);
                if (!tenderData.ledger_status) {
                    tenderData.ledger_status = auditConst.status.uncheck;
                }
                if (!tenderData.ledger_times) {
                    tenderData.ledger_times = 1;
                }
                const curAuditor = await ctx.service.ledgerAudit.getCurAuditor(tenderId, tenderData.ledger_times);
                const auditors = await ctx.service.ledgerAudit.getAuditors(tenderId, tenderData.ledger_times);
                const times = tenderData.ledger_status === auditConst.status.checkNo ? tenderData.ledger_times - 1 : tenderData.ledger_times;
                const content = await ctx.service.ledgerAuditContent.getAllDataByCondition({
                    where: {tender_id: tenderId, times: times, audit_id: auditors[0].audit_id}
                });
                const ledgerData = await ctx.service.ledger.getDataByTenderId(tenderId);
                const renderData = {
                    tenderData,
                    auditConst,
                    auditors,
                    curAuditor,
                    content,
                    ledger: JSON.stringify(ledgerData),
                    ledgerSpreadSetting: JSON.stringify(spreadConst.ledgerSpread),
                    tenderList,
                };
                await this.layout('ledger/explode.ejs', renderData, 'ledger/explode_modal.ejs');
            }
        }

        /**
         * 检查标段是否只读(审核中，审核完成)
         * @param {Object} tenderData
         * @returns {boolean}
         * @private
         */
        _ledgerReadOnly (tenderData) {
            return tenderData.ledger_status === auditConst.status.checking || tenderData.ledger_status === auditConst.status.checked;
        }

        /**
         * 获取子节点
         * @param ctx
         * @return {Promise<void>}
         */
        async getChildren(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);
                const id = data.ledger_id;
                if (isNaN(id) || id <= 0) {
                    throw '参数错误';
                }

                responseData.data = await ctx.service.ledger.getChildrenByParentId(tenderId, id);
            } catch (err) {
                responseData.err = 1;
                responseData.msg = err;
            }

            ctx.body = responseData;
        }

        /**
         * 树结构基本操作（增、删、上下移、升降级）
         * @param {Object} ctx - egg全局变量
         * @return {Promise<void>}
         */
        async baseOperation(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);
                if (!tenderData || tenderData.user_id !== ctx.session.sessionUser.accountId || this._ledgerReadOnly(tenderData)) {
                    throw '标段数据错误';
                }
                const data = JSON.parse(ctx.request.body.data);
                if ((isNaN(data.id) || data.id <= 0) || (!data.postType)) {
                    throw '参数错误';
                }

                switch (data.postType) {
                    case 'add':
                        responseData.data = await ctx.service.ledger.addNode(tenderId, data.id);
                        break;
                    case 'delete':
                        responseData.data = await ctx.service.ledger.deleteNode(tenderId, data.id);
                        break;
                    case 'up-move':
                        responseData.data = await ctx.service.ledger.upMoveNode(tenderId, data.id);
                        break;
                    case 'down-move':
                        responseData.data = await ctx.service.ledger.downMoveNode(tenderId, data.id);
                        break;
                    case 'up-level':
                        responseData.data = await ctx.service.ledger.upLevelNode(tenderId, data.id);
                        break;
                    case 'down-level':
                        responseData.data = await ctx.service.ledger.downLevelNode(tenderId, data.id);
                        break;
                    default:
                        throw '未知操作';
                }
            } catch (err) {
                responseData.err = 1;
                responseData.msg = err;
                console.log(err);
            }

            ctx.body = responseData;
        }

        /**
         * 提交更新数据
         * @param ctx
         * @return {Promise<void>}
         */
        async updateInfo(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);
                if (!tenderData || tenderData.user_id !== ctx.session.sessionUser.accountId || this._ledgerReadOnly(tenderData)) {
                    throw '标段数据错误';
                }
                const data = JSON.parse(ctx.request.body.data);
                if (data instanceof Array) {
                    responseData.data = await ctx.service.ledger.updateInfos(tenderId, data);
                } else {
                    responseData.data = await ctx.service.ledger.updateInfo(tenderId, data);
                }
            } catch (err) {
                responseData.err = 1;
                responseData.msg = err;
            }

            ctx.body = responseData;
        }

        async update(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);
                if (!tenderData || tenderData.user_id !== ctx.session.sessionUser.accountId || this._ledgerReadOnly(tenderData)) {
                    throw '标段数据错误';
                }
                const data = JSON.parse(ctx.request.body.data);
                responseData.data = await ctx.service.ledger.updateCalc(tenderId, data);
            } catch (err) {
                responseData.err = 1;
                responseData.msg = err;
            }

            ctx.body = responseData;
        }

        /**
         * 复制粘贴整块
         * @param ctx
         * @return {Promise<void>}
         */
        async pasteBlock(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);
                if (!tenderData || tenderData.user_id !== ctx.session.sessionUser.accountId || this._ledgerReadOnly(tenderData)) {
                    throw '标段数据错误';
                }
                const data = JSON.parse(ctx.request.body.data);
                if ((isNaN(data.id) || data.id <= 0) || (!data.block || data.block.length <= 0)) {
                    throw '参数错误';
                }

                responseData.data = await ctx.service.ledger.pasteBlock(tenderId, data.id, data.block);
            } catch (err) {
                responseData.err = 1;
                responseData.msg = err;
            }

            ctx.body = responseData;
        }

        /**
         * 从标准项目表添加数据
         * @param ctx
         * @returns {Promise<void>}
         */
        async addFromStandardLib(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);
                if (!tenderData || tenderData.user_id !== ctx.session.sessionUser.accountId || this._ledgerReadOnly(tenderData)) {
                    throw '标段数据错误';
                }
                const data = JSON.parse(ctx.request.body.data);
                if ((isNaN(data.id) || data.id <= 0) || !data.stdType || !data.stdNode) {
                    throw '参数错误';
                }
                //todo 校验项目是否使用该库的权限

                let stdLib;
                switch (data.stdType) {
                    case 'chapter':
                        stdLib = ctx.service.stdChapter;
                        break;
                    case 'bills':
                        stdLib = ctx.service.stdBills;
                        break;
                    default:
                        throw '未知标准库';
                }
                const stdData = await stdLib.getDataByDataId(data.stdLibId, data.stdNode);
                const addType = stdDataAddType.withParent;
                switch (addType) {
                    case stdDataAddType.self:
                        responseData.data = await ctx.service.ledger.addStdNode(tenderId, data.id, stdData);
                        break;
                    case stdDataAddType.withParent:
                        responseData.data = await ctx.service.ledger.addStdNodeWithParent(tenderId, stdData, stdLib);
                        break;
                    default:
                        throw '未知添加方法';
                }
            } catch (err) {
                responseData.err = 1;
                responseData.msg = err;
            }

            ctx.body = responseData;
        }

        /**
         * 批量插入数据
         *
         * data = {id, batchData, batchType}
         * data.batchType = 'batchInsertChild'/'batchInsertNext'
         * data.batchData = [{name, children}] -- 项目节列表
         * data.batchData.children = [{code, name, unit, unit_price, quantity}] -- 工程量清单列表
         *
         * @param ctx
         * @returns {Promise<void>}
         */
        async batchInsert(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);
                if (!tenderData || tenderData.user_id !== ctx.session.sessionUser.accountId || this._ledgerReadOnly(tenderData)) {
                    throw '标段数据错误';
                }
                const data = JSON.parse(ctx.request.body.data);
                if ((isNaN(data.id) || data.id <= 0) || !data.batchType) {
                    throw '参数错误';
                }

                switch (data.batchType) {
                    case 'batchInsertChild':
                        responseData.data = await ctx.service.ledger.batchInsertChild(tenderId, data.id, data.batchData);
                        break;
                    case 'batchInsertNext':
                        responseData.data = await ctx.service.ledger.batchInsertNext(tenderId, data.id, data.batchData);
                        break;
                    default:
                        throw '参数错误';
                }
            } catch (err) {
                responseData.err = 1;
                responseData.msg = err;
            }

            ctx.body = responseData;
        }

        /**
         * 台账变更页面
         *
         * @param {object} ctx - egg全局变量
         * @return {void}
         */
        async change(ctx) {
            const renderData = {};
            await this.layout('ledger/change.ejs', renderData);
        }

        /**
         * 计量台账页面
         *
         * @param {object} ctx - egg全局变量
         * @return {void}
         */
        async index(ctx) {
            const renderData = {};
            await this.layout('ledger/index.ejs', renderData);
        }
    }

    return LedgerController;
};
