/**
 * Created by chen on 2017/8/2.
 */

let async_n = require("async");
let mongoose = require('mongoose');
let feeRateModel = mongoose.model('fee_rates');
let feeRateFileModel = mongoose.model('fee_rate_file');
let std_fee_rate_lib_model = mongoose.model('std_fee_rate_libs');
let billModel=require('../../main/models/bills');//mongoose.model('bills');
let projectsModel = mongoose.model('projects');
let consts = require('../../main/models/project_consts');
let _=require("lodash");
let template = require('../controllers/feerate_template');
let logger = require("../../../logs/log_helper").logger;
const uuidV1 = require('uuid/v1');
let EngineeringLibModel = require("../../users/models/engineering_lib_model");

module.exports={
    save:save,
    getData:getData,
    getFeeRateStandardsByProjectID:getFeeRateStandardsByProjectID,
    changeFeeRateStandard:changeFeeRateStandard,
    checkFeeRateName:checkFeeRateName,
    getChangeInfo:getChangeInfo,
    changeFeeRateFileFromCurrent:changeFeeRateFileFromCurrent,
    changeFeeRateFileFromOthers:changeFeeRateFileFromOthers,
    newFeeRateFile:newFeeRateFile,
    getFeeRatesByProject:getFeeRatesByProject,
    getGCFeeRateFiles: getGCFeeRateFiles ,
    setFeeRateToBill:setFeeRateToBill,
    updateFeeRate:updateFeeRate,
    updateFeeRates:updateFeeRates,
    updateRates:update_rates,
    feeRateFileSaveAs:feeRateFileSaveAs,
    getFeeRateByID:getFeeRateByID,
    changeFeeRateFile:changeFeeRateFile
};
let operationMap={
    'ut_create':create_fee_rate,
    'ut_update':update_fee_rate,
    'ut_delete':delete_fee_rate
};

let updateFunctionMap = {
    'normalUpdate':normalUpdate,
    'update_rates':update_rates,
    'updateStatusBySelected':updateStatusBySelected,
    'feeRateFileSaveAs':feeRateFileSaveAs
}


function create_fee_rate() {

}

function update_fee_rate(user_id,datas) {
    if(datas.updateFunction){
        return updateFunctionMap[datas.updateFunction](user_id,datas);
    }else {
        return normalUpdate(user_id,datas);
    }
}

function updateStatusBySelected(user_id,datas) {
    return function(callback){
        feeRateModel.bulkWrite(generateUpdateTaks(datas.tasks),function (err,data) {
            console.log(data);
            commonCallback(callback,data,err);
        })

    }
}
function feeRateFileSaveAs(user_id,datas) {
    return function(callback){
        let doc = datas.doc;
        let projectID=datas.query.projectID;
        let feeRate={
            ID:doc.feeRateID,
            rates:doc.rates
        };
        delete doc._id;
        delete doc.rates;
        creatFeeRateFile(doc,feeRate,projectID).then(function (result) {
            commonCallback(callback,result,result.err);
        })

    }
}


async function creatFeeRateFile(feeRateFile,feeRate,projectID) {//预留projectID
    let result={
        err:null
    }
    try {
        let feeFile={
            id:feeRateFile.ID,
            name:feeRateFile.name
        }
        await projectsModel.findOneAndUpdate({ID:projectID},{'property.feeFile':feeFile});
        await feeRateFileModel.create(feeRateFile);
        await  feeRateModel.create(feeRate);
    }catch (err){
        console.log(err);
        result.err=err;
    }
    return result;
}


function normalUpdate(user_id,datas) {
    return function(callback){
        console.log(datas)
        callback(null,'');
    }
}


function  generateUpdateTaks(updateTasks) {
    var tasks=[];
    for(let u of updateTasks){
        let t ={
            updateOne:{
                filter:u.query,
                update: u.doc
            }
        }
        tasks.push(t);
    }
    return tasks;
}

function update_rates(user_id,datas) {
    return function(callback){
        feeRateModel.findOne(datas.query,['rates'],function(err, data){
            let doc = datas.doc;
            if(_.isArray(doc)){
                _.forEach(doc,function (item) {
                    data.rates[item.rateIndex]=item.rate;
                })
            }else {
                data.rates[doc.rateIndex]=doc.rate;
            }
            data.save(function (err) {
                commonCallback(callback,'',err);
            });
        })
    }
}

