package com.lz.modules.sys.service.app.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lz.common.emun.WorkMsgTypeEnum;
import com.lz.common.exception.RRException;
import com.lz.common.utils.*;
import com.lz.modules.app.dao.DepartmentsDao;
import com.lz.modules.app.dao.DepartmentsStaffRelateDao;
import com.lz.modules.app.dto.ApprovalDto;
import com.lz.modules.app.dto.EmployeesDto;
import com.lz.modules.app.dto.GraphicsStatisticalDto;
import com.lz.modules.app.entity.DepartmentsEntity;
import com.lz.modules.app.entity.DepartmentsStaffRelateEntity;
import com.lz.modules.app.entity.StaffEntity;
import com.lz.modules.app.enums.FlowApprovalRoleTypeEnums;
import com.lz.modules.app.enums.FlowRecordStatusEnums;
import com.lz.modules.app.req.ResultRecordReq;
import com.lz.modules.app.resp.OwnResultResp;
import com.lz.modules.app.resp.ResultRecordResp;
import com.lz.modules.app.service.DepartmentsService;
import com.lz.modules.app.service.DepartmentsStaffRelateService;
import com.lz.modules.app.service.StaffService;
import com.lz.modules.app.utils.t.TwoTuple;
import com.lz.modules.flow.entity.*;
import com.lz.modules.flow.enums.FlowRecordEnum;
import com.lz.modules.flow.model.*;
import com.lz.modules.flow.service.*;
import com.lz.modules.job.business.DingtalkBusiness;
import com.lz.modules.performance.res.ChartStatistical;
import com.lz.modules.sys.dao.app.ResultRecordMapper;
import com.lz.modules.sys.entity.SysUserEntity;
import com.lz.modules.sys.entity.app.ResultComment;
import com.lz.modules.sys.entity.app.ResultDetail;
import com.lz.modules.sys.entity.app.ResultRecord;
import com.lz.modules.sys.service.app.ResultCommentService;
import com.lz.modules.sys.service.app.ResultDetailService;
import com.lz.modules.sys.service.app.ResultRecordService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 业绩记录表 服务类
 * </p>
 *
 * @author quyixiao
 * @since 2020-08-10
 */

@Service
@Slf4j
public class ResultRecordServiceImpl extends ServiceImpl<ResultRecordMapper, ResultRecord> implements ResultRecordService {


    @Autowired
    private ResultRecordMapper resultRecordMapper;




    private static EmployeesDto employeesDto;

    @Autowired
    private DepartmentsDao departmentsDao;

    @Autowired
    private DepartmentsStaffRelateDao departmentsStaffRelateDao;

    @Autowired
    private StaffService staffService;

    @Autowired
    private FlowDepartmentService flowDepartmentService;

    @Autowired
    private StaffRoleService staffRoleService;

    @Autowired
    private DepartmentsService departmentsService;

    @Autowired
    private RecordAuthService recordAuthService;

    @Autowired
    private FlowRelationService flowRelationService;

    @Autowired
    private FlowService flowService;

    @Autowired
    private FlowRecordService flowRecordService;


    @Autowired
    private StaffRoleDepartmentService staffRoleDepartmentService;

    @Autowired
    private ResultRecordService resultRecordService;

    @Autowired
    private DepartmentsStaffRelateService departmentsStaffRelateService;

    @Autowired
    private ResultDetailService resultDetailService;

    @Autowired
    private ResultCommentService resultCommentService;

    @Autowired
    private DingtalkBusiness dingtalkBusiness;

    @Autowired
    private FlowApprovalRoleService flowApprovalRoleService;

    @Autowired
    private  FlowChartService flowChartService;

    @Value("${dingtalk.appid}")
    private String appid;

    @Value("${domain.main}")
    private String domain;

    @Override
    public ResultRecord selectResultRecordById(Long id) {
        return resultRecordMapper.selectResultRecordById(id);
    }


    @Override
    public Long insertResultRecord(ResultRecord resultRecord) {
        return resultRecordMapper.insertResultRecord(resultRecord);
    }


    @Override
    public int updateResultRecordById(ResultRecord resultRecord) {
        return resultRecordMapper.updateResultRecordById(resultRecord);
    }


    @Override
    public int updateCoverResultRecordById(ResultRecord resultRecord) {
        return resultRecordMapper.updateCoverResultRecordById(resultRecord);
    }

    @Override
    public int deleteResultRecordById(Long id) {
        return resultRecordMapper.deleteResultRecordById(id);
    }

    @Override
    public int deleteResultRecordById2(Long id) {
        return resultRecordMapper.deleteResultRecordById2(id);
    }

