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

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import com.yonyou.hrcloud.pm.ps.service.ISchemeService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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 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.Sorter;
import com.yonyou.hrcloud.adder.model.query.Condition;
import com.yonyou.hrcloud.adder.model.query.Operator;
import com.yonyou.hrcloud.adder.service.IGenericService;
import com.yonyou.hrcloud.pm.base.model.Period;
import com.yonyou.hrcloud.pm.common.model.CommonValue;
import com.yonyou.hrcloud.pm.common.model.CommonValue.EnumMarkState10;
import com.yonyou.hrcloud.pm.common.model.CommonValue.EnumWorkStep;
import com.yonyou.hrcloud.pm.common.model.CommonValue.EnumWorkflowState;
import com.yonyou.hrcloud.pm.common.model.CommonValue.EnumWorkflowType;
import com.yonyou.hrcloud.pm.common.model.PmStaff;
import com.yonyou.hrcloud.pm.helper.ListHelper;
import com.yonyou.hrcloud.pm.helper.StaffHelper;
import com.yonyou.hrcloud.pm.ia.dao.ISheetSettingDao;
import com.yonyou.hrcloud.pm.ia.service.ISheetSettingService;
import com.yonyou.hrcloud.pm.notice.model.NoticeBaseParam;
import com.yonyou.hrcloud.pm.notice.model.NoticeExtendParam;
import com.yonyou.hrcloud.pm.notice.service.INoticeEngineService;
import com.yonyou.hrcloud.pm.notice.service.INoticeFactoryService;
import com.yonyou.hrcloud.pm.pa.model.Appraise;
import com.yonyou.hrcloud.pm.ps.model.Approver;
import com.yonyou.hrcloud.pm.ps.model.EvaObject;
import com.yonyou.hrcloud.pm.ps.model.Scheme;
import com.yonyou.hrcloud.pm.ps.model.SchemeFlow;
import com.yonyou.hrcloud.pm.ps.model.SchemeRelation;
import com.yonyou.hrcloud.pm.ps.model.Sheet;
import com.yonyou.hrcloud.pm.ps.model.SheetAppraiser;
import com.yonyou.hrcloud.pm.ps.model.SheetIndicator;
import com.yonyou.hrcloud.pm.ps.service.IEvaAppraiserService;
import com.yonyou.hrcloud.pm.ps.service.IEvaGroupService;
import com.yonyou.hrcloud.pm.ps.service.IEvaSettingService;
import com.yonyou.hrcloud.pm.wf.model.BaseParam;
import com.yonyou.hrcloud.pm.wf.model.WorkflowEngine;
import com.yonyou.hrcloud.pm.wf.model.WorkflowParam;
import com.yonyou.hrcloud.pm.wf.service.IWorkflowService;



/**
 * 指标填报服务层
 *
 * @author nijb@yonyou.com
 */
@Service
@Transactional
public class SheetSettingServiceImpl implements ISheetSettingService {

    @Resource
    public IGenericService daoex;

    @Resource
    public ISheetSettingDao dao;

    @Resource
    public IWorkflowService wfService;

    @Resource
    public INoticeFactoryService fService;

    @Resource
    public IEvaGroupService evaGroupSrv;

    @Resource
    ISchemeService schemeService;

    @Resource
    IEvaAppraiserService evaAppriaiserService;
    
    @Resource
    IEvaSettingService evaSettingService;
    
	@Resource
	public INoticeEngineService noticeEngineService;
	
    protected static final Logger logger = LoggerFactory.getLogger(SheetSettingServiceImpl.class);

    /**
     * 量表提交前的检查校验
     */
    @Override
    public void checkSheetIndiBeforeSubmit(Sheet sheet) {
    	String sheetid = sheet.getId();
        // 1.检查量表审核人
        Condition apprIndiCond = new Condition();
        apprIndiCond.addExpression("sheetid", sheetid);
        List<Approver> evaList = daoex.find(Approver.class, apprIndiCond, new Sorter(Direction.ASC, "apr_level"));
        if(evaList.size() > 0){
    		//List<String> collect = evaList.stream().map(Approver::getStaffid).distinct().collect(Collectors.toList());
    		List<String> collect = ListHelper.collect(evaList, "getStaffid");
    		collect = ListHelper.distinct(collect);
    		if(collect.contains("") || collect.contains(null)){
    			throw new AdderBusinessException("指标审核人不能为空","pm.i18n_pbc.ia.008");
    		}
    		if(collect.size() != evaList.size()){
    			throw new AdderBusinessException("指标审核人不能重复","pm.i18n_pbc.ia.006");
    		}
        } else {
        	//验证考核流程上审核人信息。
        	List<Approver> approverSet = evaSettingService.verificationApproverOnFlow(sheet);
        	if(approverSet.size() <= 0)
        		throw new AdderBusinessException("指标审核人不能为空","pm.i18n_pbc.ia.008");
        	// List<String> collect2 = approverSet.stream().map(Approver::getStaffid).distinct().collect(Collectors.toList());
        	List<String> collect2 = ListHelper.collect(approverSet, "getStaffid");
    		if(collect2.contains("") || collect2.contains(null)){
    			throw new AdderBusinessException("指标审核人不能为空","pm.i18n_pbc.ia.008");
    		}
    		if(collect2.size() != approverSet.size()){
    			throw new AdderBusinessException("指标审核人不能重复","pm.i18n_pbc.ia.006");
    		}
        	daoex.insertBatch(approverSet);
	    }
        // 2检验至少有一条指标
        Condition findIndiCond = new Condition();
        findIndiCond.addExpression("sheetid", sheetid);
        List<SheetIndicator> indiList = daoex.find(SheetIndicator.class,
                findIndiCond, new Sorter(Direction.ASC, "disp_seq"));
        if (indiList.size() <= 0) {
            throw new AdderBusinessException("量表至少需要有一条指标","pm.i18n_pbc.ia.001");
        }
        // 3验证指标考核人/权重/分类权重
        evaSettingService.verificationSheetAppraiser(sheet,indiList);
    }
    