function delete_fee_rate() {

}

function save (user_id, datas, callback) {
    let operations=[];
    if(_.isArray(datas)){
        for(let i=0;i<datas.length;i++){
            operations.push(operationMap[datas[i].updateType](user_id,datas[i]));
        }
    }else {
        operations.push(operationMap[datas.updateType](user_id,datas));
    }
    async_n.parallel(operations,function (err,results) {
        if(err){
            callback(err,'');
        }else {
            if(results.length==1){
                callback(null,results[0])
            }else {
                callback(null,results)
            }
        }
    })
}

function getData(projectID, callback) {
    getFeeRateData(projectID).then(function (result) {
        if(result.err){
            callback(1, '', null);
        }else {
            //feeRateModel
            callback(0, consts.projectConst.FEERATE, result.datas);
        }
    })
}

async function getFeeRateData(projectID) {
    let result={
        err:null
    }
    try {
        //
      /*  let getProjectGLJ = +new Date();
        console.log("取项目工料机数据-----"+(getProjectGLJ - getenderData));*/
        let project =  await projectsModel.findOne({ID:projectID});
        if (project&&project.property&&project.property.feeFile){
            let feeRateData = await feeRateFileModel.findOne({'ID':project.property.feeFile.id,deleteInfo:null});
            if(feeRateData===null){
                result.datas=[];
            }else {
                let feeRate =  await feeRateModel.findOne({ID:feeRateData.feeRateID});
                feeRateData._doc.rates = feeRate?feeRate.rates:[];
                //
                feeRateData._doc.usageProjects=await getUsageProjects(feeRateData.ID);
                result.datas = feeRateData;
            }
        }else {
            result.datas=[];
        }
        logger.info("get fee rate data");

    }catch (err){
        console.log(err);
        result.err=err;
    }
    return result;
}

async function getUsageProjects(feeRateID){
    let projects = await projectsModel.find({'property.feeFile.id':feeRateID,'deleteInfo':null});
    return projects;
}


function commonCallback(callback,result,err) {
    if(err){
        callback(err,'');
    }else {
        callback(null,result);
    }
}

async function getFeeRateStandardsByProjectID(projectID) {
    logger.info("get feeRate standard, projectID:"+projectID)
    let feeRateStandards=[];
    let project =  await projectsModel.findOne({ID:projectID});
    let temFee = await feeRateFileModel.findOne({ID:project.property.feeFile.id});
    feeRateStandards.push({ID:temFee.libID,libName:temFee.libName});
   /* let engineeringLibModel = new EngineeringLibModel();
    let engineeringInfo = project !== null && project.property.engineering_id !== undefined ?
        await engineeringLibModel.getEngineering(project.property.engineering_id) : null;
    if(engineeringInfo!=null){
        let fee_lib = engineeringInfo.fee_lib;
        for(let lib of fee_lib){
            feeRateStandards.push({ID:lib.id,libName:lib.name});
        }
    }*/
    return feeRateStandards;
}

async function changeFeeRateStandard(jdata){
    let data = JSON.parse(jdata);
    let template = await std_fee_rate_lib_model.findOne({"ID":data.newLibID});
    let newFeeRate = {};
    newFeeRate.ID =uuidV1();
    newFeeRate.rates=template.rates;
    (newFeeRate.rates || []).forEach(item => item.originalRate = item.rate);
    await feeRateModel.create(newFeeRate);
    let doc={
        libID:data.newLibID,
        libName:template.libName,
        feeRateID: newFeeRate.ID
    };
    await feeRateFileModel.findOneAndUpdate({ID:data.feeRateFileID,deleteInfo:null},doc);
    await feeRateModel.deleteOne({ID:data.feeRateID});
    doc.rates=newFeeRate.rates;
    return doc;
}