    @Override
    public R queryPage(ResultRecordReq params, SysUserEntity user) {
        List<String> departmentIds = new ArrayList<>();
        List<DepartmentsEntity> tDepartments = departmentsDao.selectAll();
        if (StringUtil.isNotBlank(params.getDepartment1()) || StringUtil.isNotBlank(params.getDepartment2())
                || StringUtil.isNotBlank(params.getDepartment3())) {
            Map<String,List<DepartmentsEntity>> departmentMap = null;
            if(employeesDto == null || employeesDto.getExpire() < new Date().getTime()){
                departmentMap = getStringListMap(tDepartments);
                Date expire = DateUtils.addMinute(new Date(),30);
                EmployeesDto newDto = new EmployeesDto(expire.getTime(),departmentMap);
                employeesDto = newDto;
                log.info("使用新数据");
            }else{
                log.info("使用缓存");
                departmentMap = employeesDto.getCacheMap();
            }
            if (StringUtil.isNotBlank(params.getDepartment3())) {
                getChildIds(departmentIds, params.getDepartment3(), departmentMap);
            } else if (StringUtil.isNotBlank(params.getDepartment2())) {
                getChildIds(departmentIds, params.getDepartment2(), departmentMap);
            } else if (StringUtil.isNotBlank(params.getDepartment1())) {
                getChildIds(departmentIds, params.getDepartment1(), departmentMap);
            }
        }

        if(StringUtil.isNotBlank(params.getStatusStr())){
            String status [] = params.getStatusStr().split(",");
            List<Long> listx = new ArrayList<>();
            if(status !=null){
                for(String l : status){
                    listx.add(NumberUtil.objToLongDefault(l,-1));
                }
                params.setStatusList(listx);
            }
        }

        params.setDepartmentIds(departmentIds);
        String departmentLevel = Constant.ME;
        if (params.getIsSelf() != 1) { // 表示点击我们审批
            StaffRole staffRole = staffRoleService.selectByStaffId(user.getUserId());
            if (staffRole != null) {
                departmentLevel = staffRole.getDepartmentLevel();
            } else {
                FlowDepartment flowDepartment = flowDepartmentService.selectByStaffId(user.getUserId());
                if (flowDepartment != null) {
                    departmentLevel = flowDepartment.getDepartmentLevel();
                }
            }
        }
        params.setDepartmentLevel(departmentLevel);

        if ("1,2,3,4,5,6,7".equals(params.getStatusStr()) && "HR".equals(departmentLevel)) { //如果是查看全部，并且用户角色是HR 的话，可以推动一切
            params.setDepartmentLevel(null);
        }
        if ("1,2,5".equals(params.getStatusStr()) || "3".equals(params.getStatusStr())) {
            params.setApprovalStaffId(user.getUserId());
        }
        PageUtils pageUtils = PageUtils.startPage(params.getPage(), params.getLimit()).doSelect(
                page -> resultRecordMapper.selectByConditionByLeader(page, params)
        );

        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM");
        List<ResultRecord> resultRecords = pageUtils.getList();
        if (CollectionUtils.isNotEmpty(resultRecords)) {
            List<ResultRecordResp> list = new ArrayList<>();
            for (ResultRecord resultRecord : resultRecords) {
                ResultRecordResp resp = new ResultRecordResp();
                BeanUtils.copyProperties(resultRecord, resp);
                Map<Long, Long> staffRoleMap = recordAuthService.selectRoleIdByStaffRoleInfo(resultRecord.getFlowStaffIdRole());
                if (resp.getStatus().equals(5) && staffRoleMap.get(user.getUserId()) == null) {
                    resp.setStatus(1); // 如果不是自己审批，说明自己己经审批完成
                }
                resp.setMonthTimeStr(df.format(resultRecord.getMonthTime()));
                list.add(resp);
            }
            pageUtils.setList(list);
        }
        return R.ok().put("page", pageUtils)
                .put("departmentLevel",departmentLevel);
    }

    @Override
    public Map<String, List<DepartmentsEntity>> getStringListMap(List<DepartmentsEntity> tDepartments) {
        Map<String, List<DepartmentsEntity>>  departmentMap = new HashMap<>();
        for(DepartmentsEntity department : tDepartments) {
            List<DepartmentsEntity> list = new ArrayList<>();
            for(DepartmentsEntity child : tDepartments) {
                if(child.getDepartmentParentId().equals(department.getDepartmentId())){
                    list.add(child);
                }
            }
            departmentMap.put(department.getDepartmentId(), list);
        }
        return departmentMap;
    }

    @Override
    public ResultRecord selectResultRecordByStaffIdStatus(Long staffId, int status) {
        return resultRecordMapper.selectResultRecordByStaffIdStatus(staffId, status);
    }

    public void getChildIds(List<String> childDepartIds ,String parentId,Map<String,List<DepartmentsEntity>> departmentMap ){
        childDepartIds.add(parentId);
        List<DepartmentsEntity > tDepartments = departmentMap.get(parentId);
        if(CollectionUtils.isNotEmpty(tDepartments)){
            for(DepartmentsEntity tDepartment:tDepartments){
                getChildIds(childDepartIds,tDepartment.getDepartmentId(),departmentMap);
            }
        }
    }


    @Override
    public void deleteBatchIds(List<Long> asList) {

    }

    @Override
    public ResultRecord selectResultRecordByStaffId(Long staffId) {

        return resultRecordMapper.selectResultRecordByStaffId(staffId);
    }

    @Override
    public void updateFlowStaffIdRoleToNull(Long id,Integer status) {
        resultRecordMapper.updateFlowStaffIdRoleToNull(id,status);
    }

    @Override
    public TwoTuple getFlowInfo(Long staffId, Integer type) {
        FlowDepartment flowDepartment = flowDepartmentService.selectByStaffId(staffId);
        List<FlowDepartment> list = new ArrayList<>();
        Long flowId = flowDepartment != null ? TypeFlowDto.getFlowId(flowDepartment.getFlowIds(), Constant.SELF, type) : 0l;       // 表示是部门主管自己
        if (flowDepartment == null) {
            DepartmentsStaffRelateEntity leader = getLeaderDepartmentsStaffRelateEntity(staffId);
            flowDepartment = flowDepartmentService.selectByStaffId(leader.getStaffId());
            flowId = TypeFlowDto.getFlowId(flowDepartment.getFlowIds(), Constant.CHILD, type);//表示是部门下的普通员工
            list.add(flowDepartment);
        }
        for (int i = 0; i < 10; i++) {
            if (flowDepartment.getParentId() != null && flowDepartment.getParentId() > 0) {
                flowDepartment = flowDepartmentService.selectFlowDepartmentById(flowDepartment.getParentId());
                list.add(flowDepartment);
            } else {
                break;
            }
        }
        return new TwoTuple(flowId, list);
    }

    @Override
    public DepartmentsStaffRelateEntity getLeaderDepartmentsStaffRelateEntity(Long staffId){
        DepartmentsStaffRelateEntity departmentsStaffRelateEntity = departmentsStaffRelateService.selectLastDepartmentByStaffId(staffId);
        DepartmentsStaffRelateEntity leader = departmentsStaffRelateService.selectLeaderByDepartmentId(departmentsStaffRelateEntity.getDepartmentId());
        if(leader == null){
            Map<String, String> map = departmentsService.selectUserAllDepartmentInFo(departmentsStaffRelateEntity.getDepartmentId());
            if (StringUtil.isNotBlank(map.get("dd2"))) {
                leader = departmentsStaffRelateService.selectLeaderByDepartmentId(map.get("dd2"));
                if(leader ==null  && StringUtil.isNotBlank(map.get("dd3"))){
                    leader = departmentsStaffRelateService.selectLeaderByDepartmentId(map.get("dd3"));
                    return leader;

                }
            }
        }
        return leader;
    }

