/**
 * Created by Zhong on 2018/1/9.
 */
const mongoose = require('mongoose');
const compleRationModel = mongoose.model('complementary_ration_items');
const complementaryGljModel = mongoose.model('complementary_glj_lib');
const stdGljModel = mongoose.model('std_glj_lib_gljList');
const compleRationSectionTreeModel = mongoose.model('complementary_ration_section_tree');
const rationLibModel = mongoose.model('std_ration_lib_map');
let stdSectionTreeModel = require ('../../ration_repository/models/ration_section_tree').Model;
let stdRationModel = require ('../../ration_repository/models/ration_item').Model;
let gljUtil = require('../../../public/gljUtil');

const compleRationLib = 'compleRationLib';

class SearchDao{
    async getRationItem(userId, compilationId, rationRepIds, code, ID, callback){
        let ration = null;
        let otherLibs=[];
        const compleLibUsers = [userId];
        try{
            let [firstLib] = String(rationRepIds[0]).split('*');//优先取第一个
            for (let l of rationRepIds){
                const [libID, owner] = String(l).split('*');
                if(libID != firstLib && libID != compleRationLib){
                    otherLibs.push(libID);
                } else if (libID === compleRationLib && owner && !compleLibUsers.includes(owner)) {
                    compleLibUsers.push(owner);
                }
            }
            if(firstLib == compleRationLib){//说明选中的是补充定额库
                ration = await this.getCompleRation(compleLibUsers,compilationId,code,ID);
            }else {
                firstLib = parseInt(firstLib);
                let firstQuery = {rationRepId: firstLib, code: code};
                if(ID){
                    firstQuery = {ID: ID};
                }
                ration = await this.getStdRation(firstQuery);
            }
            if(ration == null){//选中的定额库或者默认的定额库中没有找到定额，才走常规的流程查找其它定额库
                let stdQuery = {rationRepId: {$in: otherLibs}, code: code};
                if(ID){
                    stdQuery = {ID: ID};
                }
                ration = await this.getStdRation(stdQuery);
                if(ration == null) ration = await this.getCompleRation(compleLibUsers,compilationId,code,ID);
            }
            if(isDef(ration)){
                if (ration.type === 'std') {
                    let stdChapter = await stdSectionTreeModel.findOne({ID: ration.sectionId});
                    if(isDef(stdChapter)){
                        ration.chapter = stdChapter._doc;
                    }
                } else {
                    let compleChapter = await compleRationSectionTreeModel.findOne({ID: ration.sectionId});
                    if(isDef(compleChapter)){
                        ration.chapter = compleChapter._doc;
                    }
                }
            }
            if(callback){
                callback(0, ration);
            }
        }
        catch(err){
            if(callback){
                callback(err, null);
            }
        }
        return ration;
    }
    async getCompleRation(users,compilationId,code,ID){
        let ration = null;
        let compleQuery = {userId: {$in: users}, compilationId: compilationId, code: code, $or: [{deleteInfo: null}, {'deleteInfo.deleted': false}]};
        if(ID){
            compleQuery.ID = ID;
        }
        let compleRation = await compleRationModel.findOne(compleQuery);
        if(isDef(compleRation)){
            ration = compleRation._doc;
            ration.type = 'complementary';
        }
        return ration
    }
    async getStdRation(query){
        let ration = null;
        let stdRation = await stdRationModel.findOne(query);
        if(isDef(stdRation)){
            ration = stdRation._doc;
            ration.type = 'std';
        }
        return ration;
    }
    // 设置定额所属定额库数据
    async setRationLibName(stdRations, compleRations) {
        const rationLibIDSet = new Set();
        stdRations.forEach(ration => {
            rationLibIDSet.add(ration.rationRepId);
        });
        const rationLibNameList = await rationLibModel.find({ ID: { $in: [...rationLibIDSet] } }, '-_id dispName ID').lean();
        const rationLibNameMap = {};
        rationLibNameList.forEach(lib => rationLibNameMap[lib.ID] = lib.dispName);
        stdRations.forEach(ration => {
            ration.rationLibName = rationLibNameMap[ration.rationRepId];
        });
        compleRations.forEach(ration => ration.rationLibName = '我的补充定额');
    }
    //@param {Object}skip({std: Number, comple: Number})
    async findRation(userId, compilationId, rationRepId, keyword, skip, callback){
        //每次限制结果数
        const limit = 50;
        //结果数
        let resultCount = 0,
            rst = {data: [], count: null};
        try{
            let compleLibUsers = new Set();
            const stdRationLibs = [];
            rationRepId.forEach(libItem => {
                const [libID, owner] = String(libItem).split('*');
                if (libID === compleRationLib) {
                    compleLibUsers.add(owner || userId);
                } else {
                    stdRationLibs.push(libID);
                }
            });
            compleLibUsers = [...compleLibUsers];
            //是否需要查找补充定额
            let findCompleRtion = compleLibUsers.length > 0;
            let filter = {
                'rationRepId': {$in: stdRationLibs},
                '$and': [{
                    '$or': [{'code': {'$regex': keyword, $options: '$i'}}, {'name': {'$regex': keyword, $options: '$i'}}]
                }, {
                    '$or': [{'isDeleted': {"$exists":false}}, {'isDeleted': null}, {'isDeleted': false}, {deleteInfo: null}]
                }]
            };
            let compleFilter = {
                userId: { $in: compleLibUsers },
                compilationId: compilationId,
                '$and': [{
                    '$or': [{'code': {'$regex': keyword, $options: '$i'}}, {'name': {'$regex': keyword, $options: '$i'}}]
                }, {
                    '$or': [{deleteInfo: null}, {'deleteInfo.deleted': false}]
                }]
            };
            //结果数
            if (skip && skip.std === 0 && skip.comple === 0) {
                resultCount += stdRationLibs.length === 0 ? 0 : await stdRationModel.find(filter).count();
                resultCount += findCompleRtion ? await compleRationModel.find(compleFilter).count() : 0;
                rst.count = resultCount;
            }
            //搜索定额
            let stdGljIds = [],
                comGljIds = [];
            let stdRations = stdRationLibs.length === 0 ? [] : await stdRationModel.find(filter).lean().sort({code: 1}).skip(skip.std).limit(limit);
            for(let i = 0, len = stdRations.length; i < len; i++){
                stdRations[i].type = 'std';
                for(let glj of stdRations[i].rationGljList){
                    stdGljIds.push(glj.gljId);
                }
            }
            let compleRations = [];
            let residueLimit = limit - stdRations.length;
            if (residueLimit > 0) {
                compleRations = findCompleRtion ? await compleRationModel.find(compleFilter).lean().sort({code: 1}).skip(skip.comple).limit(residueLimit) : [];
                for(let i = 0, len = compleRations.length; i <len; i++){
                    compleRations[i].type = 'complementary';
                    for(let glj of compleRations[i].rationGljList){
                        if(glj.type === 'std'){
                            stdGljIds.push(glj.gljId);
                        }
                        else {
                            comGljIds.push(glj.gljId);
                        }
                    }
                }
            }

            // 设置定额所属定额库名称
            await this.setRationLibName(stdRations, compleRations);

            //设置悬浮信息
            stdGljIds = Array.from(new Set(stdGljIds));
            comGljIds = Array.from(new Set(comGljIds));
            let gljIDMapping = {};
            if(stdGljIds.length > 0){
                let stdGljs = await stdGljModel.find({ID: {$in: stdGljIds}}, '-_id ID code name specs unit gljType');
                for(let stdGlj of stdGljs){
                    gljIDMapping[stdGlj.ID] = stdGlj;
                }
            }
            if(comGljIds.length > 0){
                let comGljs = await complementaryGljModel.find({ID: {$in: stdGljIds}});
                for(let comGlj of comGljs){
                    gljIDMapping[comGlj.ID] = comGlj;
                }
            }
            for(let ration of stdRations){
                let hintsArr = [];
                //对人材机进行排序
                ration.rationGljList.sort(function (a, b) {
                    let gljA = gljIDMapping[a.gljId],
                        gljB = gljIDMapping[b.gljId],
                        seqs = gljUtil.getGljTypeSeq() ;
                    if(gljA && gljB){
                        let indA = seqs.indexOf(gljA.gljType)+"",
                            indB = seqs.indexOf(gljB.gljType)+"";
                        let aV = indA+gljA.gljType + gljA.code,
                            bV = indB+gljB.gljType + gljB.code;
                        if(aV > bV) {
                            return 1;
                        } else if(aV < bV) {
                            return -1;
                        }
                    }
                    return 0;
                });

                if(ration.jobContent && ration.jobContent.toString().trim() !== ''){
                    hintsArr.push(`<label class="nomargin font_blue">工作内容:`);
                    hintsArr = hintsArr.concat(ration.jobContent.split('\n'));
                    hintsArr.push("</label>");
                    hintsArr.push("");
                }

                for(let rationGlj of ration.rationGljList){
                    let glj = gljIDMapping[rationGlj.gljId];
                    if(glj){
                        hintsArr.push(`<label class="nomargin ${glj.gljType==4?"font_blue":""}"> ${glj.code} ${glj.name}${glj.specs ? '&nbsp;&nbsp;&nbsp;' + glj.specs : ''}&nbsp;&nbsp&nbsp;${glj.unit}&nbsp;&nbsp;&nbsp;${rationGlj.consumeAmt}</label>`)
                        //hintsArr.push(` ${glj.code} ${glj.name}${glj.specs ? ' ' + glj.specs : ''} ${glj.unit} ${rationGlj.consumeAmt}`);
                    }
                }
                hintsArr.push(`基价 元 ${ration.basePrice}`);
                if(ration.annotation && ration.annotation.toString().trim() !== ''){
                    hintsArr.push(`附注:`);
                    hintsArr = hintsArr.concat(ration.annotation.split('\n'));
                }
                ration.hint = hintsArr.join('<br>');
            }
            for(let ration of compleRations){
                let hintsArr = [];
                for(let rationGlj of ration.rationGljList){
                    let glj = gljIDMapping[rationGlj.gljId];
                    if(glj){
                        hintsArr.push(` ${glj.code} ${glj.name}${glj.specs ? ' ' + glj.specs : ''} ${glj.unit} ${rationGlj.consumeAmt}`);
                    }
                }
                hintsArr.push(`基价 元 ${ration.basePrice}`);
                if(ration.jobContent && ration.jobContent.toString().trim() !== ''){
                    hintsArr.push(`工作内容:`);
                    hintsArr = hintsArr.concat(ration.jobContent.split('\n'));
                }
                if(ration.annotation && ration.annotation.toString().trim() !== ''){
                    hintsArr.push(`附注:`);
                    hintsArr = hintsArr.concat(ration.annotation.split('\n'));
                }
                ration.hint = hintsArr.join('<br>');
            }
            rst.data = stdRations.concat(compleRations);
            callback(0, rst);
        }
        catch(err){
            console.log(err);
            callback(err, null);
        }
    }
}

function isDef(v){
    return v !== undefined && v !== null;
}

module.exports = SearchDao;