/**
 * 工料机相关控制器
 *
 * @author CaiAoLin
 * @date 2017/6/22
 * @version
 */
const BaseController = require("../../common/base/base_controller");
const GLJTypeConst = require("../../common/const/glj_type_const");
const GLJListModel = require("../models/glj_list_model");
const UnitPriceModel = require("../models/unit_price_model");
const MixRatioModel = require("../models/mix_ratio_model");
const UnitPriceFileModel = require("../models/unit_price_file_model");
let logger = require("../../../logs/log_helper").logger;
let consts = require('../../main/models/project_consts');
let glj_type_util = require('../../../public/cache/std_glj_type_util');
let ration_glj_facade = require('../../ration_glj/facade/ration_glj_facade');
let mongoose = require('mongoose');
let ration = mongoose.model('ration');
let projectModel = mongoose.model('projects');
let _ = require('lodash');
let glj_facade = require('../facade/glj_facade');
const commonFacade = require('../../main/facade/common_facade');
const ProjectModel = require('../../pm/models/project_model').project;
class GLJController extends BaseController {

    /**
     * 构造函数
     *
     * @return {void}
     */
    constructor() {
        let parent = super();
        parent.title = '工料机';
    }

    /**
     * 获取工料机相关数据
     *
     * @param {object} request
     * @param {object} response
     * @return {void}
     */
    async getGljList(request, response) {
        // 标段id
        let projectId = request.body.project_id;
        projectId = parseInt(projectId);
        let responseData = await getGLJListByProjectID(projectId);
        responseData.hostname = request.hostname;
        response.json(responseData);
    }

    /**
     * project getData 接口
     * @param projectID
     * @param callback
     */
    getData(projectID, callback){
        let start = +new Date();
        getGLJListByProjectID(projectID).then(function(result){
            let end = +new Date();
            console.log("项目工料机模块取数据总时间-----"+(end - start));
            // 项目工料机数据，这里只有最基础数据，调价后数据在 rpt_construct_data_util.js 的 assembleData() 方法中专门封装（在这里处理不了）。
            callback(result.err,consts.projectConst.PROJECTGLJ,result.data);
        })
    }
    async updateRatio(request, response) {
      let data = JSON.parse(request.body.data);
      let model = new MixRatioModel();
      if(data.type == 'delete'){
        await model.deleteById(data.id);
      }else{
        await model.updateById(data.id, data.doc);
      }
      let unitPriceUpdate = {
        base_price: data.base_price,
          market_price: data.market_price
      };
      let unitPriceModel = new UnitPriceModel();
      let unitPriceResult = await unitPriceModel.updatePrice({id:data.pid}, unitPriceUpdate);
      response.json(unitPriceResult);
    }