    @Override
    public ResultRecord selectLastResultRecordByStaffIdType(Long staffId, int type) {
        return resultRecordMapper.selectLastResultRecordByStaffIdType(staffId,type);
    }

    @Override
    public ResultRecord selectCurrentMonthResultRecordByStaffIdType(Long staffId, int type) {
        return resultRecordMapper.selectCurrentMonthResultRecordByStaffIdType(staffId,type);
    }

    @Override
    public List<ResultRecord> selectResultRecordAllByStaffId(Long staffId) {

        return resultRecordMapper.selectResultRecordAllByStaffId(staffId);
    }


    @Override
    public ResultRecord createResultRecord(Long staffId, int type, Long roleId) {
        StaffEntity staffEntity = staffService.selectStaffById(staffId);
        ResultRecord resultRecord = new ResultRecord();
        resultRecord.setMonthTime(new Date());
        resultRecord.setFlowStaffIdRole(resultDetailService.initRole(staffId, roleId));
        resultRecord.setStaffId(staffId);
        resultRecord.setStatus(0);
        resultRecord.setType(type);
        resultRecord.setGmtCreate(new Date());
        resultRecord.setGmtModified(new Date());
        resultRecord.setStaffName(staffEntity.getName());
        DepartmentsStaffRelateEntity relateEntity = departmentsStaffRelateService.selectLastDepartmentByStaffId(staffId);
        Map<String, String> map = departmentsService.selectUserAllDepartmentIds(relateEntity.getDepartmentId());
        resultRecord.setDepartmentId(relateEntity.getDepartmentId());
        resultRecord.setDepartmentName(map.get(relateEntity.getDepartmentId()));
        resultRecordService.insertResultRecord(resultRecord);
        return resultRecord;
    }

    @Override
    public ResultRecord initResult(Long staffId, Integer recordType, Long roleId) {
        ResultRecord resultRecordOld = resultRecordService.selectLastResultRecordByStaffIdType(staffId,1);
        ResultRecord resultRecordNew = null;
        if (resultRecordOld != null) {
            Long oldResultRecordId = resultRecordOld.getId();
            Long recordId = resultRecordOld.getId();
            resultRecordOld.setId(null);
            resultRecordOld.setType(Constant.TWO);                      // 1 表示是目标，2 表示是业绩
            resultRecordOld.setStatus(0);
            resultRecordOld.setCurrentApprovalStaffId(staffId);
            resultRecordOld.setScoreLevel("0");
            StaffEntity staffEntity = staffService.selectStaffById(staffId);
            resultRecordOld.setCurrentApprovalStaffName(staffEntity.getName());
            resultRecordOld.setFlowStaffIdRole(resultDetailService.initRole(resultRecordOld.getStaffId(), roleId));
            resultRecordService.insertResultRecord(resultRecordOld);
            //删除月初目标
            resultRecordService.deleteResultRecordById2(oldResultRecordId);
            List<FlowRecord> flowRecords = flowRecordService.selectFlowRecordByResultRecordIdFlowId(oldResultRecordId);

            for(FlowRecord flowRecord : flowRecords){
                flowRecord.setRecordId(resultRecordOld.getId());
                flowRecord.setId(null);
                flowRecord.setType(Constant.ONE);
                //新增record
                flowRecordService.copyFlowRecord(flowRecord);
            }

            flowRecordService.initFlowRecord(resultRecordOld, roleId, recordType, "月未总结");
            resultRecordNew = resultRecordOld;
            List<ResultDetail> resultDetails = resultDetailService.selectByRecordId(recordId);
            if (CollectionUtils.isNotEmpty(resultDetails)) {
                // 保存业绩相关
                for (ResultDetail resultDetail : resultDetails) {
                    resultDetail.setRecordId(resultRecordNew.getId());
                    resultDetail.setId(null);
                    resultDetail.setType(1);                    // 表示业绩
                    resultDetailService.insertResultDetail(resultDetail);
                }
            }
        } else {
            resultRecordNew = resultRecordService.createResultRecord(staffId, recordType, roleId);
        }
        //保存文件价值观
        resultDetailService.insertWenHuaJiaZhiGua(Constant.WENHUAJIAZHIGUAN, resultRecordNew.getId(), staffId,new BigDecimal(0.3));
        return resultRecordNew;
    }

    @Override
    public R checkApproval(ResultRecord resultRecord,Long userId){
        Long recordId = resultRecord.getId();
        List<ResultDetail> resultDetails = resultDetailService.selectByRecordId(recordId);
        if (CollectionUtils.isEmpty(resultDetails)) {
            return R.error("请先添加绩效。");
        }
        double sum = resultDetails.stream().filter(p -> p.getType() == 1).mapToDouble(p -> NumberUtil.objToDoubleWithDefault(p.getCheckWeight(), 0d)).sum();
        if (sum < 0.7) {
            return R.error("recordId为[" + recordId + "]绩效权重之和必需等于0.7。");
        }

        Map<Long, Long> staffRoleMap = recordAuthService.selectRoleIdByStaffRoleInfo(resultRecord.getFlowStaffIdRole());
        List<RecordAuth>  listAuth = recordAuthService.selectAuthInfo(staffRoleMap.get(userId));
        Auth auth = recordAuthService.getAuth(listAuth);
        // 如果是评分，查看是不是所有内容都己经评分
        if(auth.getEditScore() == 1 ){
            for(ResultDetail resultDetail : resultDetails ){
                if(resultDetail.getAcquireScore().compareTo(BigDecimal.ZERO) <= 0 ){
                    return R.error("resultDetail[" + resultDetail.getId() + "] 评分必需 > 0 ");
                }
            }
        }
        return R.ok();
    }