async function newFeeRateFile(userId, updateData){
    if(updateData.property !== null){
        let property = updateData.property;
        logger.info("Create new feeRate file for project :"+updateData.ID);
        let feeFile = property.feeFile;
        let rootProjectID = property.rootProjectID;
        let name = updateData.name;
        let newFeeRate = {};
        if(feeFile.id.indexOf("newFeeRate")!=-1){
            let temFee = await feeRateFileModel.findOne({rootProjectID:rootProjectID,name:name,deleteInfo:null});
            if(temFee){
                newFeeRate.id=temFee.ID;
                newFeeRate.name = temFee.name;
                return newFeeRate;
            }
            let temA = feeFile.id.split("@@");
            let libID = temA[1];
            let doc={
                userID: userId,
                rootProjectID:rootProjectID,
                name:name
            };
            if(libID!== ''){
                let template = await std_fee_rate_lib_model.findOne({"ID":libID});
                let newFeeRate = {};
                newFeeRate.ID =uuidV1();
                newFeeRate.rates=template.rates;
                (newFeeRate.rates || []).forEach(item => item.originalRate = item.rate);
                await feeRateModel.create(newFeeRate);
                doc.libID = libID;
                doc.libName = template.libName;
                doc.feeRateID =  newFeeRate.ID;
            }
            doc.ID = uuidV1();
            await feeRateFileModel.create(doc);
            newFeeRate.id = doc.ID;
            newFeeRate.name =doc.name;
            return newFeeRate;
        }else {
            return feeFile
        }

    }
    return null;
}



async function checkFeeRateName(jdata) {
    let data = JSON.parse(jdata);
    let count = await feeRateFileModel.count({rootProjectID:data.rootProjectID,name:data.name,deleteInfo:null});
    if(count>0){
        return true;
    }
    return false;
}

async function getChangeInfo(jdata,compilation){
    let data = JSON.parse(jdata);
    //{ rootProjectID: 99, user_id: '76075' }
    const notDeleted = [{deleteInfo: null}, {'deleteInfo.deleted':false}];
    let result={};
    let treeData = [];
    let currentProject = await projectsModel.findOne({'ID':data.rootProjectID},['ID','NextSiblingID','ParentID','name']); //{projectID:99,name:'建设项目1'};//dummy 数据
    let currentTender = await projectsModel.findOne({ID: data.projectID, $or: notDeleted});
    if(currentProject){
        //剔除自身
        let currentFeeFile = await getFeeRatesByProject(data.rootProjectID);
        let currentUsedFF = currentTender.property.feeFile.id;
        currentProject._doc.currentOptions = _.filter(currentFeeFile, function (ff) {
            return ff.ID !== currentUsedFF;
        });
    }
    //根据用户ID 找除了当前项目的其它建设项目;
    let others =await projectsModel.find({'$and': [
            {'$or':[{'userID': data.user_id,'compilation': compilation,'projType':'Project', 'deleteInfo': null}, {'userID': data.user_id,'compilation': compilation,'projType':'Project', 'deleteInfo.deleted': {'$in': [null, false]}}]},
            { 'ID':{'$nin':[data.rootProjectID]}}
        ]},['ID','NextSiblingID','ParentID','name']);
    for(let o of others){
        o._doc.optionList = await getFeeRatesByProject(o.ID);
    }
    //获取对应用户所有文件夹
    let folders = await projectsModel.find({userID: data.user_id, $or: notDeleted, projType: 'Folder'}, ['ID','NextSiblingID','ParentID','name']);
    treeData = treeData.concat(currentProject);
    treeData = treeData.concat(others);
    treeData = treeData.concat(folders);
    result.currentProject=currentProject;
    result.others = others;
    result.treeData = treeData;
    return result;
}

async function getFeeRatesByProject(rootProjectID) {
       let feeRates = await feeRateFileModel.find({rootProjectID:rootProjectID,deleteInfo:null},['ID','name']);
       return feeRates;
}

async function setFeeRateToBill(data){
    data=JSON.parse(data);
    if(data.hasOwnProperty('bills')){
        await billModel.model.findOneAndUpdate(data.bills.query,data.bills.doc);
    }
    if(data.hasOwnProperty('feeRate')){
        await feeRateModel.findOneAndUpdate(data.feeRate.query,data.feeRate.doc);
    }
    return "ok";
}

async function updateFeeRate(data) {
    data=JSON.parse(data);
   return  await feeRateModel.findOneAndUpdate(data.query,data.doc);
}

async function updateFeeRates(datas){//批量更新费率
    datas = JSON.parse(datas);
    let tasks = [];
    for(let d of datas){
        let task = {
                updateOne:{
                    filter:d.query,
                    update:d.doc
                }
        }
        tasks.push(task);
    }
    tasks.length > 0 ?  await feeRateModel.bulkWrite(tasks) : '';
    return 'OK';
}



