package com.yonyou.hrcloud.pm.result.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import com.yonyou.hrcloud.adder.data.jdbc.DialectHelper;
import com.yonyou.hrcloud.pm.ps.model.*;
import org.apache.commons.collections.CollectionUtils;
import com.yonyou.hrcloud.commons.org.model.CommonOrg;
import com.yonyou.hrcloud.commons.staff.model.CommonSimpleStaff;
import com.yonyou.hrcloud.pm.helper.*;
import com.yonyou.hrcloud.pm.manage.service.ISystemManagService;

import org.apache.commons.collections4.map.HashedMap;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StopWatch;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yonyou.hrcloud.adder.context.AppContext;
import com.yonyou.hrcloud.adder.exception.AdderBusinessException;
import com.yonyou.hrcloud.adder.model.param.PagerRequest;
import com.yonyou.hrcloud.adder.model.param.Sorter;
import com.yonyou.hrcloud.adder.model.query.Condition;
import com.yonyou.hrcloud.adder.model.query.Operator;
import com.yonyou.hrcloud.adder.model.query.SqlExpression;
import com.yonyou.hrcloud.pm.base.model.Period;
import com.yonyou.hrcloud.pm.base.service.IPeriodService;
import com.yonyou.hrcloud.pm.common.model.CommonValue;
import com.yonyou.hrcloud.pm.common.model.PmStaff;
import com.yonyou.hrcloud.pm.pa.model.Appraise;
import com.yonyou.hrcloud.pm.pa.service.IAppraiseService;
import com.yonyou.hrcloud.pm.pa.service.IBatchAppraiseService;
import com.yonyou.hrcloud.pm.ps.service.ISchemeService;
import com.yonyou.hrcloud.pm.ps.service.ISheetService;
import com.yonyou.hrcloud.pm.ps.service.ISummarySchemeService;
import com.yonyou.hrcloud.pm.result.dao.IApproveScoreDao;
import com.yonyou.hrcloud.pm.result.model.ApproveScore;
import com.yonyou.hrcloud.pm.result.model.Score;
import com.yonyou.hrcloud.pm.result.service.IApproveScoreService;
import com.yonyou.hrcloud.pm.result.service.IScoreService;


/**
 * 结果实现层
 *
 * @author Flysea
 */
@Service
@Transactional
public class ScoreServiceImpl implements IScoreService {

    protected static final Logger logger = new LoggerDecorator(ScoreServiceImpl.class);

    @Resource
    public com.yonyou.hrcloud.adder.service.IGenericService daoex;

    @Resource
    public ISchemeService schemeService;

    @Resource
    public ISheetService sheetService;

    @Resource
    public IAppraiseService appraiseService;

    @Resource
    public IApproveScoreService approveScoreService;

    @Resource
    public ISummarySchemeService summarySchemeService;

    @Resource
    IApproveScoreDao daoAppScore;

    @Resource
    IPeriodService periodService;

    @Resource
    IBatchAppraiseService batchAppraiseService;

    @Resource
    private ISystemManagService sysService;

	@Override
	public List<Score> queryScoreByConditon(Condition cond, Sorter sort, Pageable pageable) {
		if (pageable == null)
			pageable = new PagerRequest(0, 1000);
		if (sort != null)
			((PagerRequest) pageable).setSort(sort);
		return daoex.findPage(Score.class, cond, pageable).getContent();
	}

    @Override
    public void insert(List<Score> scores) {
        daoex.insertBatch(scores);
    }

    @Override
    public void update(Score score) {
        daoex.update(score, Arrays.asList("numvalue", "text", "annex"));
    }

    @Override
    public void saveObjectScore(String schemeid, Sheet sheet, BigDecimal score,
                                String grade, Boolean isConfirm) {
        if (grade == null)
            throw new AdderBusinessException("总分未对应考核等级，请检查", "pm.i18n_pbc.result.012");
        String sheetid = sheet.getId();
        List<Score> scoreList = new ArrayList<Score>();
        Condition cond = new Condition();
        cond.addExpression("sheetid", sheetid);
        Sorter sortObj = new Sorter(Direction.ASC, "columncode");
        scoreList = daoex.find(Score.class, cond, sortObj);
        if (scoreList.isEmpty()) {
        	Scheme scheme = daoex.load(Scheme.class, schemeid);
            // 不存在记录
            Score obj = new Score();
            // 只更新计算结果
            obj.setSchemeid(schemeid);
            obj.setSheetid(sheetid);
			obj.setColumncode(CommonValue.EnumSchemeScoreColumnCode.CODE002.getCode());// "002"
            obj.setStaffid(sheet.getStaffid());
            obj.setDeptid(sheet.getDeptid());
            obj.setPeriodcode(sheet.getPeriodcode());
			if (isConfirm == null || !isConfirm)
				obj.setNumvalue(score);
            scoreList.add(obj);
            obj = new Score();
            obj.setSchemeid(schemeid);
            obj.setSheetid(sheetid);
			obj.setColumncode(CommonValue.EnumSchemeScoreColumnCode.CODE004.getCode());// "004"
            obj.setStaffid(sheet.getStaffid());
            obj.setDeptid(sheet.getDeptid());
            obj.setPeriodcode(sheet.getPeriodcode());
            if (isConfirm == null || !isConfirm)
                obj.setText(grade);
            scoreList.add(obj);
            // 只更新确认结果
            obj = new Score();
            obj.setSchemeid(schemeid);
            obj.setSheetid(sheetid);
			obj.setColumncode(CommonValue.EnumSchemeScoreColumnCode.CODE003.getCode());// "003"
            obj.setStaffid(sheet.getStaffid());
            obj.setDeptid(sheet.getDeptid());
            obj.setPeriodcode(sheet.getPeriodcode());
            if (isConfirm == null || isConfirm)
                obj.setNumvalue(score);
            scoreList.add(obj);
            obj = new Score();
            obj.setSchemeid(schemeid);
            obj.setSheetid(sheetid);
			obj.setColumncode(CommonValue.EnumSchemeScoreColumnCode.CODE010.getCode());// "010"
            obj.setStaffid(sheet.getStaffid());
            obj.setDeptid(sheet.getDeptid());
            obj.setPeriodcode(sheet.getPeriodcode());
            if (isConfirm == null || isConfirm)
                obj.setText(grade);
            scoreList.add(obj);
			for (Score item : scoreList) {
				// 给结果赋值适用对象
				item.setApplyobj(scheme.getApplyobj());
			}
            insert(scoreList);
        } else {
            if (isConfirm == null || !isConfirm) {
                scoreList.get(0).setNumvalue(score);
                scoreList.get(0).setEs(1);
                scoreList.get(2).setText(grade);
                scoreList.get(2).setEs(1);
            }
            if (isConfirm == null || isConfirm) {
            	// 20200214提供效率
				if (!Toolkit.equals(scoreList.get(1).getNumvalue(), score)) {
					scoreList.get(1).setNumvalue(score);
					scoreList.get(1).setEs(1);
				}
				if (!Toolkit.equals(scoreList.get(3).getText(), grade)) {
					scoreList.get(3).setText(grade);
					scoreList.get(3).setEs(1);
				}
            }
            for (Score item : scoreList) {
                if (item.getEs() == 1)
                    update(item);
            }
        }
    }