    /**
     * 提交量表
     */
    @Override
	public Sheet submitSheet(String sheetid) {
		Sheet sheet = daoex.load(Sheet.class, sheetid);
		if (sheet == null || !sheet.getTenantid().equals(AppContext.getContext().getScope())) {
			throw new AdderBusinessException("数据已不存在，请刷新再试", "pm.i18n_core.comm.004");
		}
		if (sheet.getMarkStatus() >= CommonValue.EnumMarkState10.State2.getIndex()) { //
			throw new AdderBusinessException("考核表已提交，无需重复提交", "pm.i18n_pbc.ia.021");
		}
		// 1 检查与校验
		checkSheetIndiBeforeSubmit(sheet); // 对量表进行检查
		// 2 更新量表状态为已提交
		sheet.setMarkStatus(CommonValue.EnumMarkState10.State2.getIndex());// 已提交
		daoex.update(sheet);
		// 2.1将审核人审核意见置空
		cleanApproverComment(sheetid);
		// 3 创建量表审核人工作流 和指标评价人工作流
		creatWorkflowEngnie(sheet); // 创建工作流

		// 4 给第一轮审核人发送消息通知
		sendAprNotice(sheet); // 给第一轮审核人发送消息通知

		// 5 处理待办任务
		NoticeBaseParam ep = new NoticeBaseParam();
		ep.businessKey = String.format("%s,%s", "indiFill_" + sheet.getId(), "indiFill_" + sheet.getSchemeid());
		noticeEngineService.disposeTODO(ep);
		
		return sheet;
	}

    /**
     * 将审核人审核意见置空
     */
    @Override
    public void cleanApproverComment(String sheetid){
    	Condition apprcondition = new Condition();
		apprcondition.addExpression("sheetid", sheetid);
		List<Approver> approverList = daoex.find(Approver.class,
				apprcondition, new Sorter(Direction.ASC, "apr_level"));
		for(Approver approver : approverList){
			approver.setComment(null);
			daoex.update(approver);
		}
    }
    /**
     * 创建工作流
     */
    @Override
    public void creatWorkflowEngnie(Sheet sheet) {
        Scheme scheme = daoex.load(Scheme.class, sheet.getSchemeid());
        // 创建考核人工作流
        createAppraiserWorkflow(scheme, sheet);
        // 创建审核人工作流
        createApproverWorkflow(scheme, sheet);
    }
    
    /**
     * 创建考核人工作流
     */
    @Override
	public void createAppraiserWorkflow(Scheme scheme, Sheet sheet) {
		// 如果是中期回顾的子方案不需要评分，则不用创建工作流
		if (scheme.getSchememode() == CommonValue.EnumSchemeMode.pm_mtr.getIndex() && !scheme.isIsallowcalc())
			return;
    	// 创建考核人工作流
        List<Map<String, Object>> apprTurn = dao.findDistinctApprTurn(sheet.getId());
        // 获取流程执行轮次
        Integer appraiserWorkStepOrder = getWorkStepOrder(sheet.getSchemeid(), CommonValue.EnumWorkStep.step2.getIndex() );
        List<WorkflowParam> evaParamList = new ArrayList<>();
        for (Map<String, Object> appr : apprTurn) {
            // 生成流程参数实例
            WorkflowParam param = new WorkflowParam();
            // 当前人员
			if (appr.get("staffid") == null)
				throw new AdderBusinessException("考核对象的评价人未对应人员，请检查", "pm.i18n_pbc.ps.018");
            param.setCurrentOperator(appr.get("staffid").toString());
            param.setWorksteporder(appraiserWorkStepOrder);
            param.setWorkstep(CommonValue.EnumWorkStep.step2);
            param.setBiztype(CommonValue.EnumWorkflowType.performance);
            param.setBizid(sheet.getId());
            List<String> bizinfo = new ArrayList<String>();
            bizinfo.add(sheet.getSchemeid());
            param.setBizinfo(bizinfo);
            // param.setStepserial(Integer.parseInt(appr.get("turn").toString()));
            if (scheme.isIsturn()) {
                param.setStepserial(Integer.parseInt(appr.get("turn")
                        .toString()));
            } else {
                param.setStepserial(1);
            }
            /*if (param.getStepserial() == 1 && param.getWorksteporder() == 1) { // 第一轮默认待处理
                param.setWorkflowState(EnumWorkflowState.PENDING);
            } else {
                param.setWorkflowState(EnumWorkflowState.NO_ARRIVE);
            }*/
            param.setWorkflowState(EnumWorkflowState.NO_ARRIVE);//提交后工作流会进入审核环境，还不到评分环境，故而全部未到达
            /*
			 * if (!scheme.isIsturn()) {// 非严格按照轮次 全部是待处理
			 * param.setWorkflowState(EnumWorkflowState.PENDING); } else if
			 * (Integer.parseInt(appr.get("turn").toString()) == 1) { //
			 * 第一轮默认待处理 param.setWorkflowState(EnumWorkflowState.PENDING); }
			 * else { // 其他默认未到达
			 * param.setWorkflowState(EnumWorkflowState.NO_ARRIVE); }
			 */
            evaParamList.add(param);
        }
        // 同步工作流程(提交时同步)
		if (evaParamList.isEmpty() && scheme.getIndisource() == CommonValue.EnumIndiSource.issued.getIndex())
			throw new AdderBusinessException("量表指标考核人不能为空", "pm.i18n_pbc.ia.010");
        wfService.syncWorkflowEngine(sheet.getId(), evaParamList);
    }
    