    @Override
    public R approval(Long resultRecordId, Long userId,Integer status,boolean flagEnd) {
        ResultRecord resultRecord = resultRecordService.selectResultRecordById(resultRecordId);
        R r = resultRecordService.checkApproval(resultRecord,userId);
        if (!r.isSuccess()) {
            return r;
        }
        StaffEntity mySelf = staffService.selectStaffById(userId);
        TwoTuple<Long, List<FlowDepartment>> flowInfo = getFlowInfo(resultRecord.getStaffId(), resultRecord.getType());
        Long flowId = flowInfo.getFirst();
        List<FlowDepartment> list = flowInfo.getSecond();
        List<FlowRelation> flowRelations = flowRelationService.selectFlowRelationAll();
        Map<String, FlowDepartment> staffEntityMap = list.stream().collect(Collectors.toMap(FlowDepartment::getDepartmentLevel, p -> p));
        //approvalList = [ME,ONE_D,TWO_D,HR,BOSS]
        List<String> approvalList = new ArrayList<>();
        approvalList.add("ME");
        for (FlowRelation flowRelation : flowRelations) {
            if (staffEntityMap.get(flowRelation.getChild()) != null || flowRelation.getCanReplace() == 0) {
                approvalList.add(flowRelation.getChild());
            }
        }
        log.info("approvalList approval : " + Arrays.toString(approvalList.toArray()) );
        List<Flow> flows = flowService.selectByFlowId(flowId,0l);
        FlowRecord lastFlowRecord = flowRecordService.selectLastFlowRecordByRecordId(resultRecordId);
        FlowRecord notFlowRecord = flowRecordService.selectNotApprovalStaffIdFlowRecords(resultRecord.getId());
        if (notFlowRecord != null) {
            notFlowRecord.setApprovalStaffId(userId);
        }
        StaffEntity staff = staffService.selectStaffById(resultRecord.getStaffId());
        int flowIndex = lastFlowRecord != null ? lastFlowRecord.getFlowIndex() + 1 : 1;
        int index = getDepartmentLevelIndex(flows, flowIndex);
        if (index < 0 || index >= approvalList.size() || flagEnd) {             //表示流程己经结束
            lastFlowRecord.setFlowName(mySelf.getName() + "-审批通过");
            lastFlowRecord.setStatusName(FlowRecordEnum.END.getName());
            flowRecordService.updateCoverFlowRecordById(lastFlowRecord);
            resultRecordService.updateFlowStaffIdRoleToNull(resultRecord.getId(), status != null ? status : 4);// 更新状态
            if (flagEnd) {
                return R.ok("流程终止")
                        .put("from", staff)
                        .put("to", staff)
                        .put("type", WorkMsgTypeEnum.END);
            } else {
                return R.ok("流程审批结束")
                        .put("from", staff)
                        .put("to", staff)
                        .put("type", WorkMsgTypeEnum.PASS);
            }
        }
        FlowRecord flowRecord = new FlowRecord();
        flowRecord.setRecordId(resultRecordId);
        flowRecord.setRecordStaffId(resultRecord.getStaffId());
        flowRecord.setFlowIndex(flowIndex);
        flowRecord.setFlowId(flowId);
        String departmentLevel = approvalList.get(index);
        StaffEntity approvalStaff = null;
        List<StaffRoleDto> staffRoleDtos = new ArrayList<>();
        Long roleId = flows.get(flowIndex - 1).getRoleId();
        if (Constant.ME.equals(departmentLevel)) {                  //如果是自己
            approvalStaff = staff; // 是自己进行审批
            StaffRoleDto staffRoleDto = new StaffRoleDto(staff.getId(), roleId);
            staffRoleDtos.add(staffRoleDto);
        } else {
            FlowDepartment flowD = staffEntityMap.get(departmentLevel);
            if (flowD == null) {
                approvalStaff = getApprovalStaff(resultRecord, departmentLevel, staffRoleDtos, roleId);
            } else {
                approvalStaff = staffService.selectStaffById(flowD.getStaffId());
                StaffRoleDto staffRoleDto = new StaffRoleDto(approvalStaff.getId(), roleId);
                staffRoleDtos.add(staffRoleDto);
            }
        }
        flowRecord.setFlowName((approvalStaff != null ? approvalStaff.getName() + "-" : "") + flows.get(flowIndex - 1).getOptDesc());
        flowRecord.setApprovalStaffId(approvalStaff != null ? approvalStaff.getId() : null);
        flowRecord.setApprovalStaffName(approvalStaff != null ? approvalStaff.getName() : null);
        // 如果用户有 HR 的权限，又在 flow_department 表中有记录，则记录为 HR
        if (approvalStaff != null) {
            StaffRole staffRole = staffRoleService.selectByStaffId(approvalStaff.getId());
            if (staffRole != null) {
                departmentLevel = staffRole.getDepartmentLevel();
            }
        }
        flowRecord.setDepartmentLevel(departmentLevel);
        String staffRoles = JSON.toJSONString(staffRoleDtos);
        flowRecord.setFlowStaffIdRole(staffRoles);

        flowRecord.setStatusName(FlowRecordEnum.APPROVALING.getName());
        flowRecord.setType(resultRecord.getType());

        FlowRecord lastFlowRecordNoStatus = flowRecordService.selectLastFlowNoStatusRecordByRecordId(resultRecordId);
        // 如果上一步是开始，则不进行修改，如果上一步是确认中，改成提交，如果上一点是审批中，将上一步改成通过
        if (lastFlowRecordNoStatus != null) {
            if (!StringUtil.equals(lastFlowRecordNoStatus.getStatusName(), FlowRecordEnum.START.getName())
                    && !StringUtil.equals(lastFlowRecordNoStatus.getStatusName(), FlowRecordEnum.CONFIRM.getName())) {
                lastFlowRecordNoStatus.setStatusName(FlowRecordEnum.APPROVAL.getName());
                lastFlowRecordNoStatus.setGmtCreate(new Date());
            } else if (StringUtil.equals(lastFlowRecordNoStatus.getStatusName(), FlowRecordEnum.CONFIRM.getName())) {
                lastFlowRecordNoStatus.setStatusName(FlowRecordEnum.COMMIT.getName());
                lastFlowRecordNoStatus.setGmtCreate(new Date());
            }
            flowRecordService.updateFlowRecordById(lastFlowRecordNoStatus);
        }
        flowRecordService.insertFlowRecord(flowRecord);
        resultRecord.setFlowStaffIdRole(staffRoles);
        resultRecord.setStatus(status != null ? status : 1); //如果状态不为空，则使用传入进来的状态，如果状态为空，则默认1,审批中
        resultRecord.setCurrentApprovalStaffId(approvalStaff != null ? approvalStaff.getId() : null);
        resultRecord.setCurrentApprovalStaffName(approvalStaff != null ? approvalStaff.getName() : null);
        resultRecordService.updateResultRecordById(resultRecord);// 更新用户权限
        return R.ok("提交审批成功")
                .put("from", staff)
                .put("to", approvalStaff)
                .put("type", WorkMsgTypeEnum.SUBMIT);
    }