    @Override
    public List<Score> queryMyResultList(String staffid, Pageable pageable) {
        List<Score> scores = getScoreList(staffid, new Sorter(Sort.Direction.DESC,
                "periodcode"), pageable);
        scores = getReleaseSheet(scores);
        //scores = getResultScore(scores);
        // 获取用友集团中历史绩效结果
        queryNCPsnResult(staffid, scores, null);
        getPsnInfo(scores);
        return scores;
    }

    @Override
    public Sheet queryIndicatorScoreDetail(String sheetId) {
        return sheetService.querySheetByID(sheetId, true);
    }

    @Override
    public List<Appraise> querySheetResultDetail(String sheetid) {
        Condition cond = new Condition();
        cond.addExpression("sheetid", sheetid, "=");
        return appraiseService.queryAppraiseByCondition(cond, new Sorter(
                Sort.Direction.ASC, "turn"));
    }

    @Override
    public List<ApproveScore> queryApprvoeScore(String sheetid) {
        Condition cond = new Condition();
        cond.addExpression("sheetid", sheetid, "=");
        cond.addExpression("markStatus",
                CommonValue.EnumMarkState30.State3.getIndex(), "=");
        List<ApproveScore> approveScores = approveScoreService
                .queryApproveScoreByConditon(cond, new Sorter(Direction.DESC,
                        "turn"));
        return approveScores;
    }

    @Override
	public List<Scheme> queryDeptResultList(String staffid) {
		List<String> deptids = getPrevDeptids(staffid);
		// 根据部门id和人员id 到评分表pm_appraise查找曾经打分的量表id
		Condition cond = new Condition();
		cond.addExpression("appraiser", staffid, "=");
		// 如果没有历任部门 则返回空集合
		if (deptids == null || deptids.size() == 0) {
			List<Scheme> schemeList = new ArrayList<Scheme>();
			// queryNCDeptDocList(schemeList);
			return schemeList;
		}
		cond.addExpression("deptid", deptids, "in");
		// 这有效率问题
		/*List<String> schemeids = appraiseService.queryAppraiseByCondition(cond, null).stream().map(obj -> {
			return obj.getSchemeid();
		}).distinct().collect(Collectors.toList());*/
		List<Appraise> apprlist = appraiseService.queryAppraiseByCondition(cond, null);
		List<String> schemeids = ListHelper.collect(apprlist, "getSchemeid");
		schemeids = ListHelper.distinct(schemeids);
		if (schemeids.isEmpty()) {
			List<Scheme> schemeList = new ArrayList<Scheme>();
			queryNCDeptDocList(schemeList);
			return schemeList;
		}
		// 增加汇总方案权限
		StopWatch stopWatch = new StopWatch("pm:queryDeptResultList");
		stopWatch.start("queryDeptSumResultList");
		queryDeptSumResultList(schemeids);
		stopWatch.stop();
		logger.debug(stopWatch.prettyPrint());
		// 获得结果集
		cond = new Condition();
		cond.addExpression("id", schemeids, "in");
		cond.addExpression("schemestate", CommonValue.EnumSchemeState.State9.getIndex(), "=");
		List<Scheme> schemeList = schemeService.querySchemeByConditon(cond, new Sorter(Sort.Direction.DESC, "periodcode"), null);
        // 获取用友集团中历史绩效结果
		queryNCDeptDocList(schemeList);
		return schemeList;
	}

	/**
	 * 查询所辖部门的汇总方案
	 *
	 * @param schemeids
	 */
	private void queryDeptSumResultList(List<String> schemeids) {
		if (schemeids != null && schemeids.size() > 0) {
			// 查询当前方案id是否被包含在汇总方案中
			Condition cond = new Condition();
			cond.addExpression("formulaschemeid", schemeids, "in");
			List<SchemeRelation> relations = summarySchemeService.querySchemeRelationList(cond, null);
			if (relations != null && relations.size() > 0) {
				/*List<String> periodIds = relations.stream().map(obj -> {
					return obj.getFormulaperiodid();
				}).distinct().collect(Collectors.toList());*/
				List<String> periodIds = ListHelper.collect(relations, "getFormulaperiodid");
				periodIds = ListHelper.distinct(periodIds);
				cond = new Condition();
				cond.addExpression("id", periodIds, "in");
				List<Period> periods = periodService.queryPeriodByConditon(cond,
						new Sorter(Direction.DESC, Arrays.asList("tdate")));
				Map<String, Date> periodDateMap = new HashMap<String, Date>(); // periods.stream()
						//.collect(Collectors.toMap(Period::getId, Period::getTdate));
				for(Period period : periods){
					periodDateMap.put(period.getId(), period.getTdate());
				}
				/*Map<String, List<SchemeRelation>> map = relations.stream()
						.collect(Collectors.groupingBy(SchemeRelation::getSchemeid));*/
				Map<String, List<SchemeRelation>> map = ListHelper.groupingBy(relations, "getSchemeid");
				for (Map.Entry<String, List<SchemeRelation>> entry : map.entrySet()) {
					List<String> ids = checkLatestPeriod(entry.getValue(), periodDateMap);
					// 如果最新的期间所在的基础方案 是 该人员有权限查看的方案中的，则该汇总方案也有被查看的权限
					ids.retainAll(schemeids);
					if (ids.size() > 0) {
						schemeids.add(entry.getKey());
					}
				}
			}
		}
	}