    /**
     * 创建审核人工作流
     */
    @Override
    public void createApproverWorkflow(Scheme scheme, Sheet sheet){
    	// 创建审核人工作流
        Condition apprCond = new Condition();
        apprCond.addExpression("sheetid", sheet.getId());
        List<Approver> approverList = daoex.find(Approver.class, apprCond,
                new Sorter(Sort.Direction.ASC, "apr_level"));
        List<WorkflowParam> apprParamList = new ArrayList<>();
        int aprlevel = 1;
        // 获取流程执行轮次
        Integer approverWorkStepOrder = getWorkStepOrder(sheet.getSchemeid(), CommonValue.EnumWorkStep.step1.getIndex() );
        for (Approver appr : approverList) {
            // 生成流程参数实例
            WorkflowParam param = new WorkflowParam();
            // 当前人员
            param.setCurrentOperator(appr.getStaffid());
            param.setWorksteporder(approverWorkStepOrder);
            List<String> bizinfo = new ArrayList<String>();
            bizinfo.add(sheet.getSchemeid());
            param.setBizinfo(bizinfo);
            param.setWorkstep(CommonValue.EnumWorkStep.step1);
            param.setBiztype(CommonValue.EnumWorkflowType.performance);
            param.setBizid(sheet.getId());
            // 指标审核人都是严格按照轮次的。
            //param.setStepserial(appr.getAprLevel());
            param.setStepserial(aprlevel ++ );
            if (param.getStepserial() == 1) { // 第一轮默认待处理
                param.setWorkflowState(EnumWorkflowState.PENDING);
            } else {
                param.setWorkflowState(EnumWorkflowState.NO_ARRIVE);
            }
			/*if (scheme.isIsturn()) {
				param.setStepserial(appr.getAprLevel());
			} else {
				param.setStepserial(1);
			}*/
			/*if (param.getStepserial() == 1 && param.getWorksteporder() == 1) { // 第一轮默认待处理
				param.setWorkflowState(EnumWorkflowState.PENDING);
			} else {
				param.setWorkflowState(EnumWorkflowState.NO_ARRIVE);
			}*/
			/*
			 * if (!scheme.isIsturn()) {// 非严格按照轮次 全部是待处理
			 * param.setWorkflowState(EnumWorkflowState.PENDING); } else if
			 * (appr.getAprLevel() == 1) { // 第一轮默认待处理
			 * param.setWorkflowState(EnumWorkflowState.PENDING); } else { //
			 * 其他默认未到达 param.setWorkflowState(EnumWorkflowState.NO_ARRIVE); }
			 */
            apprParamList.add(param);
        }
		if (apprParamList.isEmpty() && scheme.getIndisource() == CommonValue.EnumIndiSource.issued.getIndex())
			throw new AdderBusinessException("请设置指标下达人", "pm.i18n_pbc.ia.022");
        wfService.syncWorkflowEngine(sheet.getId(), apprParamList);
    }
    
    /**
     * 获取流程执行轮次
     * @param schemeid
     * @param workstep
     * @return
     */
    private Integer getWorkStepOrder(String schemeid, Integer workstep){
    	Condition approverFlowCond = new Condition();
        approverFlowCond.addExpression("schemeid", schemeid, "=");
        approverFlowCond.addExpression("workstep", workstep);
        List<SchemeFlow> flows = daoex.find(SchemeFlow.class, approverFlowCond, null);
        Integer worksteporder = flows.size() > 0 ? flows.get(0).getWorksteporder() : null;
        return worksteporder;
    }
    /**
     * 提交后发送通知
     */
    @Override
    public void sendAprNotice(Sheet sheet) {
        Scheme scheme = schemeService.querySchemeByID(sheet.getSchemeid(), false);
        //true表示前面多人时只收到最后一条消息
        if (scheme.isIsmergemsg()) {
            sendMergeMsg(sheet, scheme.getId());
        } else {
            sendSingleMsg(sheet);
        }
    }