    @Override
    public StaffEntity getApprovalStaff(ResultRecord resultRecord, String departmentLevel,List<StaffRoleDto> staffRoleDtos, Long roleId) {
        StaffEntity approvalStaff = null;
        List<StaffRole> staffRoles = staffRoleService.selectByRole(departmentLevel);
        for (StaffRole staffRole : staffRoles) {
            List<StaffRoleDepartment> staffRoleDepartments = staffRoleDepartmentService.selectStaffRoleDepartmentByStaffRoleId(staffRole.getId());
            Map<String, String> departmentIdMap = departmentsService.selectUserAllDepartmentIds(resultRecord.getDepartmentId());
            for (StaffRoleDepartment staffRoleDepartment : staffRoleDepartments) {
                String value = departmentIdMap.get(staffRoleDepartment.getDepartmentId());
                if (StringUtil.isNotBlank(value)) {
                    StaffRoleDto staffRoleDto = new StaffRoleDto(staffRole.getStaffId(), roleId != null && roleId > 0 ? roleId :
                            TypeRoleDto.getRoleId(staffRole.getTypeRoleIds(), resultRecord.getType()));
                    staffRoleDtos.add(staffRoleDto);
                }
            }
        }
        if (staffRoleDtos.size() >= 1) { //表示只有一个审批的用户
            approvalStaff = staffService.selectStaffById(staffRoleDtos.get(0).getStaffId());
        }
        return approvalStaff;
    }

    @Override
    public List<ResultRecord> selectResultRecordByIds(List<Long> recordIds) {
        return resultRecordMapper.selectResultRecordByIds(recordIds);
    }


    @Override
    public int getDepartmentLevelIndex(List<Flow> list, int flowIndex) {
        if (flowIndex > list.size()) {
            return -1 ;
        }
        List<Flow> flows = new ArrayList<>();
        for(int i = 0 ;i < flowIndex ;i ++){
            flows.add(list.get(i));
        }
        int index = 0;
        for (Flow flow : flows) {
            String opt = flow.getOpt();
            String opts[] = opt.split("");
            for (String p : opts) {
                if ("+".equals(p)) {
                    index++;
                } else {
                    index--;
                }
            }
        }
        return index;
    }

    @Override
    public R commitApproval(ResultRecordReq req, Long userId) {
        ResultRecord resultRecord = resultRecordService.selectResultRecordById(req.getRecordResultId());
        if(req.getStatus() == 2 || req.getStatus() == 3 || req.getStatus() == 5 ){
            if (resultRecord.getCurrentApprovalStaffId() !=null && !userId.equals(resultRecord.getCurrentApprovalStaffId())) {
                return R.error("请勿重复提交");
            }
        }

        R r = null;
        int status = 1;
        FlowRecord lastUsedFlowRecord = flowRecordService.selectLastFlowRecordByRecordId(req.getRecordResultId());
        if (req.getStatus() == 2) {
            r = resultRecordService.approval(req.getRecordResultId(), userId,null,false);
        } else if (req.getStatus() == 3) {      //侍提交
            resultRecord.setStatus(Constant.STATUS_3);
            resultRecordService.updateResultRecordById(resultRecord);
        } else if (req.getStatus() == 5) { // 驳回
            status = 5;
            r = reject(resultRecord,status);
        } else if (req.getStatus() == 7) {
            List<FlowRecord> flowRecords = flowRecordService.selectFlowRecordByResultRecordIdType(req.getRecordResultId(), resultRecord.getType());
            if (flowRecords != null && flowRecords.size() == 2) {       // 表示可以撤回
                r = reject(resultRecord,5);
            } else if (flowRecords != null && flowRecords.size() > 2) {
                return R.error("你的领导己经审批，不能撤回了");
            }
        } else if (req.getStatus() == 8) {
            Long staffId = resultRecord.getStaffId();
            Long approvalStaffId = resultRecord.getCurrentApprovalStaffId();
            StaffEntity mySelf = staffService.selectStaffById(staffId);
            StaffEntity approvalStaff = staffService.selectStaffById(approvalStaffId);
            r = R.ok("成功")
                    .put("from", mySelf)
                    .put("to", approvalStaff)
                    .put("type", WorkMsgTypeEnum.URGING);
        }else if (req.getStatus() == 6){
            status = 6;
            // 回滚代码
            resultRecordService.reject(resultRecord,req.getStatus());
        }
        resultCommentService.addOrUpdateComment(req, userId, status,lastUsedFlowRecord);
        if(r != null){//下面推送消息
            if(r.isSuccess()){
                StaffEntity mySelf = (StaffEntity)r.get("from");
                StaffEntity toSelf = (StaffEntity)r.get("to");
                WorkMsgTypeEnum workMsgTypeEnum = (WorkMsgTypeEnum)r.get("type");
                sendWorkMSG(mySelf, toSelf, workMsgTypeEnum, req.getRecordResultId(), 1);
                return R.ok("成功");
            }
            return r;
        }
        return R.ok("成功");
    }