    /**
     * 更新数据
     *
     * @param {object} request
     * @param {object} response
     * @return {void}
     */
    async updateData(request, response) {
        let field = request.body.field;
        let value = request.body.value;
        let extend = request.body.extend;
        value = value === 'true' ? 1 : value;
        value = value === 'false' ? 0 : value;
        let id = request.body.id;

        let responseData = {
            err: 0,
            msg: ''
        };
        try {
            // 可编辑的字段
            let editableField = ['is_evaluate','unit_price.taxRate', 'unit_price.market_price', 'is_adjust_price', 'mix_ratio.consumption','is_eval_material','no_tax_eqp','is_coe_adjust','is_info_adjust','FI','FO','standardPrice','riskCoe',
                'supply', 'supply_quantity','delivery_address','delivery','materialType','materialCoe','is_main_material','originPlace','vender','qualityGrace','brand','remark'];
            if (editableField.indexOf(field) < 0) {
                throw '对应字段不能编辑';
            }

            let modelString = 'glj';
            // 切割字段
            let fieldArray = field.split('.');
            modelString = fieldArray.length > 1 ? fieldArray[0] : modelString;
            field = fieldArray.length > 1 ? fieldArray[1] : field;

            // 组合数据
            let updateData = new Object();
            updateData[field] = value;

            let result = false;
            let model = null;
            switch (modelString) {
                case 'glj':
                    if (extend&&extend !== '') {
                        extend = JSON.parse(extend);
                        for (let code in extend) {
                            updateData[code] = extend[code];
                        }
                    }
                    console.log(updateData);
                    model = new GLJListModel();
                    // 更新数据
                    result = await model.updateById(id, updateData);
                    break;
                case 'unit_price':
                    model = new UnitPriceModel();
                    // 更新数据
                    result = await model.updatePrice({id: id}, updateData, extend);

                    break;
                case 'mix_ratio':
                    let marketPrice = request.body.market_price;
                    let basePrice = request.body.base_price;

                    model = new MixRatioModel();
                    result = await model.updateById(id, updateData);

                    if (result && marketPrice && basePrice) {
                        // 修改后更新父节点的项目工料机市场单价
                        let mixRatioData = await model.findDataByCondition({id: id});
                        if (mixRatioData.length <= 0) {
                            break;
                        }
                        let indexList = ['code','name','specs','unit','type'];
                        let keyList = mixRatioData.connect_key.split("|-|");
                        // 更新市场单价和基价单价
                        let condition = {unit_price_file_id: mixRatioData.unit_price_file_id};
                        for(let i = 1;i<keyList.length;i++){
                            if(keyList[i]!='null'){
                                condition[indexList[i]]=keyList[i];
                            }
                        }
                        let unitPriceUpdate = {
                            base_price: basePrice,
                            market_price: marketPrice
                        };
                        let unitPriceModel = new UnitPriceModel();
                        let unitPriceResult = await unitPriceModel.updatePrice(condition, unitPriceUpdate);
                        if (!unitPriceResult) {
                            throw '更新单价数据失败';
                        }
                    }

                    break;
            }

            if (!result) {
                throw '更新失败';
            }
        } catch (error) {
            console.log('error:' + error);
            responseData.err = 1;
        }

        response.json(responseData);
    }

    /**
     * 加载配合比相关数据
     *
     * @return {void}
     */
    async getRatio(request, response) {
        let projectGLJId = request.body.id;
        let projectId = request.body.project_id;
        let responseData = {
            err: 0,
            data: null
        };
        try {
            // 获取标段对应的单价文件id
            let unitPriceFileId = await commonFacade.getUnitPriceFileId(projectId);
            if (unitPriceFileId <= 0) {
                throw '没有对应的单价文件';
            }

            let gljListModel = new GLJListModel();
            let result = await gljListModel.getCompositionList(projectGLJId, unitPriceFileId);
            if (result.length <= 0) {
                throw '没有找到数据';
            }

            responseData.data = JSON.stringify(result);
        } catch (error) {
            console.log(error);
            responseData.err = 1;
        }

        response.json(responseData);
    }

    /**
     * 删除配合比数据
     *
     * @param {object} request
     * @param {object} response
     * @return {void}
     */
    async deleteMixRatio(request, response) {
        if(request.body.data){
          let data = request.body.data;
          request.body = JSON.parse(data);
        }
        let id = request.body.id;
        id = parseInt(id);
        let responseData = {
            err: 0,
            msg: ''
        };
        try {
            if (isNaN(id) || id <= 0) {
                throw '参数错误';
            }

            let mixRatioModel = new MixRatioModel();
            let result = await mixRatioModel.deleteById(id);
            if (!result) {
                throw '删除失败';
            }
        } catch (error) {
            responseData.err = 1;
            responseData.msg = error;
        }
        response.json(responseData);
    }