    /**
     * 指标提交合并发送消息
     * 发送规则：
     * 1/当前人员提交指标后，查找当前人员所在考核对象组。
     * 只有当 当前考核对象组中的所有对象提交指标后，才会触发合并发送消息
     * (根据考核对象的第一轮审核人 进行分类发送。)
     * 逻辑对应：
     * 1.根据当前人员取考核组id,跟id取出该考核组的所有考核对象，若当前考核组只存在一个对象则执行发送通知
     * 2.查找考核对象是否提交量表 若未全部提交则不发送通知
     * 3.根据量表集合和轮次 取出所有第一级考核人 并进行分类
     * 4.对考核人循环发送通知
     */
    private void sendMergeMsg(Sheet sheet, String schemeid) {
        //根据人员Id和方案id确定考核对象组
        Condition cond = new Condition();
        cond.addExpression("staffid", sheet.getStaffid(), "=");
        cond.addExpression("schemeid", schemeid, "=");
        List<EvaObject> evaObjects = daoex.find(EvaObject.class, cond, null);
        if (evaObjects != null && evaObjects.size() > 0) {
            String groupId = evaObjects.get(0).getGroupid();
            //根据组Id查询当前组人员
            cond = new Condition();
            cond.addExpression("groupid", groupId, "=");
           /* List<String> staffIds = daoex.find(EvaObject.class, cond, null).stream().map(obj -> {
                return obj.getStaffid();
            }).collect(Collectors.toList());*/
            List<String> staffIds = ListHelper.collect(daoex.find(EvaObject.class, cond, null), "getStaffid");
            //如果当前考核组中的考核对象除去当前人员 还有其他人员 则进行合并发送，如果当前考核组只存在当前提交指标的人员，则直接发送
            if (staffIds.size() > 1) {
                cond = new Condition();
                cond.addExpression("staffid", staffIds, "in");
                cond.addExpression("schemeid", schemeid, "=");
                List<Sheet> sheets = daoex.find(Sheet.class, cond, null);
                for (Sheet s : sheets) {
                    //只有量表中存在未填报，已填报状态的，则不发送合并消息
                    if (s.getMarkStatus() == CommonValue.EnumMarkState10.State0.getIndex() ||
                            s.getMarkStatus() == CommonValue.EnumMarkState10.State1.getIndex()) {
                        return;
                    }
                }
                //已提交量表Id集合
                /*List<String> sheetIds = sheets.stream().map(obj -> {
                    return obj.getId();
                }).collect(Collectors.toList());*/
                List<String> sheetIds = ListHelper.collect(sheets, "getId");
                //已提交量表id对应人员Map
                //Map<String, String> sheetStaffMap = sheets.stream().collect(Collectors.toMap(Sheet::getId, Sheet::getStaffid));
                Map<String, String> sheetStaffMap = ListHelper.toMap(sheets, "getId", "getStaffid");
                //获取人员
                Map<String, PmStaff> staffMap = StaffHelper.queryStaffByIds2(staffIds, false);
                //查询对象组中所有对象的第一轮考核人
                //并对第一轮考核人进行map分类(每一个考核人只对应一个考核对象即可)
                cond = new Condition();
                cond.addExpression("sheetid", sheetIds, "in");
                cond.addExpression("aprLevel", 1, "=");
                //Map<String, String> map = daoex.find(Approver.class, cond, null).stream().collect(Collectors.toMap(Approver::getStaffid, Approver::getSheetid, (key1, key2) -> key2));
                Map<String, String> map = ListHelper.toMap(daoex.find(Approver.class, cond, null), "getStaffid", "getSheetid");
                for (String approver : map.keySet()) {
                    NoticeExtendParam ep = new NoticeExtendParam("您有新的对" + staffMap.get(sheetStaffMap.get(map.get(approver))).name
                            + "等人的指标审核", schemeid, Arrays.asList(approver), false,true,true);
                    ep.businessKey = String.format("indiAudit_%s",map.get(approver));//指标审核待办业务主键—indiAudit_sheetId
                    fService.getNoticeServiceToSend(CommonValue.EnumNoticeType.INDIAUDIT, ep);
                }
            } else {
                //当前考核组只存在当前提交指标的人员，则直接发送
                sendSingleMsg(sheet);
            }
        }
    }

    /**
     * 发送单一消息
     */
    private void sendSingleMsg(Sheet sheet) {
        Map<String, PmStaff> staffMap = StaffHelper
                .queryStaffByIds2(Arrays.asList(sheet.getStaffid()), false);
        if (staffMap.get(sheet.getStaffid()) == null) {
            throw new AdderBusinessException("通知发送失败:获取被评价人错误","pm.i18n_pbc.ia.015");
        }
        // 第一次给所有待审核的审核人发送通知
        Condition cond = new Condition();
        cond.addExpression("bizid", sheet.getId(), "=");
        cond.addExpression("workstep",
                CommonValue.EnumWorkStep.step1.getIndex(), "=");
        cond.addExpression("state",
                CommonValue.EnumWorkflowState.PENDING.getIndex(), "=");
        List<WorkflowEngine> nextEngine = daoex.find(WorkflowEngine.class, cond, null);
        //List<String> staffids = nextEngine.stream().map(WorkflowEngine :: getDisposeperson).collect(Collectors.toList());
        List<String> staffids = ListHelper.collect(nextEngine, "getDisposeperson");
        
        NoticeExtendParam ep = new NoticeExtendParam("您有新的对" + staffMap.get(sheet.getStaffid()).name
                + "的指标审核", sheet.getSchemeid(), staffids, false,true,true);
        ep.businessKey = String.format("indiAudit_%s",sheet.getId());//指标审核待办业务主键—indiAudit_sheetId
        fService.getNoticeServiceToSend(CommonValue.EnumNoticeType.INDIAUDIT, ep);

    }


    /**
     * 收回量表
     */
    @Override
    public Sheet callbackSheet(String sheetid) {
        Sheet sheet = daoex.load(Sheet.class, sheetid);
        if(sheet == null || !sheet.getTenantid().equals(AppContext.getContext().getScope())){
        	throw new AdderBusinessException("数据已不存在，请刷新再试","pm.i18n_core.comm.004");
        }
        if (sheet.isIsaudit()) {
            throw new AdderBusinessException("量表已审核，不能收回。","pm.i18n_pbc.ia.016");
        }
        // 收回时如果时已审核 或审核中则无法收回
        if (sheet.getMarkStatus() != EnumMarkState10.State2.getIndex()) {
            throw new AdderBusinessException("量表不是已提交状态，不能收回。","pm.i18n_pbc.ia.017");
        }
        sheet.setMarkStatus(EnumMarkState10.State1.getIndex()); // 已填报
        daoex.update(sheet);
        //删除工作流
        delWorkflowEngnie(sheetid);
        return sheet;
    }

	@Override
	public void delWorkflowEngnie(String sheetid) {
		// 删除考核人工作流
		Condition evaDelCond = new Condition();
		evaDelCond.addExpression("bizid", sheetid, "=");
		evaDelCond.addExpression("biztype", CommonValue.EnumWorkflowType.performance.getIndex(), "=");
		evaDelCond.addExpression("workstep", CommonValue.EnumWorkStep.step2.getIndex(), "=");// CommonValue.EnumWorkStep.step1.getIndex()
		wfService.delWorkflowEngine(evaDelCond);
		// 删除审核人工作流
		Condition apprDelCond = new Condition();
		apprDelCond.addExpression("bizid", sheetid, "=");
		apprDelCond.addExpression("biztype", CommonValue.EnumWorkflowType.performance.getIndex(), "=");
		apprDelCond.addExpression("workstep", CommonValue.EnumWorkStep.step1.getIndex(), "=");// CommonValue.EnumWorkStep.step1.getIndex()
		wfService.delWorkflowEngine(apprDelCond);
	}