    @Override
    public R reject( ResultRecord resultRecord,Integer status){
        List<FlowRecord> flowRecords = flowRecordService.selectFlowRecordByResultRecordIdFlowId(resultRecord.getId());
        StaffEntity mySelf = staffService.selectStaffById(resultRecord.getStaffId());
        StaffEntity approvalStaff = mySelf;
        if (flowRecords.size() >= 2) {
            FlowRecord secondFlowRecord = flowRecords.get(flowRecords.size() - 2);
            resultRecord.setFlowStaffIdRole(secondFlowRecord.getFlowStaffIdRole());
            resultRecord.setStatus(status);                          //更新驳回状态为5
            List<StaffRoleDto> list = JSONObject.parseArray(resultRecord.getFlowStaffIdRole(), StaffRoleDto.class);
            if (CollectionUtils.isNotEmpty(list)) {
                StaffRoleDto staffRoleDto = list.get(0);
                approvalStaff = staffService.selectStaffById(staffRoleDto.getStaffId());
                resultRecord.setCurrentApprovalStaffId(approvalStaff != null ? approvalStaff.getId() : null);
                resultRecord.setCurrentApprovalStaffName(approvalStaff != null ? approvalStaff.getName() : null);
            }
            resultRecordService.updateResultRecordById(resultRecord);

            FlowRecord lastFlowRecord = flowRecords.get(flowRecords.size() - 1);
            lastFlowRecord.setStatus(1);
            flowRecordService.updateFlowRecordById(lastFlowRecord);

            FlowRecord lastFlowRecordNoStatus = flowRecordService.selectLastFlowNoStatusRecordByRecordId(resultRecord.getId());
            lastFlowRecordNoStatus.setStatusName(FlowRecordEnum.REJECT.getName());
            lastFlowRecordNoStatus.setGmtCreate(new Date());    //更新驳回时间
            flowRecordService.updateFlowRecordById(lastFlowRecordNoStatus);


            // 可能会被删除
            FlowRecord lastUsedFlowRecord = flowRecordService.selectLastFlowRecordByRecordId(resultRecord.getId());
            lastUsedFlowRecord.setId(null);
            lastUsedFlowRecord.setStatus(1);
            lastUsedFlowRecord.setStatusName(FlowRecordEnum.CONFIRM.getName());
            flowRecordService.insertFlowRecord(lastUsedFlowRecord);// 新插入一条提交记录

            if(mySelf.getId().longValue() == approvalStaff.getId().longValue()){//同一个人
                mySelf.setName("你");//用于替换消息中的@符号。无其他任何作用，不保存
            }
            return  R.ok("成功")
                    .put("from", mySelf)
                    .put("to", approvalStaff)
                    .put("type", WorkMsgTypeEnum.REJECT);
        }
        return R.error("驳回失败");
    }

    public void sendWorkMSG(StaffEntity mySelf, StaffEntity toSelf, WorkMsgTypeEnum workMsgTypeEnum
            , Long recordResultId, int count){
        String url = domain + "/management/dingtalklogin?url=";//免登接口
        String jump;
        if(count == 1){//一个提交
            log.info("单个提交推送消息");
            jump = domain + "/management/recorddetail?id=" + recordResultId
                    + "&recordType=3" ;//跳转接口
        }else{//批量提交
            log.info("批量提交推送消息");
            jump = domain + "/management/result-record-lzresultrecordapp";//跳转接口
        }

        jump = URLEncoder.encode(jump);
        String msg = dingtalkBusiness.sendWorkMSGByEntity(appid, mySelf, toSelf, workMsgTypeEnum, url + jump);
        log.info("发送钉钉工作消息{}", msg);
    }


    @Override
    public List<OwnResultResp> ownResult(Long userId, int status) {
        return resultRecordMapper.ownResult(userId,status);
    }

    @Override
    public List<GraphicsStatisticalDto> staffDistribution(String monthTime,List<String> staffIds) {

        return resultRecordMapper.staffDistribution(monthTime,staffIds);
    }

    @Override
    public List<ChartStatistical> countNumByFlowProcess(Long startId) {
        return resultRecordMapper.countNumByFlowProcess(startId);
    }

    @Override
    public List<ChartStatistical> countNumByScoreLevel(Long startId) {
        return resultRecordMapper.countNumByScoreLevel(startId);
    }

    @Override
    public void batchDeleteByStaffIds(List<String> staffIds) {

    }

    @Override
    public R initFlowRecord(Long resultRecordId) {
        ResultRecord resultRecord = resultRecordMapper.selectResultRecordById(resultRecordId);
        List<Flow> flows = flowService.selectByFlowId(resultRecord.getEvaluationId(),resultRecord.getStartId());
        List<Long> flowIds = new ArrayList<>();
        for(Flow flow:flows){
            flowIds.add(flow.getId());
        }
        List<FlowApprovalRole> flowApprovalRoles =flowApprovalRoleService.selectFlowApprovalRoleList(flowIds);
        int i = 0;
        List<FlowRecord> flowRecords = new ArrayList<>();
        for (FlowApprovalRole flowApprovalRole : flowApprovalRoles) {
            FlowRecord flowRecord = new FlowRecord();
            flowRecord.setRecordId(resultRecord.getId());
            StaffEntity staffEntity = new StaffEntity();
            if (FlowApprovalRoleTypeEnums.ME.getType().equals(flowApprovalRole.getType())) {
                staffEntity = staffService.selectStaffById(resultRecord.getStaffId());
            } else if (FlowApprovalRoleTypeEnums.STAFF.getType().equals(flowApprovalRole.getType())) {
                staffEntity = staffService.selectStaffById(flowApprovalRole.getApprovalId());
            } else if (FlowApprovalRoleTypeEnums.ONE_SUPPER.getType().equals(flowApprovalRole.getType())) {
                staffEntity = getDepartmentStaff(resultRecord.getStaffId(), 1);
            } else if (FlowApprovalRoleTypeEnums.TWO_SUPPER.getType().equals(flowApprovalRole.getType())) {
                staffEntity = getDepartmentStaff(resultRecord.getStaffId(), 2);
            } else if (FlowApprovalRoleTypeEnums.THREE_SUPPER.getType().equals(flowApprovalRole.getType())) {
                staffEntity = getDepartmentStaff(resultRecord.getStaffId(), 3);
            } else if (FlowApprovalRoleTypeEnums.FOUR_SUPPER.getType().equals(flowApprovalRole.getType())) {
                staffEntity = getDepartmentStaff(resultRecord.getStaffId(), 4);
            } else if (FlowApprovalRoleTypeEnums.FOUR_SUPPER.getType().equals(flowApprovalRole.getType())) {
                staffEntity = getDepartmentStaff(resultRecord.getStaffId(), 5);
            }
            flowRecord.setApprovalStaffName(staffEntity.getName());
            flowRecord.setApprovalStaffId(staffEntity.getId());
            flowRecord.setFlowName(getFlow(flows, flowApprovalRole.getFlowId()).getOptDesc());
            flowRecord.setRecordStaffId(resultRecord.getStaffId());
            flowRecord.setFlowId(flowApprovalRole.getFlowId());
            String staffRole = StaffRoles.getStaffRole(staffEntity.getId(), StringUtil.strToLongs(flowApprovalRole.getRoleId()));
            if (i == 0) {
                flowRecord.setStatus(FlowRecordStatusEnums.CURRENT_FLOW_STATUS.getStatus());
                resultRecord.setFlowStaffIdRole(staffRole);
                FlowChart flowChart = flowService.selectFlowChartByChartId(flowRecord.getFlowId());
                resultRecord.setFlowProcess(flowChart.getFlowProcess());
            } else {
                flowRecord.setStatus(FlowRecordStatusEnums.UN_TO_STATUS.getStatus());
            }
            flowRecord.setFlowStaffIdRole(staffRole);
            flowRecord.setFlowIndex(flowApprovalRole.getStepIndex());
            flowRecord.setType(flowApprovalRole.getStepType());         //步骤类型0：依次，1：或签（同时通知，一人通过或拒绝即可），2会签（同时通知，所有人同意才可）
            i++;
            flowRecords.add(flowRecord);
        }
        flowRecordService.insertFlowRecords(flowRecords);
        resultRecordService.updateResultRecordById(resultRecord);
        return R.ok();
    }