    /**
     * 获取当前汇总关系中最新考核周期的方案Id
     *
     * @param srs
     * @param periodDateMap
     * @return
     */
    private List<String> checkLatestPeriod(List<SchemeRelation> srs, Map<String, Date> periodDateMap) {
        //添加周期结束时间
        //srs.stream().forEach(obj -> {
    	for(SchemeRelation obj : srs){
            obj.setTdate(periodDateMap.get(obj.getFormulaperiodid()));
        } // );
        //周期结束时间排序
        /*List<Date> dlist = srs.stream().map(obj -> {
            return obj.getTdate();
        }).collect(Collectors.toList());*/
        List<Date> dlist = ListHelper.collect(srs, "getTdate");
        //dlist.sort((d1, d2) -> d1.compareTo(d2));
        Collections.sort(dlist, new Comparator<Date>(){
			@Override
			public int compare(Date d1, Date d2) {
				return d1.compareTo(d2);
			}
        });
        //根据结束日期分组
        Map<Date, List<SchemeRelation>> dateMap = new HashMap<Date, List<SchemeRelation>>(); // srs.stream().collect(Collectors.groupingBy(SchemeRelation::getTdate));
        for(SchemeRelation relation : srs){
        	Date tdate = relation.getTdate();
        	List<SchemeRelation> list = dateMap.get(tdate);
        	if(list == null){
        		list = new ArrayList<SchemeRelation>();
        		dateMap.put(tdate, list);  // TODO 真的可以按照Date对象进行分组吗？？？
        	}
        	list.add(relation);
        }
        //获取最新的结束时间的方案id
        /*List<String> ids = dateMap.get(dlist.get(dlist.size() - 1)).stream().map(obj -> {
            return obj.getFormulaschemeid();
        }).collect(Collectors.toList());*/
        List<String> ids = ListHelper.collect(dateMap.get(dlist.get(dlist.size() - 1)), "getFormulaschemeid");
        return ids;
    }

    @Override
    public List<Score> queryPsnListInDept(String schemeid, String staffid) {
        List<String> deptids = getPrevDeptids(staffid);
        List<Score> scores = getScoreList(schemeid, deptids, new Sorter(Sort.Direction.ASC,
                "text"), null);
        scores = getReleaseSheet(scores);
        //scores = getResultScore(scores);
        getPsnInfo(scores);
        return scores;
    }

    @Override
    public List<String> getPrevDeptids(String staffid) {
        // 获取当前人员历任部门主管的部门集合
        List<PmStaff> staffs = StaffHelper
                .queryPrevDeptInfo(staffid);
        if (staffs == null) {
            return new ArrayList<>();
        }
        /*return staffs.stream().map(staff -> {
            return staff.deptid;
        }).collect(Collectors.toList());*/
        List<String> deptids = new ArrayList<String>();
        for(PmStaff staff : staffs){
        	deptids.add(staff.deptid);
        }
        return deptids;
    }

    @Override
    public Map<String, Object> queryHPTimeline(String staffid, Boolean isAll,Integer... applyobj) {
        Map<String, Object> map = new LinkedHashMap<String, Object>();
        Map<String, Object> result = new HashedMap<>();
        //查询本人的考核结果
        Condition cond = new Condition();
        cond.addExpression("staffid", staffid, "=");
        cond.addExpression("columncode", "010", "=");
        cond.addExpression("tenantid", AppContext.getContext().getScope());
        cond.addExpression("text", null, Operator.ISNOTNULL);
        if(applyobj != null && applyobj.length > 0){
            cond.addExpression("applyobj",applyobj[0]);
        }
        List<Score> scores = queryScoreListOfTimeline(cond);
        //排序规则 不同纬度： 按 年->半年->季度->月 降序排,同纬度呢内降序排列
        compareToScore(scores);
        if (scores != null && scores.size() > 0) {
            //所有的结果年份集合
            /*List<Integer> pYearList = scores.stream().map(obj -> {
                return obj.getPyear();
            }).distinct().collect(Collectors.toList());*/
            List<Integer> pYearList = ListHelper.collect(scores, "getPyear");
            pYearList = ListHelper.distinct(pYearList);
            Collections.sort(pYearList);
            //三年前的年份
            int year3 = getYear();
            //默认过滤,isAll==true 展示全部 ,false筛选前三年
            if (!isAll) {
                scores = getBefore3YearsScore(scores, year3);
            }
            //筛选出已发布的量表
            scores = getReleaseSheet(scores);
            //获取方案名称
            //scores.stream().forEach(score -> {
            for(Score score : scores){
                // Scheme scheme = schemeService.querySchemeByID(score.getSchemeid(), false);
                Scheme scheme = daoex.load(Scheme.class, score.getSchemeid());
                if (scheme != null) {
                    score.setSchemename(scheme.getSchemename());
                    score.setSchememode(scheme.getSchememode());
                }
            } // );
            // 获取用友集团中历史绩效结果，由于期间数据没有，暂不显示
            // queryNCData(staffid, scores, null);
            //周期数据
            scores = getPeriodData(scores);
            List<Score> tempScore;
            for (Score score : scores) {
                if (map.get(score.getPeriodcode()) != null) {
                    List<Score> list = (List<Score>) map.get(score.getPeriodcode());
                    list.add(score);
                    map.put(score.getPeriodcode(), list);
                } else {
                    tempScore = new ArrayList<>();
                    tempScore.add(score);
                    map.put(score.getPeriodcode(), tempScore);
                }
            }
            result.put("data", map.values());
            //查询该人员的最多历史绩效是几年(用于判断前端是否显示查看全部按钮)，包含key=all,则显示全部按钮
            int smallYear = pYearList.get(0);
            if (smallYear < year3) {
                result.put("isAll", true);
            } else {
                result.put("isAll", false);
            }
        }
        return result;
    }