    @Override
    public void deleteEvaGroup(String id) {
        // 查询组下的考核对象和量表
        Condition condObj = new Condition();
        condObj.addExpression("groupid", id);
        List<EvaObject> evaObjects = evaGroupSrv.queryEvaObjectByConditon(
                condObj, null);
        List<Sheet> sheetList = evaGroupSrv
                .querySheetListByEvaObjects(evaObjects);
        if (!sheetList.isEmpty()) {
            List<String> sheetids = new ArrayList<String>();
            for (Sheet item : sheetList) {
                sheetids.add(item.getId());
            }
            // 删除工作流实体
            Condition wfcond = new Condition();
            wfcond.addExpression("bizid", sheetids, Operator.IN);
            wfService.delWorkflowEngine(wfcond);
        }
        evaGroupSrv.delete(id);
    }

    @Override
    public void deleteObject(List<String> ids) {
        for (String id : ids) {
            String sheetid = evaGroupSrv.querySheetidByEvaObject(id);
            if (sheetid != null) {
                // 删除工作流实体
                Condition wfcond = new Condition();
                wfcond.addExpression("bizid", sheetid);
                wfService.delWorkflowEngine(wfcond);
            }
            evaGroupSrv.deleteObject(id);
        }
    }

    @Override
    public List<Map<String, Object>> queryMyWorkGoal(String staffid) {
        //查询指标已经审核的量表
        Condition apprcondition = new Condition();
        apprcondition.addExpression("staffid", staffid);
        apprcondition.addExpression("isaudit", true);//已审核
        apprcondition.addExpression("iscalc", false);//未计算
        List<Sheet> sheetList = daoex.find(Sheet.class,
                apprcondition, new Sorter(Direction.ASC, "ts"));
        if (sheetList == null || sheetList.size() == 0) {
            return null;
        }
        List<String> sheetidList = new ArrayList<String>();
        for (Sheet sheet : sheetList) {
            if (!sheetidList.contains(sheet.getId()))
                sheetidList.add(sheet.getId());
        }
        // 更新工作流
        Condition workcond = new Condition();
        workcond.addExpression("bizid", sheetidList, Operator.IN);
        workcond.addExpression("workstep", EnumWorkStep.step2.getIndex()); // 评分
        workcond.addExpression("state", EnumWorkflowState.PENDING.getIndex()); // 正在评分
        workcond.addExpression("stepserial", 1); // 第一轮
        workcond.addExpression("biztype", EnumWorkflowType.performance.getIndex()); // 绩效

        List<WorkflowEngine> enginList = daoex.find(WorkflowEngine.class,
                workcond, new Sorter(Direction.ASC, "ts"));

        List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
        List<String> sheetidList2 = new ArrayList<String>();
        for (WorkflowEngine engin : enginList) {
            String sheetid = engin.getBizid();
            if(sheetidList2.contains(sheetid)){
            	continue;
            }
            sheetidList2.add(sheetid);
            Sheet sheet = daoex.load(Sheet.class, sheetid);
            Scheme scheme = daoex.load(Scheme.class, sheet.getSchemeid());
            Period period = daoex.load(Period.class, scheme.getPeriodid());
            HashMap<String, Object> map = new HashMap<String, Object>();
            map.put("sheetid", sheetid);
            map.put("schemeid", scheme.getId());
            map.put("schemename", scheme.getSchemename());
            map.put("periodname", period.getPeriodname());
            map.put("periodid", period.getId());
            if (period.getTdate() != null) {
                Date tdate = period.getTdate();
                Date ndate = new Date();
                if (tdate.getTime() - ndate.getTime() > 0) {
                    int days = (int) ((tdate.getTime() - ndate.getTime()) / (1000 * 3600 * 24));
                    map.put("days", days);
                }
            }
            result.add(map);
        }
        return result;
    }
    
    @Override
    public Map<String, Object> queryOneWorkGoal(String sheetid) {
        //查询指标已经审核的量表
        Sheet sheet = daoex.load(Sheet.class, sheetid);
        Scheme scheme = daoex.load(Scheme.class, sheet.getSchemeid());
        Period period = daoex.load(Period.class, scheme.getPeriodid());
        HashMap<String, Object> map = new HashMap<String, Object>();
        map.put("sheetid", sheetid);
        map.put("schemeid", scheme.getId());
        map.put("schemename", scheme.getSchemename());
        map.put("periodname", period.getPeriodname());
        map.put("periodid", period.getId());
        map.put("staffid", sheet.getStaffid());
        map.put("isdoubleweight", scheme.isIsdoubleweight());
        if (period.getTdate() != null) {
            Date tdate = period.getTdate();
            Date ndate = new Date();
            if (tdate.getTime() - ndate.getTime() > 0) {
                int days = (int) ((tdate.getTime() - ndate.getTime()) / (1000 * 3600 * 24));
                map.put("days", days);
            }
        }
        return map;
    }