    //添加组成物
    async addMixRatio(request,response){
        let result={
            error:0
        };
        try {
            let data = request.body.data;
            data = JSON.parse(data);
            let gljList = data.gljList, parentInfo = data.parentInfo,mixRatios = [];
            let projectGljModel = new GLJListModel();
            let mixRatioModel = new MixRatioModel();
            if(gljList.length > 0){
                let [unitFileId,ext] = await ration_glj_facade.prepareExtData(gljList[0].project_id,request.session.sessionCompilation);
                console.log(ext);
                for(let g of gljList){
                    let newProjectGLJ = await projectGljModel.addList(g,unitFileId,ext);
                    let mixRatio = {
                        glj_id:newProjectGLJ.glj_id,
                        consumption:0,
                        unit_price_file_id:unitFileId,
                        connect_key:parentInfo.connect_key,
                        type: newProjectGLJ.type,
                        code: newProjectGLJ.code,
                        specs:newProjectGLJ.specs,
                        name:newProjectGLJ.name,
                        unit:newProjectGLJ.unit,
                        model:newProjectGLJ.model
                    };
                    newProjectGLJ.ratio_data = await mixRatioModel.add(mixRatio);
                    mixRatios.push(newProjectGLJ);
                }

            }

            result.data = mixRatios;
        }catch (err){
            logger.err(err);
            result.error=1;
            result.message = err.message;
        }
        response.json(result);
    }
    /**
     * 获取项目与单价文件对应的数据
     *
     * @param {object} request
     * @param {object} response
     * @return {void}
     */
    async getProjectInfo(request, response) {
        if(typeof request.body.data == "string"){
            request.body = JSON.parse(request.body.data)
        }
        let projectId = request.body.project_id;
        let rootProjectID = request.body.rootProjectID;
        projectId = parseInt(projectId);
        const notDeleted = [{deleteInfo: null}, {'deleteInfo.deleted': false}];
        let responseData = {
            err: 0,
            data: null
        };
        try {
            let sessionUserData = request.session.sessionUser;
            //获取当前单位工程
            let currentTender = await projectModel.findOne({ID: projectId, $or: notDeleted});
            // 获取对应用户所有的建设项目数据
            let projectList = await ProjectModel.getUserProjectData(sessionUserData.id,request.session.sessionCompilation._id);
            //获取对应用户所有文件夹
            let folders = await projectModel.find({userID: sessionUserData.id, $or: notDeleted, projType: 'Folder'}, {_id: 0, name: 1, ID: 1, NextSiblingID: 1, ParentID: 1});
            if(currentTender === null){
                throw '当前单位工程不存在';
            }
            if (projectList === null) {
                throw '没有找到对应的项目数据';
            }
            // 转换mongoose数据
            projectList = JSON.stringify(projectList);
            projectList = JSON.parse(projectList);

            let result = {
                self: [],
                other: [],
                treeData: []
            };
            for (let index in projectList) {
                // 获取对应的单价文件
                let unitPriceFileModel = new UnitPriceFileModel();
                let unitPriceFileData = await unitPriceFileModel.getDataByRootProject(projectList[index].ID);
                projectList[index].unitPriceList = unitPriceFileData;

                // 归类
                if (rootProjectID == projectList[index].ID) {
                    //剔除自身
                    let currentUsedUF = currentTender.property.unitPriceFile.id;
                    result.self = _.filter(unitPriceFileData, function (uf) {
                        return uf.id !== currentUsedUF;
                    });
                    result.currentProjectName =  projectList[index].name;
                } else {
                    result.other.push(projectList[index]);
                }
                result.treeData.push({name: projectList[index].name, ID: projectList[index].ID, NextSiblingID: projectList[index].NextSiblingID, ParentID: projectList[index].ParentID});
            }
            result.treeData = result.treeData.concat(folders);
            responseData.data = result;
            response.json(responseData);

        } catch (error) {
            responseData.err = 1;
            response.json(responseData);
        }
    }

    /**
     * 更改单价文件
     *
     * @param {object} request
     * @param {object} response
     * @return {void}
     */
    async changeUnitPriceFile(request, response) {
        let projectId = request.body.project_id;
        let changeUnitPriceId = request.body.change_id;
        let newName = request.body.newName;
        let type = request.body.type;
        type = parseInt(type);
        let responseData = {
            err: 0,
            msg: ''
        };
        try {
            responseData.unitFile = await glj_facade.changeUnitFile({projectID:projectId}, {id:changeUnitPriceId,name:newName},type,request.session.sessionUser.id);
        } catch (error) {
            console.log(error);
            responseData.err = 1;
            responseData.msg = error;
        }

        response.json(responseData);
    }