    private void compareToScore(List<Score> scores) {
        Collections.sort(scores, new Comparator<Score>() {
        	@Override
        	public int compare(Score o1, Score o2) {
                String periodcode1 = o1.getPeriodcode();
                String periodcode2 = o2.getPeriodcode();
            	 Integer slength = periodcode1.length() - periodcode2.length();
        		 for(int i = 0 ; i < Math.abs(slength) ;i++){
        			if(slength > 0){
        				periodcode2 += "9";
                	} else if(slength < 0){
                		periodcode1 += "9";
                	}
        		 }
                if (Integer.parseInt(periodcode1) > Integer.parseInt(periodcode2)) {
                    return -1;
                } else if (Integer.parseInt(periodcode1) < Integer.parseInt(periodcode2)) {
                    return 1;
                } else {
                	 return 0;
                }
            }
            /*@Override
            public int compare(Score o1, Score o2) {
                if (o1.getPeriodcode().length() == o2.getPeriodcode().length()
                        && Integer.parseInt(o1.getPeriodcode()) > Integer.parseInt(o2.getPeriodcode())) {
                    return -1;
                } else if (Integer.parseInt(o1.getPeriodcode()) < Integer.parseInt(o2.getPeriodcode())) {
                    return 1;
                }
                return 0;
            }*/
        });
    }

    @Override
    public List<Score> queryScoreListOfTimeline(Condition cond) {
        return daoAppScore.queryScoreListOfTimeline(cond);
    }

    @Override
    public Sheet queryPerformanceDetail(String sheetid) {
        //add by zengcl 建工项目 方案中直接导入结果，绩效详情返回null  begin
		Condition cond = new Condition();
		cond.addExpression("id", sheetid);
		List<Sheet> sheetList = daoex.find(Sheet.class, cond, null);
		Sheet sheet1=sheetList.get(0);
		Condition cond1 = new Condition();
		cond1.addExpression("id", sheet1.getSchemeid());
		List<Scheme> schemeList = daoex.find(Scheme.class, cond1, null);
		if(schemeList.get(0).isIsimportresult()) {
			return new Sheet();
		}else {		
			//add by zengcl 建工项目 方案中直接导入结果，绩效详情返回null  begin
	        Sheet sheet = approveScoreService.queryApproveScore(sheetid);
	        if (sheet != null) {
	            if (sheet.getOSheetIndis() != null && sheet.getOSheetIndis().size() > 0) {
	                for (SheetIndicator indic : sheet.getOSheetIndis()) {
	                    //设置指标的计划完成值和实际完成值
	                    batchAppraiseService.getIndiNum(indic);
	                }
	            }
	        }      
	        return sheet;
		}
    }

    @Override
    public Score queryPsnScoreInfo(String sheetid) {
        Condition cond = new Condition();
        cond.addExpression("sheetid", sheetid, "=");
        cond.addExpression("columncode", "010", "=");
        List<Score> scores = queryScoreByConditon(cond, null, null);
        if (scores != null && scores.size() > 0) {
            Score score = getResultScore(Arrays.asList(scores.get(0))).get(0);
            getPsnInfo(Arrays.asList(score));
            return score;
        }
        return null;
    }