    @Override
    public List<Map<String, Object>> queryMyPerfList(String staffid) {

        //1处理待填报
        List<Map<String, Object>> prefList = dao.queryMyPerfList(staffid);
        HashMap<String, Object> shemeMap = new HashMap<String, Object>();
        for (Map<String, Object> perfObj : prefList) {
            String schemeid = (String) perfObj.get("schemeid");
            if (shemeMap.containsKey(schemeid)) {
                continue;
            }
            HashMap<String, Object> fillInfo = new HashMap<String, Object>();
            fillInfo.put("sheetid", perfObj.get("sheetid"));
            fillInfo.put("perfCnt", Integer.parseInt(perfObj.get("perf_cnt").toString()));
            Map<String, Object> schemeObj = new HashMap<String, Object>();
            schemeObj.put("fillInfo", fillInfo);
            shemeMap.put(schemeid, schemeObj);
        }

        //2指标审核
        BaseParam apprparam = new BaseParam();
        apprparam.setBiztype(EnumWorkflowType.performance);
        apprparam.setWorkstep(EnumWorkStep.step1);
        apprparam.setCurrentOperator(staffid);
        apprparam.setWorkflowState(EnumWorkflowState.PENDING);
        List<WorkflowEngine> aprwfList = wfService.queryWorkflowEngine(apprparam);
        for (WorkflowEngine wf : aprwfList) {
            String schemeid = wf.getBizinfo();
            Map<String, Object> schemeObj = null;
            if (shemeMap.containsKey(schemeid)) {
                schemeObj = (Map<String, Object>) shemeMap.get(schemeid);
            } else {
                schemeObj = new HashMap<String, Object>();
                shemeMap.put(schemeid, schemeObj);
            }
            Map<String, Object> aprInfo = (Map<String, Object>) schemeObj.get("aprInfo");
            if (aprInfo == null) {
                aprInfo = new HashMap<String, Object>();
                String sheetid = wf.getBizid();
                aprInfo.put("sheetid", sheetid);
                aprInfo.put("perfCnt", 1);
                aprInfo.put("turn", wf.getStepserial());
                schemeObj.put("aprInfo", aprInfo);
            } else {
                Integer perfcnt = (Integer) aprInfo.get("perfCnt") + 1;
                aprInfo.put("perfCnt", perfcnt);
            }
        }
        //评分
        BaseParam param = new BaseParam();
        param.setBiztype(EnumWorkflowType.performance);
        param.setWorkstep(EnumWorkStep.step2);
        param.setCurrentOperator(staffid);
        param.setWorkflowState(EnumWorkflowState.PENDING);
        List<WorkflowEngine> aopwfList = wfService.queryWorkflowEngine(param);
        for (WorkflowEngine wf : aopwfList) {
            String schemeid = wf.getBizinfo();
            Map<String, Object> schemeObj = null;
            if (shemeMap.containsKey(schemeid)) {
                schemeObj = (Map<String, Object>) shemeMap.get(schemeid);
            } else {
                schemeObj = new HashMap<String, Object>();
                shemeMap.put(schemeid, schemeObj);
            }
            Map<String, Object> appInfo = (Map<String, Object>) schemeObj.get("appInfo");
            if (appInfo == null) {
                appInfo = new HashMap<String, Object>();
                String sheetid = wf.getBizid();
                appInfo.put("sheetid", sheetid);
                appInfo.put("perfCnt", 1);
                appInfo.put("turn", wf.getStepserial());
                schemeObj.put("appInfo", appInfo);
            } else {
                Integer perfcnt = (Integer) appInfo.get("perfCnt") + 1;
                appInfo.put("perfCnt", perfcnt);
            }
        }
        // 重新组装shemeMap 返回数据到result
        List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
        for (String schemeid : shemeMap.keySet()) {
            Map<String, Object> schemeObj = (Map<String, Object>) shemeMap.get(schemeid);
            schemeObj.put("schemeid", schemeid);
            Scheme scheme = daoex.load(Scheme.class, schemeid);
            schemeObj.put("schemename", scheme.getSchemename());
            schemeObj.put("schememode", scheme.getSchememode());
            schemeObj.put("periodcode", scheme.getPeriodcode()); // 排序
            Integer pcount = 3;
            if (schemeObj.get("fillInfo") == null) {
                HashMap<String, Object> fillInfo = new HashMap<String, Object>();
                fillInfo.put("sheetid", "");
                fillInfo.put("perfCnt", 0);
                schemeObj.put("fillInfo", fillInfo);
                pcount -= 1;
            }
            if (schemeObj.get("aprInfo") == null) {
                HashMap<String, Object> aprInfo = new HashMap<String, Object>();
                aprInfo.put("sheetid", "");
                aprInfo.put("perfCnt", 0);
                schemeObj.put("aprInfo", aprInfo);
                pcount -= 1;
            }
            if (schemeObj.get("appInfo") == null) {
                HashMap<String, Object> appInfo = new HashMap<String, Object>();
                appInfo.put("sheetid", "");
                appInfo.put("perfCnt", 0);
                schemeObj.put("appInfo", appInfo);
                pcount -= 1;
            }
            schemeObj.put("pcount", pcount); //
            result.add(schemeObj);
        }
        Collections.sort(result, new Comparator<Map<String, Object>>() {
            public int compare(Map<String, Object> o1, Map<String, Object> o2) {
                String per1 = (String) o1.get("periodcode");
                String per2 = (String) o2.get("periodcode");
                return per1.compareTo(per2);
            }
        });
        return result;
    }

