'use strict';

/**
 *
 *
 * @author Mai
 * @date 2018/8/14
 * @version
 */

const moment = require('moment');
const sendToWormhole = require('stream-wormhole');
const fs = require('fs');
const path = require('path');
const audit = require('../const/audit');
const codeRuleConst = require('../const/code_rule');
const changeConst = require('../const/change');
// const tenderMenu = require('../../config/menu').tenderMenu;

module.exports = app => {
    class ChangeController extends app.BaseController {
        /**
         * 构造函数
         *
         * @param {Object} ctx - egg全局变量
         * @return {void}
         */
        constructor(ctx) {
            super(ctx);
            ctx.showProject = true;
            ctx.showTender = true;
            ctx.showTitle = true;
        }

        async _filterChanges(ctx, status = 0) {
            const tenderId = ctx.params.id;
            ctx.session.sessionUser.tenderId = tenderId;
            const tender = await this.service.tender.getDataById(tenderId);
            const tenderList = await this.service.tender.getList();

            const page = ctx.page;
            const changes = await ctx.service.change.getListByStatus(tender.id, status);
            const total = await ctx.service.change.getCountByStatus(tender.id, status);
            if (changes !== null) {
                let i = 0;
                for (const c of changes) {
                    const status = c.status === audit.flow.status.uncheck ? 0 : 1;
                    // 根据审批人对当前变更令的状态取不同的展示方式。
                    let changeAudit = '';
                    let auditStatus = 0;
                    switch (c.status) {
                        case 1:
                            auditStatus = 1;
                            break;
                        case 2:
                            changeAudit = await ctx.service.changeAudit.getLastUser(c.cid, c.times, status);
                            auditStatus = changeAudit.uid === ctx.session.sessionUser.accountId ? 1 : 0;
                            break;
                        case 3:
                        case 4:
                            auditStatus = 0;
                            changeAudit = await ctx.service.changeAudit.getLastUser(c.cid, c.times, status);
                            break;
                        case 5:
                            changeAudit = await ctx.service.changeAudit.getLastUser(c.cid, c.times - 1, status);
                            auditStatus = c.uid === ctx.session.sessionUser.accountId ? 1 : 0;
                            break;
                        case 6:
                            changeAudit = await ctx.service.changeAudit.getLastBackUser(c.cid, c.times);
                            const checkingAudit = await ctx.service.changeAudit.getLastUser(c.cid, c.times, status);
                            auditStatus = checkingAudit.uid === ctx.session.sessionUser.accountId ? 1 : 0;
                            break;
                        default:
                            break;
                    }
                    changes[i].changeAudit = changeAudit;
                    changes[i].auditStatus = auditStatus;
                    i++;
                }
            }

            // 分页相关
            const pageInfo = {
                page,
                total: parseInt(total / app.config.pageSize),
                queryData: JSON.stringify(ctx.urlInfo.query),
            };

            const filter = JSON.parse(JSON.stringify(audit.filter));
            filter.count = [];
            filter.count[filter.status.pending] = await ctx.service.change.getCountByStatus(tender.id, filter.status.pending);// await ctx.service.change.pendingDatas(tender.id, ctx.session.sessionUser.accountId);
            filter.count[filter.status.uncheck] = await ctx.service.change.getCountByStatus(tender.id, filter.status.uncheck);// await ctx.service.change.checkingDatas(tender.id, ctx.session.sessionUser.accountId);
            filter.count[filter.status.checking] = await ctx.service.change.getCountByStatus(tender.id, filter.status.checking);// await ctx.service.change.checkedDatas(tender.id, ctx.session.sessionUser.accountId);
            filter.count[filter.status.checked] = await ctx.service.change.getCountByStatus(tender.id, filter.status.checked);// await ctx.service.change.pendingDatas(tender.id, ctx.session.sessionUser.accountId);
            filter.count[filter.status.checkNo] = await ctx.service.change.getCountByStatus(tender.id, filter.status.checkNo);// await ctx.service.change.pendingDatas(tender.id, ctx.session.sessionUser.accountId);

            const codeRule = tender.c_rule ? JSON.parse(tender.c_rule) : [];
            for (const rule of codeRule) {
                switch (rule.rule_type) {
                    case codeRuleConst.measure.ruleType.tenderName:
                        rule.preview = tender.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;
                    default: break;
                }
            }

            const renderData = {
                uid: ctx.session.sessionUser.accountId,
                moment,
                tender,
                tenderList,
                pageInfo,
                changes,
                filter,
                status,
                codeRule,
                auditConst: audit.flow,
                changeConst,
                ruleType: codeRuleConst.ruleType.change,
                ruleConst: codeRuleConst.measure,
                tenderMenu: this.menu.tenderMenu,
                preUrl: '/tender/' + tenderId,
            };

            await this.layout('change/index.ejs', renderData, 'change/modal.ejs');
        }

        /**
         * 变更管理 页面 (Get)
         *
         * @param {Object} ctx - egg全局变量
         * @return {void}
         */
        async index(ctx) {
            try {
                console.log(ctx);
                await this._filterChanges(ctx);
            } catch (err) {
                this.log(err);
                ctx.redirect('/dashboard');
            }
        }

        /**
         *
         * @param {Object} ctx - egg全局变量
         * @return {void}
         */
        async newCode(ctx) {
            const responseData = {
                err: 0,
                msg: '',
                data: '',
            };
            try {
                const tenderId = ctx.params.id;
                if (!tenderId) {
                    throw '当前未打开标段';
                }
                const tenderData = await ctx.service.tender.getDataById(tenderId);
                const cCodeRule = JSON.parse(tenderData.c_rule);

                const code = [];
                for (const rule of cCodeRule) {
                    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.change.count({ tid: tenderId });
                            s = s + count;
                            code.push(s.substr(s.length - rule.format));
                            break;
                        default: break;
                    }
                }
                responseData.data = code.join(tenderData.c_connector !== null && tenderData.c_connector !== 3 ? codeRuleConst.measure.connectorString[tenderData.c_connector] : '');
            } catch (err) {
                responseData.err = 1;
                responseData.msg = err;
            }

            ctx.body = responseData;
        }

        /**
         * 新增变更 (Post)
         *
         * @param {Object} ctx - egg全局变量
         * @return {void}
         */
        async add(ctx) {
            try {
                const tenderId = ctx.params.id;
                if (!tenderId) {
                    throw '当前未打开标段';
                }
                const data = JSON.parse(ctx.request.body.data);
                if (!data.code || data.code === '' || !data.name || data.name === '') {
                    throw '提交数据错误';
                }

                const change = await ctx.service.change.add(tenderId, ctx.session.sessionUser.accountId, data.code, data.name);

                ctx.body = { err: 0, msg: '', data: change };
            } catch (err) {
                this.log(err);
                ctx.body = { err: 1, msg: err.toString() };
            }
        }

        /**
         * 变更管理 状态筛选 页面 (Get)
         * @param {Object} ctx - egg全局变量
         * @return {void}
         */
        async status(ctx) {
            try {
                const status = parseInt(ctx.params.status);
                await this._filterChanges(ctx, status);
            } catch (err) {
                this.logger.error(err);
                ctx.redirect('/tender/' + ctx.params.id + '/change');
            }
        }

        /**
         * 变更信息 页面 (Get)
         *
         * @param {Object} ctx - egg全局变量
         * @return {void}
         */
        async info(ctx) {
            try {
                const whiteList = this.ctx.app.config.multipart.whitelist;
                const tenderid = ctx.session.sessionUser.tenderId !== undefined ? ctx.session.sessionUser.tenderId : ctx.params.id;
                const tender = await this.service.tender.getDataById(tenderid);
                const change = await ctx.service.change.getDataByCondition({ cid: ctx.params.cid });

                // 后台判断当前人查看info状态
                const auditStatus = await ctx.service.changeAudit.getStatusByChange(change);

                // 获取附件列表
                const attList = await ctx.service.changeAtt.getAllDataByCondition({ where: { cid: ctx.params.cid } });

                // 根据auditStatus获取审批人列表
                const auditList = await ctx.service.changeAudit.getListByStatus(change, auditStatus);

                // 获取已选清单
                const changeList = await ctx.service.changeAuditList.getAllDataByCondition({ where: { cid: ctx.params.cid } });

                const renderData = {
                    uid: ctx.session.sessionUser.accountId,
                    tender,
                    change,
                    changeConst,
                    auditStatus,
                    auditConst: audit.flow,
                    attList,
                    whiteList,
                    auditList,
                    changeList,
                    tpUnit: ctx.tender.info.decimal.tp,
                };
                // 根据auditStatus状态获取的不同的数据
                if (auditStatus === 1 || auditStatus === 2) {
                    // 获取标准清单列表
                    const dealBillList = await ctx.service.dealBills.getAllDataByCondition({ where: { tender_id: tenderid } });
                    // 获取清单列表和台账清单列表
                    const ledger = await ctx.service.ledger.getDataByTenderId(tenderid, -1);
                    const pos = await ctx.service.pos.getPosData({ tid: tenderid });
                    renderData.ledger = ledger;
                    renderData.pos = pos;

                    renderData.dealBillList = dealBillList;
                    renderData.changeUnits = ctx.tender.info.precision;
                    // 根据清单获取提交数据和计算总金额
                    const changeListData = [];
                    const changeWhiteListData = [];
                    let ototalCost = 0;
                    let ctotalCost = 0;
                    for (const cl of changeList) {
                        const cLArray = [
                            cl.code,
                            cl.name,
                            cl.unit,
                            cl.unit_price,
                            cl.oamount,
                            cl.camount,
                            cl.detail,
                            cl.lid,
                        ];
                        ototalCost += ctx.helper.accMul(cl.unit_price, cl.oamount);
                        ctotalCost += ctx.helper.accMul(cl.unit_price, cl.camount);
                        if (cl.lid !== 0) {
                            changeListData.push(cLArray.join(';'));
                        } else {
                            changeWhiteListData.push(cLArray.join(';'));
                        }
                    }
                    renderData.changeListData = changeListData.join('^_^');
                    renderData.changeWhiteListData = changeWhiteListData.join('^_^');
                    renderData.ototalCost = ototalCost;
                    renderData.ctotalCost = ctotalCost;

                    // 获取公司列表
                    const companyList = await ctx.service.changeCompany.getAllDataByCondition({ where: { tid: tenderid } });
                    renderData.companyList = companyList;
                } else if (auditStatus === 3 || auditStatus === 4 || auditStatus === 5 || auditStatus === 7) {
                    // 展示页左侧审批流程列表和清单审批列表数据
                    const auditList2 = await ctx.service.changeAudit.getListGroupByTimes(change.cid, change.times);

                    // 展示页右侧审批流程列表
                    const auditList3 = [];
                    for (let time = 1; time <= change.times; time++) {
                        const auditTimeList = [];
                        for (const al of auditList) {
                            if (al.times === time) {
                                auditTimeList.push(al);
                            }
                        }
                        auditList3.push(auditTimeList);
                    }
                    renderData.auditList3 = auditList3;

                    renderData.changeList = changeList.sort();
                    let ototalCost = 0;
                    let ctotalCost = 0;
                    let stotalCost = 0;
                    const auditTotalCost = [];
                    for (const cl of changeList) {
                        ototalCost += parseFloat(ctx.helper.roundNum(ctx.helper.accMul(cl.unit_price, cl.oamount), renderData.tpUnit));
                        ctotalCost += parseFloat(ctx.helper.roundNum(ctx.helper.accMul(cl.unit_price, cl.camount), renderData.tpUnit));
                        stotalCost += cl.samount !== '' ? parseFloat(ctx.helper.roundNum(ctx.helper.accMul(cl.unit_price, cl.samount), renderData.tpUnit)) : 0;
                        const audit_amount = cl.audit_amount !== null && cl.audit_amount !== '' ? cl.audit_amount.split(',') : '';
                        auditTotalCost.push(audit_amount);
                    }
                    renderData.ototalCost = ototalCost;
                    renderData.ctotalCost = ctotalCost;
                    renderData.stotalCost = stotalCost;

                    // 清单表页赋值
                    for (const [index, au] of auditList2.entries()) {
                        if (au.usite !== 0) {
                            au.list_amount = [];
                            au.totalCost = 0;
                            for (const [auindex, at] of auditTotalCost.entries()) {
                                au.list_amount.push(at[index - 1]);
                                au.totalCost += at[index - 1] !== undefined ? parseFloat(ctx.helper.roundNum(ctx.helper.accMul(changeList[auindex].unit_price, at[index - 1]), renderData.tpUnit)) : 0;
                            }
                        }
                    }
                    renderData.auditList2 = auditList2;
                } else if (auditStatus === 6) {
                    renderData.changeList = changeList.sort();
                    let ototalCost = 0;
                    let ctotalCost = 0;
                    const auditTotalCost = [];
                    const auditUnit = [];
                    for (const cl of changeList) {
                        ototalCost += parseFloat(ctx.helper.roundNum(ctx.helper.accMul(cl.unit_price, cl.oamount), renderData.tpUnit));
                        ctotalCost += parseFloat(ctx.helper.roundNum(ctx.helper.accMul(cl.unit_price, cl.camount), renderData.tpUnit));
                        const audit_amount = cl.audit_amount !== null && cl.audit_amount !== '' ? cl.audit_amount.split(',') : '';
                        auditTotalCost.push(audit_amount);
                    }
                    renderData.ototalCost = ototalCost;
                    renderData.ctotalCost = ctotalCost;

                    // 清单表页赋值
                    for (const [index, au] of auditList.entries()) {
                        if (au.usite !== 0) {
                            au.list_amount = [];
                            au.totalCost = 0;
                            if (au.uid === renderData.uid) {
                                for (const [auindex, at] of auditTotalCost.entries()) {
                                    if (at[index - 2] !== undefined) {
                                        au.list_amount.push(at[index - 2]);
                                        au.totalCost += parseFloat(ctx.helper.roundNum(ctx.helper.accMul(changeList[auindex].unit_price, at[index - 2]), renderData.tpUnit));
                                    } else if (at[index - 2] === undefined) {
                                        au.list_amount.push(changeList[auindex].camount);
                                        au.totalCost += parseFloat(ctx.helper.roundNum(ctx.helper.accMul(changeList[auindex].unit_price, changeList[auindex].camount), renderData.tpUnit));
                                    }
                                }
                            } else {
                                for (const [auindex, at] of auditTotalCost.entries()) {
                                    au.list_amount.push(at[index - 1]);
                                    au.totalCost += at[index - 1] !== undefined ? parseFloat(ctx.helper.roundNum(ctx.helper.accMul(changeList[auindex].unit_price, at[index - 1]), renderData.tpUnit)) : 0;
                                }
                            }
                        }
                    }
                }
                renderData.auditList = auditList;
                await this.layout('change/info.ejs', renderData, 'change/info_modal.ejs');
            } catch (err) {
                this.log(err);
                ctx.redirect('/tender/' + ctx.params.id + '/change');
            }
        }

        /**
         * 变更令上报和保存
         * @param {Object} ctx - egg全局变量
         * @return {void}
         */
        async save(ctx) {
            try {
                // console.log(ctx.request.body);
                const result = await ctx.service.change.save(ctx.request.body, ctx.session.sessionUser.tenderId);
                if (!result) {
                    throw '上报失败';
                }
                ctx.redirect('/tender/' + ctx.session.sessionUser.tenderId + '/change');
            } catch (err) {
                this.log(err);
                ctx.redirect('/tender/' + ctx.session.sessionUser.tenderId + '/change/' + ctx.request.body.cid + '/info');
            }
        }

        /**
         * 变更令审批
         * @param {Object} ctx - egg全局变量
         * @return {void}
         */
        async approval(ctx) {
            try {
                console.log(ctx.request.body);
                const status = parseInt(ctx.request.body.status);
                let result = false;
                switch (status) {
                    case 3:// 审批通过
                        result = await ctx.service.change.approvalSuccess(ctx.request.body);
                        break;
                    case 4:// 审批终止
                        result = await ctx.service.change.approvalStop(ctx.request.body);
                        break;
                    case 5:// 审批退回到原报人
                        result = await ctx.service.change.approvalBack(ctx.request.body);
                        break;
                    case 6:// 审批退回到上一个审批人
                        result = await ctx.service.change.approvalBackNew(ctx.request.body);
                        break;
                    default:break;
                }
                if (!result) {
                    throw '审批失败';
                }
                ctx.redirect('/tender/' + ctx.session.sessionUser.tenderId + '/change');
            } catch (err) {
                console.log(err);
                ctx.redirect('/tender/' + ctx.session.sessionUser.tenderId + '/change/' + ctx.request.body.change_id + '/info');
            }
        }

        /**
         * 变更公司管理
         * @param {Object} ctx - egg全局变量
         * @return {void}
         */
        async updateCompany(ctx) {
            const responseData = {
                err: 0,
                msg: '',
                data: '',
            };
            try {
                const data = JSON.parse(ctx.request.body.data);
                if (data.tid === undefined || data.uci === undefined || data.uc === undefined || data.ac === undefined) {
                    throw '参数有误';
                }
                const [addCompany, selectCompany] = await ctx.service.changeCompany.setCompanyList(data);
                responseData.data = { add: addCompany, select: selectCompany };
            } catch (err) {
                responseData.err = 1;
                responseData.msg = err;
            }

            ctx.body = responseData;
        }

        /**
         * 上传附件
         * @param {Object} ctx - egg全局变量
         * @return {void}
         */
        async uploadFile(ctx) {
            const responseData = {
                err: 0,
                msg: '',
                data: [],
            };
            let stream;
            try {
                stream = await ctx.getFileStream();
                const create_time = Date.parse(new Date()) / 1000;
                const fileInfo = path.parse(stream.filename);
                const dirName = 'app/public/upload/changes/' + moment().format('YYYYMMDD');
                const fileName = 'changes' + create_time + fileInfo.ext;

                // 判断文件夹是否存在，不存在则直接创建文件夹
                if (!fs.existsSync(path.join(this.app.baseDir, dirName))) {
                    await fs.mkdirSync(path.join(this.app.baseDir, dirName));
                }
                // 保存文件
                await ctx.helper.saveStreamFile(stream, path.join(this.app.baseDir, dirName, fileName));
                // 保存数据到att表
                const fileData = {
                    in_time: create_time,
                    filename: fileInfo.name,
                    fileext: fileInfo.ext,
                    filesize: stream.fields.size,
                    filepath: path.join(dirName, fileName),
                };
                const result = await ctx.service.changeAtt.save(stream.fields, fileData, ctx.session.sessionUser.accountId);
                if (result.effectRows !== 1) {
                    throw '导入数据库保存失败';
                }
                fileData.in_time = moment(create_time * 1000).format('YYYY-MM-DD');
                fileData.filesize = await ctx.helper.bytesToSize(stream.fields.size);
                fileData.id = result.insertId;
                responseData.data = fileData;
            } catch (err) {
                this.log(err);
                // 失败需要消耗掉stream 以防卡死
                if (stream) {
                    await sendToWormhole(stream);
                }
                this.setMessage(err.toString(), this.messageType.ERROR);
            }
            ctx.body = responseData;
        }

        /**
         * 下载附件
         * @param {Object} ctx - egg全局变量
         * @return {void}
         */
        async downloadFile(ctx) {
            const id = ctx.params.id;
            if (id) {
                try {
                    const fileInfo = await ctx.service.changeAtt.getDataById(id);
                    if (fileInfo !== undefined && fileInfo !== '') {
                        const fileName = path.join(this.app.baseDir, fileInfo.filepath);
                        ctx.response.set({
                            'Content-Type': 'application/octet-stream',
                            'Content-Disposition': 'attachment; filename=' + fileInfo.filename + fileInfo.fileext,
                            'Content-Length': fileInfo.filesize,
                        });
                        ctx.body = await fs.createReadStream(fileName);
                    } else {
                        throw '不存在该文件';
                    }
                } catch (err) {
                    this.log(err);
                    this.setMessage(err.toString(), this.messageType.ERROR);
                }
            }
        }

        /**
         * 删除附件
         * @param {Object} ctx - egg全局变量
         * @return {void}
         */
        async deleteFile(ctx) {
            const responseData = {
                err: 0,
                msg: '',
                data: '',
            };
            try {
                const data = JSON.parse(ctx.request.body.data);
                console.log(data.id);
                const fileInfo = await ctx.service.changeAtt.getDataById(data.id);
                if (fileInfo !== undefined && fileInfo !== '') {
                    // 先删除文件
                    await fs.unlinkSync(path.join(this.app.baseDir, fileInfo.filepath));
                    // 再删除数据库
                    await ctx.service.changeAtt.deleteById(data.id);
                    responseData.data = '';
                } else {
                    throw '不存在该文件';
                }

                // if (data.tid === undefined || data.uci === undefined || data.uc === undefined || data.ac === undefined) {
                //     throw '参数有误';
                // }
                // const [addCompany, selectCompany] = await ctx.service.changeCompany.setCompanyList(data);
                // responseData.data = { add: addCompany, select: selectCompany };
            } catch (err) {
                responseData.err = 1;
                responseData.msg = err;
            }

            ctx.body = responseData;
        }
    }

    return ChangeController;
};