    @Override
    ////1 提交审批,审批通过,2 撤回,3 催办,4 跳过,5 驳回，6 申述，7 流程终止，8 转交
    public R newApproval(ApprovalDto approvalDto)  throws Exception{
        if(approvalDto.getResultRecordId() == null){
            throw  new RRException("resultRecordId 不能为空");
        }
        if(approvalDto.getStatus() == null ){
            throw  new RRException("status 不能为空");
        }
        if(StringUtil.isBlank(approvalDto.getMenuName())){
            throw new RRException("menuName 不能为空");
        }
        switch (approvalDto.getStatus()) {
            case 1: //1 提交审批,审批通过
                return newSubmit(approvalDto);
            case 2:     //2 撤回
                return reSubmit(approvalDto);
            case 3:     //3 催办
                return urge(approvalDto);
            case 5:     //5 驳回
                return newReject(approvalDto);
            case 6:     //6 申述
                return explain(approvalDto);
            case 8:     //6 转交
                if (approvalDto.getTransferStaffId() == null) {
                    throw new RRException("transferStaffId 不能为空");
                }
                if(approvalDto.getCurrentStaffId() == null){
                    throw new RRException("currentStaffId 不能为空");
                }
                return transfer(approvalDto);
            default:
                break;
        }
        return null;
    }

    private R transfer(ApprovalDto approvalDto) {
        return null;
    }

    private R reSubmit(ApprovalDto approvalDto) {
        List<FlowRecord> flowRecords = flowRecordService.selectFlowRecordByRecordIdStatus(approvalDto.getResultRecordId(), 1);
        if(flowRecords!=null && flowRecords.size()>0){
            return R.error("领导己经审批，不能撤回");
        }
        return newReject(approvalDto);
    }


    public void comment (ApprovalDto approvalDto,FlowChart flowChart){
        StaffEntity staffEntity = staffService.selectStaffById(approvalDto.getLoginUserId());
        if(staffEntity !=null ){
            ResultComment resultComment = new ResultComment();
            resultComment.setComment(approvalDto.getComment());
            resultComment.setStaffName(staffEntity.getName());
            resultComment.setRecordId(approvalDto.getResultRecordId());
            resultComment.setOptDesc(approvalDto.getMenuName()  + flowChart.getName());
            resultCommentService.insertResultComment(resultComment);
        }
    }

    private R newSubmit(ApprovalDto approvalDto) {
        ResultRecord resultRecord = resultRecordMapper.selectResultRecordById(approvalDto.getResultRecordId());
        if(approvalDto.getLoginUserId() == null){
            approvalDto.setLoginUserId(resultRecord.getCurrentApprovalStaffId());
        }
        List<FlowRecord> flowRecords = flowRecordService.selectFlowRecordByRecordIdStatus(approvalDto.getResultRecordId(),2);
        if(CollectionUtils.isEmpty(flowRecords)){
            log.info("流程己经结束");
            return R.ok("流程己经结束");
        }
        FlowRecord preFlowRecord = flowRecords.get(0);
        int stepType = preFlowRecord.getType();
        if (flowRecords != null && flowRecords.size() > 0) {
            if (stepType == 0 || stepType == 1) {           //表示只要一个人通过就可以了
                for (FlowRecord flowRecord : flowRecords) {
                    if (flowRecord.getApprovalStaffId().equals(approvalDto.getLoginUserId())) {
                        flowRecord.setStatus(FlowRecordStatusEnums.FINISHED_STATUS.getStatus());//当前审批己经完成
                    } else {
                        flowRecord.setStatus(FlowRecordStatusEnums.OTHER_APPROVAL.getStatus()); //其他审批
                    }
                    flowRecordService.updateFlowRecordById(flowRecord);
                }
            } else {
                boolean flag = false;
                FlowRecord currentFlowRecord = null;
                for (FlowRecord flowRecord : flowRecords) {
                    if (!flowRecord.getApprovalStaffId().equals(approvalDto.getLoginUserId())
                            && flowRecord.getStatus().equals(FlowRecordStatusEnums.CURRENT_FLOW_STATUS.getStatus())) {
                        flag = true;
                    } else {
                        currentFlowRecord = flowRecord;//当前流程 id
                    }
                }
                currentFlowRecord.setStatus(FlowRecordStatusEnums.FINISHED_STATUS.getStatus());//当前审批己经完成
                flowRecordService.updateFlowRecordById(currentFlowRecord);
                if (flag) {                         //流程未向下走
                    return R.ok("审批成功");
                }
            }
        } else {
            preFlowRecord.setStatus(FlowRecordStatusEnums.FINISHED_STATUS.getStatus());//流程己走
            flowRecordService.updateFlowRecordById(preFlowRecord);
            FlowChart flowChart = flowService.selectFlowChartByChartId(preFlowRecord.getFlowId());
            comment(approvalDto, flowChart);
        }

        List<FlowRecord> nextFlowRecords = flowRecordService.selectFlowRecordByRecordIdStatusFlowIndex(approvalDto.getResultRecordId(),0,preFlowRecord.getFlowIndex() + 1 );
        if(CollectionUtils.isEmpty(nextFlowRecords)){
            log.info("流程己经结束2");
            return R.ok("流程己经结束");
        }
        FlowRecord currentFlowRecord = nextFlowRecords.get(0);

        for (FlowRecord flowRecord : nextFlowRecords) {
            flowRecord.setStatus(FlowRecordStatusEnums.CURRENT_FLOW_STATUS.getStatus());
            flowRecordService.updateFlowRecordById(flowRecord);
        }
        FlowChart flowChart = flowService.selectFlowChartByChartId(currentFlowRecord.getFlowId());

        resultRecord.setFlowProcess(flowChart.getFlowProcess());
        resultRecord.setFlowStaffIdRole(nextFlowRecords.size() == 1 ? currentFlowRecord.getFlowStaffIdRole() : null);
        resultRecord.setCurrentApprovalStaffId(nextFlowRecords.size() == 1 ? currentFlowRecord.getApprovalStaffId() : null);
        resultRecord.setCurrentApprovalStaffName(nextFlowRecords.size() == 1 ? currentFlowRecord.getApprovalStaffName() : null);
        resultRecordService.updateCoverResultRecordById(resultRecord);
        return R.ok();
    }