	/**
	 * 我的绩效
	 * 
	 * @param staffid
	 * @return
	 */
	@Override
	public List<Map<String, Object>> queryAchievement(String staffid) {
		List<Map<String, Object>> rslt = new ArrayList<Map<String, Object>>();
		Condition sheet_cdtn = new Condition();
		sheet_cdtn.addExpression("staffid", staffid);
		sheet_cdtn.addExpression("enablestate", true);
		Sorter sorter = new Sorter(Sort.Direction.ASC, "periodcode");
		// 查询考核对象是本人的量表
		List<Sheet> sheetlist = daoex.find(Sheet.class, sheet_cdtn, sorter);

		// 子方案的主方案发布了，子方案就不再显示
		Set<String> releaseMainSchemeSet = getMainSchemeState(sheetlist);
		List<String> aprsht_ids = new ArrayList<String>();
		for (Sheet shet : sheetlist) {
			if (releaseMainSchemeSet.contains(shet.getSchemeid()))
				continue;
			Scheme scheme = daoex.load(Scheme.class, shet.getSchemeid());
			if(scheme.isIsend())
				continue;
			int schemestate = scheme.getSchemestate();
			int markStatus = shet.getMarkStatus();
			HashMap<String, Object> rs_map = new HashMap<String, Object>();
			if (schemestate == CommonValue.EnumSchemeState.State3.getIndex()
					|| schemestate == CommonValue.EnumSchemeState.State4.getIndex()) {
				if (markStatus == 0 || markStatus == 1) {// 填报
					rs_map.put("tag_code", 1);// 填报
					rs_map.put("tag_name", "指标填报");
					rs_map.put("audit_comment", getCallbackApr(shet.getId()));
				} else if (markStatus == 2) {
					rs_map.put("tag_code", 2);// 填报已提交 可收回
					rs_map.put("tag_name", "指标待审核");
				} else {
					rs_map.put("tag_code", 3);// 指标审核
					rs_map.put("tag_name", "指标审核");
				}
			} else if (schemestate == CommonValue.EnumSchemeState.State5.getIndex()) {
				// 评分中的有可能需要填报
				if (markStatus == 0 || markStatus == 1) {// 填报
					rs_map.put("tag_code", 1);// 填报
					rs_map.put("tag_name", "指标填报");
					rs_map.put("audit_comment", getCallbackApr(shet.getId()));
				} else if (markStatus == 2) {
					rs_map.put("tag_code", 2);// 填报已提交 可收回
					rs_map.put("tag_name", "指标待审核");
				} else {
					aprsht_ids.add(shet.getId()); // aprsht_ids 用于后面检查是否有自评得人员
					continue;
				}
			} else if (schemestate == CommonValue.EnumSchemeState.State6.getIndex()) {
				// 评分阶段
				aprsht_ids.add(shet.getId());
				continue;
			} else if (schemestate == CommonValue.EnumSchemeState.State7.getIndex()
					|| schemestate == CommonValue.EnumSchemeState.State8.getIndex()) {
				// 结果审核环节 ||schemestate == 8 结果已发布的不显示
				rs_map.put("tag_code", 7);// 结果审核
				rs_map.put("tag_name", "结果审核");
				// 查询本人在评分中轮次
				Condition condObj = new Condition();
				condObj.addExpression("sheetid", shet.getId());
				condObj.addExpression("appraiser", staffid);
				List<Appraise> apprList = daoex.find(Appraise.class, condObj, null);
				// 本人可能不参与评分
				if (!apprList.isEmpty())
					rs_map.put("turn", apprList.get(0).getTurn());
			} else if (scheme.isIsresultconfirm() && !scheme.isIsend()
					&& schemestate >= CommonValue.EnumSchemeState.State9.getIndex()) {
				rs_map.put("tag_code", 8);// 员工确认
				rs_map.put("tag_name", "结果认可");
			} else if (scheme.isIsviewresult() && schemestate >= CommonValue.EnumSchemeState.State5.getIndex()) {
				//add by@chenzf添加不查看结果数据 2022-1-12 18:08:33 begin
				//结果已审核后不能看到
				continue;
				//add by@chenzf添加不查看结果数据 2022-1-12 18:08:33 end	
			}
			else {
				continue;
			}
			Period period = daoex.load(Period.class, scheme.getPeriodid());
			rs_map.put("schemename", scheme.getSchemename());
			rs_map.put("schemeid", scheme.getId());
			rs_map.put("schememode", scheme.getSchememode()); 
			rs_map.put("periodname", period.getPeriodname());
			rs_map.put("periodcode", period.getPeriodcode());// 排序用
			rs_map.put("sheetid", shet.getId());
			rs_map.put("deadline", 0);
			rs_map.put("creationtime", scheme.getCreationtime());
			rslt.add(rs_map);
		}
		// 评分中只查自评的
		BaseParam apprparam = new BaseParam();
		apprparam.setBiztype(EnumWorkflowType.performance);
		apprparam.setBizids(aprsht_ids);// 自己的量表
		apprparam.setWorkstep(EnumWorkStep.step2); // 评分
		List<WorkflowEngine> aprwfList = wfService.queryWorkflowEngine(apprparam);
		for (String sheetid : aprsht_ids) {
        	 //List<WorkflowEngine> workflow_list = aprwfList.stream().filter(obj -> obj.getBizid().equals(sheetid)).collect(Collectors.toList());
        	 List<WorkflowEngine> workflow_list = ListHelper.filter(aprwfList, "getBizid", ListHelper.Operator.EQUAL, sheetid);
        	 if(workflow_list.size() == 0)
        		 continue;
        	 //workflow_list.stream().sorted(Comparator.comparing(WorkflowEngine::getStepserial).reversed());
        	 Collections.sort(workflow_list, new Comparator<WorkflowEngine>() {
				@Override
				public int compare(WorkflowEngine o1, WorkflowEngine o2) {
					//return o1.getStepserial() - o2.getStepserial();
					return o2.getStepserial() - o1.getStepserial();
				}
			 }); // .reversed()
			HashMap<String, Object> rs_map = new HashMap<String, Object>();
			rs_map.put("tag_code", 6);// 查看评分指标，未区分未到达和没有本人评分
			rs_map.put("tag_name", "指标评价-查看指标");
			// rs_map.put("turn", 1);
			for (WorkflowEngine flow : workflow_list) {
				int state = flow.getState();
				if (EnumWorkflowState.PASS_AUDIT.getIndex() == state
						|| EnumWorkflowState.HAVE_FINAL.getIndex() == state) {
					if (!rs_map.containsKey("turn"))
						rs_map.put("turn", flow.getStepserial());
				}
				if (staffid.equals(flow.getDisposeperson())) {
					if (state == EnumWorkflowState.PENDING.getIndex()) { // 待自评
						rs_map.put("tag_code", 4);// 自评
						rs_map.put("tag_name", "指标评价");
						rs_map.put("turn", flow.getStepserial());// 为了跳评分
					} else if (EnumWorkflowState.PASS_AUDIT.getIndex() == state
							|| EnumWorkflowState.HAVE_FINAL.getIndex() == state) {
						rs_map.put("tag_code", 5);// 收回自评
						rs_map.put("tag_name", "收回评价");
						rs_map.put("turn", flow.getStepserial());
					} else { // EnumWorkflowState.NO_ARRIVE 未到达的只能查看
					}
				}
			}
			WorkflowEngine engine = workflow_list.get(0);
			Scheme scheme = daoex.load(Scheme.class, engine.getBizinfo());
			Period period = daoex.load(Period.class, scheme.getPeriodid());
			rs_map.put("schemename", scheme.getSchemename());
			rs_map.put("schememode", scheme.getSchememode()); 
			rs_map.put("schemeid", scheme.getId());
			rs_map.put("periodname", period.getPeriodname());
			rs_map.put("periodcode", period.getPeriodcode());// 排序用
			rs_map.put("sheetid", engine.getBizid());
			rs_map.put("deadline", 0);
			rs_map.put("creationtime", scheme.getCreationtime());// 用于排序
			rslt.add(rs_map);
		}
		// 排序规则 ： 按 年->半年->季度->月 降序排
		Collections.sort(rslt, new Comparator<Map<String, Object>>() {
			public int compare(Map<String, Object> o1, Map<String, Object> o2) {
				String periodcode1 = (String) o1.get("periodcode");
				String periodcode2 = (String) o2.get("periodcode");
				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 {
					Date creation1 = (Date) o1.get("creationtime");
					Date creation2 = (Date) o2.get("creationtime");
					if(creation1.getTime() > creation2.getTime()){
						return -1;
					} else if (creation1.getTime() < creation2.getTime()){
						return 1;
					} else {
						return 0;
					}
				}
			}
		});
		return rslt;
	}
    