    async checkUnitFileName(request, response){
        let result={
            error:0
        }
        try {
            let data = request.body.data;
            let nameExist = false;
            data = JSON.parse(data);
            let unitPriceFileModel = new UnitPriceFileModel();
            let count = await unitPriceFileModel.model.count({root_project_id:data.rootProjectID,name:data.name,deleteInfo:null});
            if(count>0){
                nameExist = true;
            }else {
                nameExist = false;
            }
            result.data= nameExist;
        }catch (err){
            console.log(err);
            result.error=1;
            result.message = err.message;
        }
        response.json(result);
    }

    /**
     * 单价文件另存为
     *
     * @param {object} request
     * @param {object} response
     * @return {void}
     */
    async unitPriceSaveAs(request, response) {
        let responseData = {
            err: 0,
            msg: ''
        };
        let projectId = request.body.project_id;
        let name = request.body.name;
        try {
            // 当前单价文件id
            let currentUnitPriceId = await commonFacade.getUnitPriceFileId(projectId);
            // 获取当前项目的rootProjectId
            let projectData = await ProjectModel.getProject(projectId);
            let rootProjectId = projectData.property.rootProjectID !== undefined ? projectData.property.rootProjectID : 0;

            // 新增单价文件信息
            let unitPriceFileModel = new UnitPriceFileModel();
            let insertData = {
                name: name,
                project_id: projectId,
                user_id: request.session.sessionUser.id,
                root_project_id: rootProjectId
            };
            let addResult = await unitPriceFileModel.add(insertData);
            if (!addResult) {
                throw '单价文件另存为失败';
            }

            // 查找对应单价文件的项目工料机数据
            let unitPriceModel = new UnitPriceModel();
            let copyResult = await unitPriceModel.copyNotExist(currentUnitPriceId, addResult.id,projectId);
            // 复制成功后更改project数据
            if (!copyResult) {
                throw '复制数据失败';
            }
           await ProjectModel.updateUnitFileToProject(projectId,{id:addResult.id,name:addResult.name});
            responseData.data = addResult;
        } catch (error) {
            responseData.err = 1;
            responseData.msg = error;
        }

        response.json(responseData);
    }

    /**
     * 获取项目中所有组成物数据(用户缓存到前端变量)
     *
     * @param {object} request
     * @param {object} response
     * @return {void}
     */
    async getComposition(request, response) {
        let projectId = request.body.project_id;
        projectId = parseInt(projectId);

        let responseData = {
            err: 0,
            data: null
        };
        try {
            // 当前单价文件id
            let currentUnitPriceId = await commonFacade.getUnitPriceFileId(projectId);
            if (currentUnitPriceId <= 0) {
                throw '没有找到对应的单价文件';
            }

            // 获取组成物数据
            let mixRatioModel = new MixRatioModel();
            let compositionData = await mixRatioModel.findDataByCondition({unit_price_file_id: currentUnitPriceId}, null, false);
            if (compositionData === null) {
                throw '没有找到组成物数据';
            }
            compositionData = JSON.parse(JSON.stringify(compositionData));
            // 查找对应的单价数据
            let unitPriceModel = new UnitPriceModel();
            let unitPriceData = await unitPriceModel.findDataByCondition({unit_price_file_id: currentUnitPriceId}, null, false, 'glj_id');

            // 整理数据
            let result = {};
            for(let composition of compositionData) {
                let tmpId = composition.glj_id !== undefined ? composition.glj_id : -1;
                let tmpData = {
                    market_price: unitPriceData[tmpId] !== undefined ?
                        unitPriceData[tmpId].market_price : 0,
                    base_price: unitPriceData[tmpId] !== undefined ?
                        unitPriceData[tmpId].base_price : 0,
                    consumption: composition.consumption,
                    glj_type: composition.glj_type,
                    connect_code: composition.connect_code
                };
                if (result[tmpId] === undefined) {
                    result[tmpId] = [];
                }
                result[tmpId].push(tmpData);
            }
            responseData.data = result;
        } catch (error) {
            responseData.err = 1;
            responseData.data = null;
        }

        response.json(responseData);
    }