async function changeFeeRateFileFromCurrent(jdata){
    let data = JSON.parse(jdata);
    let newFeeRateFile=data.newFeeRateFile;
    await changeFeeRateFile(data,newFeeRateFile,0);
    let feeRateData = await feeRateFileModel.findOne({'ID':newFeeRateFile.id});
    if(feeRateData!==null){
        let feeRate = await feeRateModel.findOne({ID:feeRateData.feeRateID});
        feeRateData._doc.rates = feeRate.rates;
    }
    //
    feeRateData._doc.usageProjects=await getUsageProjects(feeRateData.ID);
    return feeRateData;
}

async function changeFeeRateFile(projectData,feeRateFile,type,userID) {
    let temFile=null,newFeeRateFile = {};
    if(type == 0){//从本建设项目中替换,直接赋值
        temFile =  feeRateFile
    }else if(type == 1) {//从其它建设项目中复制
        let oldFeeRateFile = await feeRateFileModel.findOne({'ID':feeRateFile.id});
        let feeRate = await feeRateModel.findOne({ID:oldFeeRateFile.feeRateID});
        let newFeeRate={};
        if(! feeRate){
            throw '不存在对应费率文件';
        }
        newFeeRate.ID=uuidV1();
        newFeeRate.rates =feeRate.rates;
        newFeeRateFile.ID = uuidV1();
        newFeeRateFile.name = feeRateFile.name;
        newFeeRateFile.userID = userID;
        newFeeRateFile.libName = oldFeeRateFile.libName;
        newFeeRateFile.libID=oldFeeRateFile.libID;
        newFeeRateFile.rootProjectID = projectData.rootProjectID;
        newFeeRateFile.feeRateID =newFeeRate.ID;
        await feeRateModel.create(newFeeRate);
        await feeRateFileModel.create(newFeeRateFile);
        temFile={
            id:newFeeRateFile.ID,
            name:feeRateFile.name
        };
        newFeeRateFile.rates=newFeeRate.rates;//构建返回数据
    }
    await  projectsModel.findOneAndUpdate({ID:projectData.projectID},{'property.feeFile':temFile});
    return newFeeRateFile
}


async function changeFeeRateFileFromOthers(jdata) {
    let data = JSON.parse(jdata);
    let newFeeRateFile = await changeFeeRateFile(data,{id:data.feeRateFileID,name:data.name},1,data.userID);
   /* let feeRateFile = await feeRateFileModel.findOne({'ID':data.feeRateFileID});
    let feeRate = await feeRateModel.findOne({ID:feeRateFile.feeRateID});
    let newFeeRate={};
    newFeeRate.ID=uuidV1();
    newFeeRate.rates =feeRate.rates;
    let newFeeRateFile = {};
    newFeeRateFile.ID = uuidV1();
    newFeeRateFile.name = data.name;
    newFeeRateFile.userID = data.userID;
    newFeeRateFile.libName = feeRateFile.libName;
    newFeeRateFile.libID=feeRateFile.libID;
    newFeeRateFile.rootProjectID = data.rootProjectID;
    newFeeRateFile.feeRateID =newFeeRate.ID;
    await feeRateModel.create(newFeeRate);
    await feeRateFileModel.create(newFeeRateFile);
    let feeFile={
        id:newFeeRateFile.ID,
        name:data.name
    }
    await projectsModel.findOneAndUpdate({ID:data.projectID},{'property.feeFile':feeFile});
    newFeeRateFile.rates=newFeeRate.rates;*/
    newFeeRateFile.usageProjects=await getUsageProjects(newFeeRateFile.ID);
    return newFeeRateFile;
}

async function getGCFeeRateFiles(userID){
    return await feeRateFileModel.find({userID: userID, 'deleteInfo.deleted': true, '$or': [{'deleteInfo.completeDeleted': false}, {'deleteInfo.completeDeleted': null}]});
}

async function getFeeRateByID(ID) {
    let feeRateFile = await feeRateFileModel.findOne({'ID':ID}, '-_id');
    let feeRate = await feeRateModel.findOne({ID:feeRateFile.feeRateID}, '-_id');
    return [feeRateFile,feeRate]
}