    private int getYear() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.YEAR, -2);
        return calendar.get(Calendar.YEAR);
    }

    /**
     * 筛选3年前结果集
     *
     * @param scores
     * @return
     */
    private List<Score> getBefore3YearsScore(List<Score> scores, int year3) {
        //筛选出日期大于三年前的结果集
        /*return scores.stream().filter(score -> {
            if (StringUtils.isBlank(score.getPeriodcode()) || score.getPeriodcode().length() < 4) {
                return false;
            } else if (Integer.parseInt(score.getPeriodcode().substring(0, 4)) >= year3) {
                return true;
            } else {
                return false;
            }
        }).collect(Collectors.toList());*/
        List<Score> newscores = new ArrayList<Score>();
        for(Score score : scores){
        	 if (StringUtils.isBlank(score.getPeriodcode()) || score.getPeriodcode().length() < 4) {
                 continue;
             } else if (Integer.parseInt(score.getPeriodcode().substring(0, 4)) >= year3) {
            	 newscores.add(score);
             } else {
            	 continue;
             }
        }
        return newscores;
    }

    /**
     * 获得周期
     *
     * @param scores
     * @return
     */
    private List<Score> getPeriodData(List<Score> scores) {
        /*return scores.stream().map(score -> {
            Condition cond = new Condition();
            cond.addExpression("periodcode", score.getPeriodcode(), "=");
            List<Period> periods = periodService.queryPeriodByConditon(cond, null);
            if (periods != null && periods.size() > 0) {
                score.setPeriod(periods.get(0));
            }
            return score;
        }).collect(Collectors.toList());*/
        for(Score score : scores){
        	Condition cond = new Condition();
            cond.addExpression("periodcode", score.getPeriodcode(), "=");
            List<Period> periods = periodService.queryPeriodByConditon(cond, null);
            if (periods != null && periods.size() > 0) {
                score.setPeriod(periods.get(0));
            }
        }
        return scores;
    }

    /**
     * 根据方案和部门id查询结果集
     *
     * @param schemeid
     * @param deptids
     * @param sort
     * @return
     */
	private List<Score> getScoreList(String schemeid, List<String> deptids, Sorter sort, Pageable pageable) {
		if (deptids == null || deptids.size() == 0) {
			return new ArrayList<>();
		}
		Scheme scheme = daoex.load(Scheme.class, schemeid);
		if (scheme == null) {
			List<Score> scoreList = new ArrayList<>();
			// 查询NC指定方案下考核对象列表
			queryNCDocPsnList(schemeid, scoreList);
			return scoreList;
		} else {
			Condition cond = new Condition();
			cond.addExpression("schemeid", schemeid);
			cond.addExpression("columncode", Arrays.asList("010", "003"), Operator.IN);
			cond.addExpression("deptid", deptids, Operator.IN);
			List<Score> scores = queryScoreByConditon(cond, sort, pageable);
			return combiningScore(scores);
		}
	}

    /**
     * 根据员工id查询结果集
     *
     * @param staffid
     * @param sort
     * @return
     */
    private List<Score> getScoreList(String staffid, Sorter sort,
                                     Pageable pageable) {
        Condition cond = new Condition();
        cond.addExpression("staffid", staffid, "=");
        cond.addExpression("columncode", Arrays.asList("010", "003"), "in");
        List<Score> scores = queryScoreByConditon(cond, sort, pageable);
        return combiningScore(scores);
    }

    /**
     * 组合score数据，将确认等级于确认结果合并成一条
     *
     * @param scores
     */
	private List<Score> combiningScore(List<Score> scores) {
		if (scores != null && scores.size() > 0) {
			// 获取方案信息
            /*List<String> schemeIds = scores.stream().map(obj -> {
                return obj.getSchemeid();
            }).distinct().collect(Collectors.toList());*/
            List<String> schemeIds = ListHelper.collect(scores, "getSchemeid");
            schemeIds = ListHelper.distinct(schemeIds);
            Condition cond = new Condition();
            cond.addExpression("id", schemeIds, "in");
            //Map<String, List<Scheme>> schemes = schemeService.querySchemeByConditon(cond, null, null).stream().collect(Collectors.groupingBy(Scheme::getId));
            List<Scheme> schemelist = schemeService.querySchemeByConditon(cond, null, null);
            Map<String, List<Scheme>> schemes = ListHelper.groupingBy(schemelist, "getId");
            //对code进行分组
            //Map<String, List<Score>> codeMap = scores.stream().collect(Collectors.groupingBy(Score::getColumncode));
            Map<String, List<Score>> codeMap = ListHelper.groupingBy(scores, "getColumncode");
            //Map<String, List<Score>> code003Map = codeMap.get("003").stream().collect(Collectors.groupingBy(Score::getSheetid));
            Map<String, List<Score>> code003Map = ListHelper.groupingBy(codeMap.get("003"), "getSheetid");
			for (Score score : codeMap.get("010")) {
				score.setNumvalue(code003Map.get(score.getSheetid()).get(0).getNumvalue());
				score.setSchemename(schemes.get(score.getSchemeid()).get(0).getSchemename());
				score.setSchememode(schemes.get(score.getSchemeid()).get(0).getSchememode());
			}
			return codeMap.get("010");
		}
		return new ArrayList<>();
	}

    /**
     * 筛选已发布的量表
     *
     * @param scores
     * @return
     */
	private List<Score> getReleaseSheet(List<Score> scores) {
		if (scores == null || scores.size() == 0)
			return new ArrayList<>();
		/*List<String> sheetids = scores.stream().map(obj -> {
			return obj.getSheetid();
		}).collect(Collectors.toList());*/
		List<String> sheetids = ListHelper.collect(scores, "getSheetid");
		Condition cond = new Condition();
		cond.addExpression("id", sheetids, "in");
		cond.addExpression("isrelease", true, "="); // sheetService.querySheetListByConditon(cond)
		/*List<String> sheets = sheetService.querySheetListByConditon(cond, null).stream().map(obj -> {
			return obj.getId();
		}).collect(Collectors.toList());*/
		List<Sheet> sheetlist = sheetService.querySheetListByConditon(cond, null);
		List<String> sheets = ListHelper.collect(sheetlist, "getId");
		//return scores.stream().filter(score -> sheets.contains(score.getSheetid())).collect(Collectors.toList());
		List<Score> score_list = new ArrayList<Score>();
		for(Score score : scores){
			if(sheets.contains(score.getSheetid())){
				score_list.add(score);
			}
		}
		return score_list;
	}

    /**
     * 获得结果中的得分数据
     *
     * @param scores
     * @return
     */
	private List<Score> getResultScore(List<Score> scores) {
		if (scores == null || scores.size() == 0)
			return new ArrayList<>();
        // 当前量表必须为已发布才可以展示
        /*scores = scores.stream().map(score -> {
            Condition cond1 = new Condition();
            cond1.addExpression("sheetid", score.getSheetid(), "=");
            cond1.addExpression("columncode", "003", "=");
            score.setNumvalue(queryScoreByConditon(cond1, null, null).get(0).getNumvalue());
            List<Scheme> schemes = daoex.findByIds(Scheme.class, score.getSchemeid());
            if (schemes != null) {
                score.setSchemename(schemes.get(0).getSchemename());
                score.setSchememode(schemes.get(0).getSchememode());
            }
            return score;
        }).collect(Collectors.toList());*/
        for(Score score : scores){
        	Condition cond1 = new Condition();
            cond1.addExpression("sheetid", score.getSheetid(), "=");
            cond1.addExpression("columncode", "003", "=");
            score.setNumvalue(queryScoreByConditon(cond1, null, null).get(0).getNumvalue());
            List<Scheme> schemes = daoex.findByIds(Scheme.class, score.getSchemeid());
            if (schemes != null) {
                score.setSchemename(schemes.get(0).getSchemename());
                score.setSchememode(schemes.get(0).getSchememode());
            }
        }
        return scores;
    }

    /**
     * 获得结果中的人员详细信息
     *
     * @param scores
     */
	private void getPsnInfo(List<Score> scores) {
		if (scores == null || scores.size() == 0)
			return;
		/*List<String> staffIds = scores.stream().map(score -> {
			return score.getStaffid();
		}).collect(Collectors.toList());*/
		List<String> staffIds = ListHelper.collect(scores, "getStaffid");
		// 根据staffid集合获取PmStaff
		Map<String, PmStaff> map = StaffHelper.queryStaffByIds(staffIds);
		//scores.stream().forEach(score -> {
		for(Score score : scores){
			PmStaff staff = map.get(score.getStaffid());
			score.setStaffname(staff != null ? staff.name : "");
			score.setDeptname(staff != null ? staff.deptname : "");
			score.setPhoto(staff != null ? staff.photo : "");
			score.setMobile(staff != null ? staff.mobile : "");
			score.setEmail(staff != null ? staff.email : "");
		} // );
	}

    @Override
    public Map<String, List<Score>> getLatestSchemeYear(List<String> staffids,Integer... applyobj) {
        Map<String, List<Score>> map = new HashMap<>();
        Condition condition = new Condition();
        condition.addExpression("staffid", staffids, Operator.IN);
        condition.addExpression("columncode", "010");
        if(applyobj != null && applyobj.length > 0){
            condition.addExpression("applyobj",applyobj[0]);
        }
        if("sqlserver".equals(DialectHelper.getDBType())){
            condition.addExpressions(new SqlExpression("LEN(periodcode)=4"));
        }else{
            condition.addExpressions(new SqlExpression("LENGTH(periodcode)=4"));
        }
        // 查询这些人的所有最终结果
        List<Score> scores = queryScoreListOfTimeline(condition);
        if (scores != null && scores.size() > 0) {
			// 筛选出已发布的量表
            scores = getReleaseSheet(scores);
            if (scores != null && scores.size() > 0) {
                /*List<String> schemeIds = scores.stream().map(score -> {
                    return score.getSchemeid();
                }).distinct().collect(Collectors.toList());*/
                List<String> schemeIds = ListHelper.collect(scores, "getSchemeid");
                schemeIds = ListHelper.distinct(schemeIds);
                condition = new Condition();
                condition.addExpression("id", schemeIds, Operator.IN);
				// 获取方案id：方案Name的Map集合
                // Map<String, Scheme> schemeMap = schemeService.querySchemeByConditon(condition, null, null).stream().collect(Collectors.toMap(Scheme::getId, Function.identity()));
                List<Scheme> schemelist = schemeService.querySchemeByConditon(condition, null, null);
                Map<String, Scheme> schemeMap = ListHelper.toMap(schemelist, "getId");
                //map = scores.stream().collect(Collectors.groupingBy(Score::getStaffid));
                map = ListHelper.groupingBy(scores, "getStaffid");
				// 保存Map中为空的key值，用于移除
                List<String> keys = new ArrayList<>();
                for (Map.Entry<String, List<Score>> entry : map.entrySet()) {
                    // 获取每个人的最新年度结果
                    int newYear = entry.getValue().get(0).getPyear();
                    /*scores = entry.getValue().stream().filter(score -> (StringUtils.isNotBlank(score.getPeriodcode()) && score.getPeriodcode().equals(newYear + "")))
                            .collect(Collectors.toList());*/
                    scores = new ArrayList<Score>();
                    for(Score score : entry.getValue()){
                    	if(StringUtils.isNotBlank(score.getPeriodcode()) && score.getPeriodcode().equals(newYear + "")){
                    		scores.add(score);
                    	}
                    }
                    // scores.forEach(obj -> {
                    for(Score obj : scores){
                        obj.setSchemename(schemeMap.get(obj.getSchemeid()).getSchemename());
                        obj.setSchememode(schemeMap.get(obj.getSchemeid()).getSchememode());
                    } // );
                    if (scores.size() == 0) {
                        keys.add(entry.getKey());
                    }
                    entry.setValue(scores);
                }
				// 移除map中value为空的key值 ，用于前端展现
                for (String key : keys) {
                    map.remove(key);
                }
            }
        }
        return map;
    }

    /**
     * 过滤出年度周期
     *
     * @param periodCodes
     * @return
     */
    private List<String> PeriodYearfilter(List<String> periodCodes) {
        Condition condition = new Condition();
        condition.addExpression("periodcode", periodCodes, "in");
        List<Period> periods = periodService.queryPeriodByConditon(condition, null);
        if (periods != null && periods.size() > 0) {
            //过滤出年度周期
            /*return periods.stream().filter(period -> {
                if (period.getPeriodtype() == CommonValue.EnumPeriodType.year.getIndex()) {
                    return true;
                }
                return false;
            }).map(period -> {
                return period.getPeriodcode();
            }).collect(Collectors.toList());*/
            List<Period> periodlist = ListHelper.filter(periods, "getPeriodtype", ListHelper.Operator.EQUAL, CommonValue.EnumPeriodType.year.getIndex());
            List<String> collect = ListHelper.collect(periodlist, "getPeriodcode");
            return collect;
        }
        return null;
    }

   /*暂不使用
    @Override
    public List<StaffPerformance> queryStaffPerformanceList(List<String> deptIds, int pageIndex, int pageSize) {
        Sorter sorter = new Sorter(Direction.ASC, new String[]{"deptname", "name"});
        Pageable pageable = new PagerRequest(pageIndex, pageSize, sorter);
        //获取所有人员信息
        List<PmStaff> pmStaffList = new ArrayList<>(StaffHelper.queryStaffPageByDeptIds(deptIds, pageable).values());
        List<StaffPerformance> spList = new ArrayList<>();
        if (pmStaffList != null && pmStaffList.size() > 0) {
            //人员id集合
            List<String> staffIdList = pmStaffList.stream().map(staff -> {
                return staff.id;
            }).collect(Collectors.toList());
            //获取最新年度考核
            Map<String, List<Score>> map = getLatestSchemeYear(staffIdList);
            StaffPerformance sp = null;
            for (PmStaff staff : pmStaffList) {
                spList.add(new StaffPerformance(staff, map.get(staff.id)));
            }
        }
        return spList;
    }*/

	@Override
	public Map<String, Object> queryStaffPerformance(List<String> deptIdList, String name, int pageIndex,
			int pageSize) {
		Map<String, Object> result = new HashMap<>();
		Map<String, List<Score>> scoreMap = new HashMap<>();
		List<String> staffIdList = new ArrayList<>();
		Sorter sorter = new Sorter(Direction.ASC, new String[] { "deptname", "name" });
		Pageable pageable = new PagerRequest(pageIndex, pageSize, sorter);
		// 获取分页人员信息
        Page<PmStaff> page = StaffHelper.queryStaffPageByDeptIds(deptIdList, name, pageable);
		result.put("staff", page);
		// 生成staffid集合
        for (int i = 0; i < page.getContent().size(); i++) {
            //staffIdList.add(page.getContent().get(i).get("bd_staffb_id").toString());
        	staffIdList.add(page.getContent().get(i).id);
		}
		// 获取最新年度考核（人员id:结果列表）
		if (staffIdList.size() > 0)
			scoreMap = getLatestSchemeYear(staffIdList,CommonValue.EnumApplyObj.psn.getIndex());
		result.put("score", scoreMap);
		return result;
	}

    /**
     * 查询组织绩效
     *
     * @param deptIdList 部门范围
     * @param pageIndex
     * @param pageSize   @return
     */
    @Override
    public Map<String, Object> queryOrgPerformance(List<String> deptIdList, int pageIndex, int pageSize) {
        Map<String, Object> result = null;
        List<CommonOrg> commonOrgs = OrgHelper.querydeptsByidList(deptIdList);
        Map<String,String> orgIdAndNameMap = new HashMap<>();
        for (CommonOrg commonOrg : commonOrgs) {
            orgIdAndNameMap.put(commonOrg.getId(),commonOrg.getName());
        }
        Map<String, List<Score>> scoreMap = new HashMap<>();
        Condition evaObjCondition = new Condition();
        evaObjCondition.addExpression("orgid",deptIdList,Operator.IN);
        List<EvaObject> evaObjectList = daoex.find(EvaObject.class, evaObjCondition, null);
        if(CollectionUtils.isNotEmpty(evaObjectList)){
            Map<String,String> staffIdAndOrgIdMap = new HashMap<>();
            for (EvaObject evaObject : evaObjectList) {
                staffIdAndOrgIdMap.put(evaObject.getStaffid(),evaObject.getOrgid());
            }
            List<String> principleIdList = ListHelper.filterAndcollect(evaObjectList, "getStaffid", false, "getStaffid");
            if(CollectionUtils.isNotEmpty(principleIdList)){
                result = new HashMap<>();
                List<String> staffIdList = new ArrayList<>();
                Sorter sorter = new Sorter(Direction.ASC, new String[] {"name"});
                Pageable pageable = new PagerRequest(pageIndex, pageSize, sorter);
                // 获取分页人员信息
                Page<CommonSimpleStaff> page = StaffHelper.queryStaffPageByIds(principleIdList,pageable);
                // 生成staffid集合
                for (int i = 0; i < page.getContent().size(); i++) {
                    CommonSimpleStaff commonSimpleStaff = page.getContent().get(i);
                    String staffid = commonSimpleStaff.getId();
                    if(StringUtils.isNotEmpty(staffIdAndOrgIdMap.get(staffid)) &&
                            StringUtils.isNotEmpty(orgIdAndNameMap.get(staffIdAndOrgIdMap.get(staffid)))){
                        commonSimpleStaff.setDeptName(orgIdAndNameMap.get(staffIdAndOrgIdMap.get(staffid)));
                        commonSimpleStaff.setDeptId(staffIdAndOrgIdMap.get(staffid));
                    }
                    staffIdList.add(staffid);
                }
                result.put("staff", page);
                // 获取最新年度考核（人员id:结果列表）
                if (staffIdList.size() > 0)
                    scoreMap = getLatestSchemeYear(staffIdList,CommonValue.EnumApplyObj.org.getIndex());
                result.put("score", scoreMap);
            }
        }
        return result;
    }

    /**
	 * 查询nc56绩效结果
	 *
	 * @param staffid
	 *            查询人
	 * @param scores
	 *            新绩效结果
	 * @param cond
	 *            条件
	 */
	private void queryNCPsnResult(String staffid, List<Score> scores, String cond) {
		String ncid = SyncNCHelper.getNcUserIdEx();
		if (ncid.length() == 0)
			return;
		JSONObject json = new JSONObject();
		json.put("pkPsnDoc", ncid);
		// 20180120 增加排序
		if (cond != null) {
			String strOrder = "pe_document.eva_fdate desc";
			if (cond.indexOf("doc_name") > -1)
				strOrder = cond.replace("doc_name", "pe_document.doc_name");
			else if (cond.indexOf("res_docname") > -1) {
				strOrder = cond;
			} else if (cond.indexOf("res_score") > -1)
				strOrder = cond.replace("res_score", "pe_score.res_score");
			json.put("order", strOrder);
		}
		// 401; 结果浏览-个人结果列表
		String data = SyncNCHelper.postNC(401, json.toString());
		logger.debug("pm:queryNCPsnResult " + data);
		if (data != null) {
			JSONArray ja = JSONArray.parseArray(data);
			Iterator<Object> it = ja.iterator();
			while (it.hasNext()) {
				JSONObject ob = (JSONObject) it.next();
				Score score = new Score();
				score.setId(ob.getString("pk_pe_score"));
				score.setStaffid(staffid);
				score.setSchemeid(ob.getString("pk_pe_doc"));
				score.setSchemename(ob.getString("doc_name"));
				score.setNumvalue(ob.getBigDecimal("res_score"));
				// score.setPyear(ob.getJSONObject("adj_time").getIntValue("year"));
				if (!StringUtils.isEmpty(ob.getString("period_code"))) {
					score.setPeriodcode(ob.getString("period_code").substring(0, 4));
					score.setPyear(Integer.parseInt(score.getPeriodcode()));
				}
				if (!StringUtils.isEmpty(ob.getString("res_docname")))
					score.setText(ob.getString("res_docname"));
				scores.add(score);
			}
		}
	}

	/**
	 * 查询分管部门方案数据
	 *
	 * @param schemeList
	 */
	private void queryNCDeptDocList(List<Scheme> schemeList) {
		String ncid = SyncNCHelper.getNcUserIdEx();
		if (ncid.length() == 0)
			return;
		JSONObject json = new JSONObject();
		json.put("className", "ResultBrowseImpl");
		json.put("methodName", "queryDeptDocList");

		String[] args = new String[1];
		args[0] = ncid;
		json.put("args", args);
		// 组织方法参数调用nc
		String data = SyncNCHelper.postNC(100, json.toString());
		logger.debug("pm:queryNCDeptDocList " + data);
		if (data != null) {
			JSONArray ja = JSONArray.parseArray(data);
			Iterator<Object> it = ja.iterator();
			while (it.hasNext()) {
				JSONObject ob = (JSONObject) it.next();
				Scheme scheme = new Scheme();
				//add by@chenzf 查询数据是否参数控制能否查看 2022-1-12 18:29:35 begin
				Scheme scheme1 = schemeService.querySchemeByID(ob.getString("pk"), false);
				if(scheme1.isIsviewresult()) {
					continue;
				}
				//add by@chenzf 查询数据是否参数控制能否查看 2022-1-12 18:29:35 end
				scheme.setId(ob.getString("pk"));
				scheme.setSchemename(ob.getString("name"));
				schemeList.add(scheme);
			}
		}
	}

	/**
	 * 查询NC指定方案下考核对象列表
	 *
	 * @param pk_pe_doc
	 * @param scoreList
	 */
	private void queryNCDocPsnList(String pk_pe_doc, List<Score> scoreList) {
		String ncid = SyncNCHelper.getNcUserIdEx();
		if (ncid.length() == 0)
			return;
		JSONObject json = new JSONObject();
		json.put("className", "ResultBrowseImpl");
		json.put("methodName", "queryDocPsnList");

		String[] args = new String[2];
		args[0] = pk_pe_doc;
		args[1] = ncid;
		json.put("args", args);
		// 组织方法参数调用nc
		String data = SyncNCHelper.postNC(100, json.toString());
		logger.debug("pm:queryNCDocPsnList " + data);
		if (data != null) {
			JSONArray ja = JSONArray.parseArray(data);
			Iterator<Object> it = ja.iterator();
			while (it.hasNext()) {
				JSONObject ob = (JSONObject) it.next();
				Score score = new Score();
				score.setId(ob.getString("pk_pe_score"));
				
				//add by@chenzf 查询数据是否参数控制能否查看 2022-1-12 18:29:35 begin
				Scheme scheme1 = schemeService.querySchemeByID(ob.getString("pk_pe_doc"), false);
				if(scheme1.isIsviewresult()) {
					continue;
				}
				//add by@chenzf 查询数据是否参数控制能否查看 2022-1-12 18:29:35 end
				score.setSchemeid(ob.getString("pk_pe_doc"));
				score.setSchemename(ob.getString("doc_name"));
				score.setNumvalue(ob.getBigDecimal("res_score"));
				score.setText(ob.getString("docname"));
				score.setStaffname(ob.getString("psnname"));
				score.setDeptname(ob.getString("deptname"));
				scoreList.add(score);
			}
		}
	}

	/**
	 * 获取考核方案
	 * @param sheetid
	 * @return
	 */
	public Scheme querySchemeInfoBySheetid(String sheetid){
		Sheet sheet = daoex.load(Sheet.class, sheetid);
		return daoex.load(Scheme.class, sheet.getSchemeid());
	}

    /**
     * 直接新增人员的考核结果数据
     *
     * @param schemeid
     * @param staffid
	 * @param groupid
     * @param numvalue
     * @param text
     */
    @Override
    public void insertAssessResultInfo(String schemeid, String staffid, String groupid, String numvalue, String text) {
        Scheme scheme = null;
        // 权限校验
        if (sysService.checkPermissions2()) { // 白名单
            scheme = schemeService.querySchemeByID(schemeid, false);
        } else {
            scheme = schemeService.queryAuthorizedSchemeByID(schemeid, false);
        }
        if (scheme == null) {
            throw new AdderBusinessException("方案不存在", "pm.i18n_core.ps.043");
        }
        if (scheme.isIsend() || scheme.getSchemestate() < CommonValue.EnumSchemeState.State8.getIndex()) {
            throw new AdderBusinessException("考核方案信息有误", "pm.i18n_core.comm.002");
        }
        // 查询量表
        Condition condition = new Condition();
        condition.addExpression("schemeid", schemeid, Operator.EQUAL);
        List<Sheet> sheets = daoex.find(Sheet.class, condition, null);
        // 查询方案下考核对象组
        List<EvaGroup> evaGroups = daoex.find(EvaGroup.class, condition, null);
        if (evaGroups.isEmpty()) {
            throw new AdderBusinessException("数据有误", "pm.i18n_core.comm.002");
        }
        List<String> groupids = evaGroups.stream().map(EvaGroup::getId).collect(Collectors.toList());
        if (!groupids.contains(groupid)) {
            throw new AdderBusinessException("考核对象组信息有误", "pm.i18n_core.comm.002");
        }
        // 查询考核组对象
        condition = new Condition();
        condition.addExpression("groupid", groupid, Operator.EQUAL);
        List<EvaObject> groups = daoex.find(EvaObject.class, condition, null);
        if (sheets == null || groups == null || sheets.isEmpty() || groups.isEmpty()) {
            throw new AdderBusinessException("数据有误", "pm.i18n_core.comm.002");
        }
        List<String> staffids = sheets.stream().map(Sheet::getStaffid).collect(Collectors.toList());
        Sheet sheet = sheets.stream().filter(Sheet::isEnablestate).collect(Collectors.toList()).get(0);
        if (staffids.contains(staffid)) {
            throw new AdderBusinessException("此考核方案中已包含此人员", "pm.i18n_core.comm.002");
        }
        // 查询人员信息
        List<PmStaff> staffList = StaffHelper.queryStaffByIds3(Arrays.asList(staffid));
        if (staffList.isEmpty()) {
            throw new AdderBusinessException("传入人员信息有误", "pm.i18n_core.comm.002");
        }
        String deptid = staffList.get(0).deptid;
        // 新增量表信息
        sheet.setId(null);
        sheet.setStaffid(staffid);
        sheet.setDeptid(deptid);
        daoex.insert(sheet);
        // 新增考核对象信息
        EvaObject evaObject = groups.get(0);
        evaObject.setId(null);
        evaObject.setGroupid(groupid);
        evaObject.setSchemeid(schemeid);
        evaObject.setStaffid(staffid);
        daoex.insert(evaObject);
        // 新增考核评分信息
        saveObjectScore(schemeid, sheet, new BigDecimal(numvalue), text, null);
    }
}