    /**
     * 模拟定额插入
     *
     * @param {object} request
     * @param {object} response
     * @return {void}
     */
    async test(request, response) {
        // 从定额库获取的数据
        let data = {
            glj_id: 17,
            project_id: 1,
            code: '00010201',
            name: '土石方综合工日',
            specs: '',
            unit: '工日',
            type: GLJTypeConst.LABOUR,
            base_price: 50,
            market_price: 50
        };
        try {
            let gljListModel = new GLJListModel();
            let result = await gljListModel.addList(data);

        } catch (error) {
            console.log(error);
        }

        response.end('success');
    }

    /**
     * 模拟定额修改单价
     *
     * @param {object} request
     * @param {object} response
     * @return {void}
     */
    async testModify(request, response) {
        let projectId = request.query.project;
        // 修改数据
        let updateData = {
            code: '36290101',
            market_price: '13',
            name: '水(10)',
            project_id: projectId
        };

        try {
            let gljListModel = new GLJListModel();
            let result = await gljListModel.modifyMarketPrice(updateData);

            console.log(result);
        } catch (error) {
            console.log(error);
        }
        response.end('success');
    }

    /**
     * 测试删除
     *
     * @param {object} request
     * @param {object} response
     * @return {void}
     */
    async delete(request, response) {
        try {
            let gljListModel = new GLJListModel();
            let result = await gljListModel.deleteById(63);

            console.log(result);
        } catch (error) {
            console.log(error);
        }
        response.end('success');
    }

    async updateUnitPrice(req, res){
        let result={
            error:0
        }
        try {
            let data = req.body.data;
            data = JSON.parse(data);
            let unitPriceModel = new UnitPriceModel();
            // 更新数据
            let datas = await unitPriceModel.updateUnitPrice(data);
            result.data=datas;
        }catch (err){
            logger.err(err);
            result.error=1;
            result.message = err.message;
        }
        res.json(result);
    }
    async batchUpdatePrices(req, res){
        let result={
            error:0
        }
        try {
            let data = req.body.data;
            data = JSON.parse(data);
            let unitPriceModel = new UnitPriceModel();
            // 更新数据
            let datas = await unitPriceModel.batchUpdatePrices(data);
            result.data=datas;
        }catch (err){
            logger.err(err);
            result.error=1;
            result.message = err.message;
        }
        res.json(result);
    }
    async batchUpdateGLJProperty(req, res){
        let result={
            error:0
        };
        try {
            let data = req.body.data;
            data = JSON.parse(data);
            let tasks = [];
            for(let key in data){
                let doc = data[key];
                let query = {id:parseInt(key)};
                let task = {updateOne:{filter:query, update :doc}};
                tasks.push(task);
            }
            if(tasks.length > 0){
                let gljModel = new GLJListModel().model;
                await gljModel.bulkWrite(tasks);
            }
            result.data=data;
        }catch (err){
            logger.err(err);
            result.error=1;
            result.message = err.message;
        }
        res.json(result);
    }