    /**
     * 获取被驳回得审核意见
     * @return
     */
    private String getCallbackApr(String sheetid){
    	String audit_comment = null;
    	//去审核人里面查看 审核意见 字段是否为空。
		Condition apprcondition = new Condition();
		apprcondition.addExpression("sheetid", sheetid);
		List<Approver> approverList = daoex.find(Approver.class,
				apprcondition, new Sorter(Direction.ASC, "apr_level"));
		for(Approver appr : approverList){
			if(appr.getComment() != null){
				audit_comment = appr.getComment();
			} else {
				break;
			}
		}
		return audit_comment;
    }
    
	/**
	 * 通过stafflist获取名称拼接
	 *
	 * @param staffids
	 * @return
	 */
	private String getStaffNamesByStaffids(List<String> staffids) {
		Map<String, PmStaff> staffList = StaffHelper
				.queryStaffByIds2(staffids, false);
		List<PmStaff> pl = new ArrayList<>();
		for (String str : staffids) {
			pl.add(staffList.get(str));
		}
		StringBuilder pmStaff = new StringBuilder();
		for (PmStaff p : pl) {
			if (p != null) {
				pmStaff.append(p.name).append(",");
			}
		}
		return pmStaff.toString().substring(0,
				pmStaff.toString().lastIndexOf(","));
	}

	/**
	 * 获取子方案对应主方案已发布的子方案id集合
	 * 
	 * @param sheetlist
	 * @return 已发布的子方案id
	 */
	private Set<String> getMainSchemeState(List<Sheet> sheetlist) {
		Set<String> ret = new HashSet<>();
		if (sheetlist.isEmpty())
			return ret;
		// 查找子方案的主方案
		List<String> subSchemeids = sheetlist.stream().map(obj -> obj.getSchemeid()).distinct()
				.collect(Collectors.toList());
		Condition cond = new Condition();
		cond.addExpression("formulaschemeid", subSchemeids, Operator.IN);
		cond.addExpression("formulaschememode", CommonValue.EnumSchemeMode.pm_mtr.getIndex());
		List<SchemeRelation> schemeRet = daoex.find(SchemeRelation.class, cond, null);
		if (schemeRet.isEmpty())
			return ret;
		List<String> mainSchemeids = schemeRet.stream().map(obj -> obj.getSchemeid()).distinct()
				.collect(Collectors.toList());
		// 查询发布的主方案
		cond = new Condition();
		cond.addExpression("id", mainSchemeids, Operator.IN);
		cond.addExpression("schemestate", CommonValue.EnumSchemeState.State9.getIndex());
		List<Scheme> schemeList = daoex.find(Scheme.class, cond, null);
		if (schemeList.isEmpty())
			return ret;
		// 循环主子方案关系，如果在发布的主方案中，则需返回
		mainSchemeids = schemeList.stream().map(obj -> obj.getId()).collect(Collectors.toList());
		Set<String> releaseMainSchemeSet = new HashSet<>(mainSchemeids);
		for (SchemeRelation item : schemeRet) {
			if (releaseMainSchemeSet.contains(item.getSchemeid()))
				ret.add(item.getFormulaschemeid());
		}
		return ret;
	}
}