    private R newReject(ApprovalDto approvalDto) {
        List<FlowRecord> currentflowRecords = flowRecordService.selectFlowRecordByRecordIdStatus(approvalDto.getResultRecordId(),FlowRecordStatusEnums.CURRENT_FLOW_STATUS.getStatus());
        if(currentflowRecords !=null && currentflowRecords.size() > 0 ){
            FlowRecord currentFlowRecord = currentflowRecords.get(0);
            // 更新当前数据
            // 获取当前审批结点组
            List<FlowRecord> currentFlowRecords = flowRecordService.selectFlowRecordByRecordIdFlowIndex(approvalDto.getResultRecordId(), currentFlowRecord.getFlowIndex());
            for(FlowRecord flowRecord : currentFlowRecords){
                flowRecord.setStatus(FlowRecordStatusEnums.UN_TO_STATUS.getStatus());
                flowRecordService.updateFlowRecordById(flowRecord);
            }
            FlowRecord currentApprovalFlowRecord = currentFlowRecords.get(0);
            FlowChart currentflowChart = flowService.selectFlowChartByChartId(currentApprovalFlowRecord.getFlowId());
            comment(approvalDto, currentflowChart); //评论

            // 恢复之前数据
            // 获取之前审批过的结点
            FlowRecord preFlowRecord = flowRecordService.selectPreFlowRecordByRecordIdMaxIdStatus(approvalDto.getResultRecordId(),
                    currentFlowRecord.getId(),FlowRecordStatusEnums.FINISHED_STATUS.getStatus());
            if(preFlowRecord != null) {
                // 获取之前审批结点组
                List<FlowRecord> flowRecords = flowRecordService.selectFlowRecordByRecordIdFlowIndex(approvalDto.getResultRecordId(), preFlowRecord.getFlowIndex());
                for (FlowRecord flowRecord : flowRecords) {
                    flowRecord.setStatus(FlowRecordStatusEnums.CURRENT_FLOW_STATUS.getStatus());
                    flowRecordService.updateFlowRecordById(flowRecord);
                }

                FlowRecord lastFlowRecord = flowRecords.get(0);
                ResultRecord resultRecord = resultRecordMapper.selectResultRecordById(approvalDto.getResultRecordId());
                resultRecord.setCurrentApprovalStaffId(flowRecords.size() == 1 ? lastFlowRecord.getApprovalStaffId():null);
                resultRecord.setCurrentApprovalStaffName(flowRecords.size() == 1 ?lastFlowRecord.getApprovalStaffName():null);
                resultRecord.setFlowStaffIdRole(flowRecords.size() == 1 ?lastFlowRecord.getFlowStaffIdRole():null);

                FlowChart flowChart = flowService.selectFlowChartByChartId(lastFlowRecord.getFlowId());
                resultRecord.setFlowProcess(flowChart.getFlowProcess());
                resultRecordService.updateCoverResultRecordById(resultRecord);
            }
        }
        return R.ok();
    }

    private R urge(ApprovalDto approvalDto) {
        ResultRecord resultRecord = resultRecordMapper.selectResultRecordById(approvalDto.getResultRecordId());
        if(!resultRecord.getCurrentApprovalStaffId().equals(approvalDto.getLoginUserId())){
            log.info("催办" +  resultRecord.getCurrentApprovalStaffId());
            StaffEntity mySelf = staffService.selectStaffById(resultRecord.getStaffId());
            StaffEntity toSelf = staffService.selectStaffById(resultRecord.getCurrentApprovalStaffId());
            resultRecordService.sendWorkMSG(mySelf, toSelf, WorkMsgTypeEnum.URGING, 0L, 2);
        }
        return R.ok();
    }

    private R explain(ApprovalDto approvalDto) {

        return R.ok();
    }

    public StaffEntity getDepartmentStaff(Long staffId, int level) {
        DepartManagers departManagers =  staffService.findLeader( staffId,  level);
        List<StaffEntity> staffEntities = departManagers.getManagers();
        if(CollectionUtils.isNotEmpty(staffEntities)){
            return staffEntities.get(0);
        }
        return new StaffEntity();

    }

    public Flow getFlow(List<Flow> flows,Long flowId){
       for(Flow flow : flows){
           if(flow.getId().equals(flowId)){
               return flow;
           }
       }
       return new Flow();
    }

}