    async batchUpdateConsumption(req,res){
        let result={
            error:0
        };
        try {
            let data = req.body.data;
            data = JSON.parse(data);
            let mixTasks = [],parent = null;
            for(let d of data){
                if(d.type == 'mix_ratio'){
                    let task = {updateOne:{filter:d.query, update :d.doc}};
                    mixTasks.push(task);
                }else if(d.type =='parent'){
                    parent = d;
                }
            }
            if(mixTasks.length > 0){
                let mixRatioModel = new MixRatioModel().model;
                await mixRatioModel.bulkWrite(mixTasks);
            }
            if(parent){
                let indexList = ['code','name','specs','unit','type'];
                let keyList = parent.connect_key.split("|-|");
                let condition = {unit_price_file_id: parent.unit_price_file_id};
                for(let i = 1;i<keyList.length;i++){
                    if(keyList[i]!='null'){
                        condition[indexList[i]]=keyList[i];
                    }
                }
                let unitPriceUpdate = {
                    base_price: parent.base_price,
                    market_price: parent.market_price
                };
                let unitPriceModel = new UnitPriceModel();
                let unitPriceResult = await unitPriceModel.updatePrice(condition, unitPriceUpdate);
                if (!unitPriceResult) {
                    throw '更新单价数据失败';
                }
            }
            result.data = "ok";
        }catch (err){
            logger.err(err);
            result.error=1;
            result.message = err.message;
        }
        res.json(result);
    }

    async updateEvaluateMaterial(request, response){
        let result={error:0};
        try {
            let data = JSON.parse(request.body.data);
            result.data = await glj_facade.updateEvaluateMaterial(data);
        }catch (err){
            logger.err(err);
            result.error=1;
            result.message = err.message;
        }
        response.json(result);
    }

    async modifyKeyValue(req,res){//修改工料机关键的属性：名称、类型、规格、型号等
        let result={
            error:0
        }
        try {
            let data = req.body.data;
            data = JSON.parse(data);
            let gljListModel = new GLJListModel();
            let ration_data = await ration.findOne(data.ration);
            //  修改项目工料机
            let projcetGLJ = await gljListModel.modifyGLJ(data.updateData,ration_data);

           // let datas = await gljListModel.addList(data);
            result.data=projcetGLJ;
        }catch (err){
            logger.err(err);
            result.error=1;
            result.message = err.message;
        }
        res.json(result);
    }

    async getProjectGLJsByProjectID(projectId){
        return await getGLJListByProjectID(projectId)
    }

}

/**
 * 取项目工料机列表
 * @param projectId
 * @returns {Promise.<void>}
 */
async function getGLJListByProjectID(projectId){
    let responseData = {
        err: 0,
        msg: '',
        data: {}
    };
    try {
        if (isNaN(projectId) || projectId <= 0) {
            throw '标段id有误';
        }
        // 获取标段对应的单价文件id
        let unitPriceFileId = await commonFacade.getUnitPriceFileId(projectId);
        if (unitPriceFileId <= 0) {
            throw '没有对应的单价文件';
        }
        // 获取使用该单价文件的项目数据
        let tenderData = await ProjectModel.getTenderByUnitPriceFileId(unitPriceFileId);
        let usedTenderList = [];
        let usedUnitPriceInfo = {};
        if (tenderData !== null) {
            for (let tmp of tenderData) {
                usedTenderList.push(tmp.name);
                usedUnitPriceInfo.name = tmp.property.unitPriceFile.name;
                usedUnitPriceInfo.id = tmp.property.unitPriceFile.id;
            }
        }
        // 先获取对应标段的项目工料机数据
        let gljListModel = new GLJListModel();
        let [gljList, mixRatioConnectData,mixRationMap,unitPriceMap] = await gljListModel.getListByProjectId(projectId, unitPriceFileId);
        responseData.data.gljList = gljList;
        responseData.data.mixRatioConnectData = mixRatioConnectData;
        responseData.data.mixRatioMap = mixRationMap;
        responseData.data.usedTenderList = usedTenderList;
        responseData.data.unitPriceMap = unitPriceMap;
        let gljTypeMap = glj_type_util.getStdGljTypeCacheObj().innerGljTypeObj;
        responseData.data.constData = {
            materialIdList: gljListModel.materialIdList,
            ownCompositionTypes: gljListModel.ownCompositionTypes,
            roomId: unitPriceFileId,
            GLJTypeConst: JSON.stringify(GLJTypeConst),
            usedUnitPriceInfo: usedUnitPriceInfo,
            gljTypeMap:gljTypeMap
        };
    } catch (error) {
        console.log(error);
        responseData.err = 1;
        responseData.msg = error;
    }
    return responseData;
}

module.exports = GLJController;
