package com.lz.modules.performance.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.lz.common.emun.WorkMsgTypeEnum;
import com.lz.common.exception.RRException;
import com.lz.common.utils.PageUtils;
import com.lz.common.utils.R;
import com.lz.common.utils.StringUtil;
import com.lz.modules.app.dto.ApprovalDto;
import com.lz.modules.app.dto.StaffSimpleDto;
import com.lz.modules.app.entity.StaffEntity;
import com.lz.modules.app.entity.StaffSimpleInfo;
import com.lz.modules.app.service.StaffService;
import com.lz.modules.flow.dao.EvaluationGroupMapper;
import com.lz.modules.flow.dao.EvaluationStartStaffMapper;
import com.lz.modules.flow.dao.FlowRecordMapper;
import com.lz.modules.flow.dao.FlowStartMapper;
import com.lz.modules.flow.entity.EvaluationGroup;
import com.lz.modules.flow.entity.FlowStart;
import com.lz.modules.flow.model.GroupStaffs;
import com.lz.modules.flow.model.StartGroups;
import com.lz.modules.flow.service.EvaluationGroupService;
import com.lz.modules.flow.service.EvaluationStartStaffService;
import com.lz.modules.flow.service.FlowStartService;
import com.lz.modules.job.business.DingtalkBusiness;
import com.lz.modules.performance.dto.ToScoreDingTalkDto;
import com.lz.modules.performance.req.AssessChangeReq;
import com.lz.modules.performance.req.AssessDetailReq;
import com.lz.modules.performance.req.AssessListReq;
import com.lz.modules.performance.req.AssessToScoreReq;
import com.lz.modules.performance.res.AssessManagerDetailRes;
import com.lz.modules.performance.res.AssessManagerListRes;
import com.lz.modules.performance.service.AssessManagerService;
import com.lz.modules.performance.service.AssessService;
import com.lz.modules.sys.dao.app.ResultRecordMapper;
import com.lz.modules.sys.entity.app.ResultRecord;
import com.lz.modules.sys.service.app.ResultRecordService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

import static java.util.stream.Collectors.toList;

/**
 * @Author: djc
 * @Desc:
 * @Date: 2020/10/22 17:28
 */
@Service("assessManagerService")
@Slf4j
public class AssessManagerServiceImpl implements AssessManagerService {
    @Autowired
    private FlowStartMapper flowStartMapper;
    @Autowired
    private ResultRecordMapper resultRecordMapper;
    @Autowired
    private EvaluationGroupService evaluationGroupService;
    @Autowired
    private EvaluationStartStaffService evaluationStartStaffService;
    @Autowired
    private StaffService staffService;
    @Autowired
    private ResultRecordService resultRecordService;
    @Autowired
    private EvaluationStartStaffMapper evaluationStartStaffMapper;
    @Autowired
    private FlowStartService flowStartService;
    @Autowired
    private AssessService assessService;
    @Autowired
    private EvaluationGroupMapper evaluationGroupMapper;
    @Autowired
    private FlowRecordMapper flowRecordMapper;
    @Autowired
    private DingtalkBusiness dingtalkBusiness;



    @Override
    public PageUtils assessList(AssessListReq req) {
        List<AssessManagerListRes> data = Lists.newArrayList();
        PageUtils pageUtils = PageUtils.startPage(req.getCurrPage(),req.getPageSize()).doSelect(
                page -> flowStartMapper.selectListByTime(page,req.getCycleType(),req.getName())
        );
        List<FlowStart> list = pageUtils.getList();
        if(CollectionUtils.isEmpty(list)){
            log.info("未找到考核发起数据");
            return pageUtils;
        }
        List<String> mandepartmentIds = assessService.roleDepartments(req.getLoginUserId());
        list.forEach(flowStart -> {
            AssessManagerListRes res = new AssessManagerListRes();
            String name = flowStart.getName();
            res.setId(flowStart.getId());
            res.setName(name);
            if(name.contains("绩效考核")){
                res.setCycleTime(name.substring(0,name.lastIndexOf("绩效考核")));
            }
            //过滤非自己管理的人员
            //没有管理的部门
            if(mandepartmentIds!=null && mandepartmentIds.size()==0){
                res.setJoinNum("0人");
            }else {
                ResultRecord resultRecord = resultRecordMapper.selectOneByStartId(flowStart.getId(),mandepartmentIds);
                int i = resultRecordMapper.countStartAndGroupNum(flowStart.getId(),mandepartmentIds);
                res.setJoinNum(resultRecord == null? StringUtil.EMPTY : resultRecord.getStaffName()  + "等"+ i + "人");
            }

            data.add(res);
        });
        PageUtils pages = new PageUtils();
        pages.setTotalPage(pageUtils.getTotalPage());
        pages.setTotalCount(pageUtils.getTotalCount());
        pages.setCurrPage(req.getCurrPage());
        pages.setPageSize(req.getPageSize());
        pages.setList(data);
        return pages;
    }

    @Override
    public PageUtils assessDetail(AssessDetailReq req) {
        if(req.getStartId() == null ){
            throw new RRException("考核id不能为空");
        }
        //拼接拷贝组
        if(StringUtil.isNotBlank(req.getEvaluationIds())){
            req.setCopyEvaluationIds(evaluationGroupService.getEvaluationCopyIdsByEvaluationIds(req.getEvaluationIds(),req.getStartId()));
        }
        List<String> mandepartmentIds = assessService.roleDepartments(req.getLoginUserId());
        //没有管理的部门
        if(mandepartmentIds!=null && mandepartmentIds.size()==0){
            return new PageUtils();
        }
        req.setDepartmentIds(mandepartmentIds);
        PageUtils pageUtils = PageUtils.startPage(req.getCurrPage(),req.getPageSize()).doSelect(
                page ->  resultRecordMapper.selectAssessListByStartId(page,req)
        );
        List<AssessManagerDetailRes> list = pageUtils.getList();
        list.forEach(assessManagerDetailRes -> {
            StaffEntity staffEntity = staffService.selectStaffById(assessManagerDetailRes.getStaffId());
            assessManagerDetailRes.setAvatar(Optional.ofNullable(staffEntity.getAvatar()).orElse(StringUtil.EMPTY));
        });

        return pageUtils;
    }

    @Override
    public void accessDelete(FlowStart flowStart) {
        flowStart.setIsDelete(1);
        flowStartMapper.updateFlowStartById(flowStart);
        evaluationStartStaffMapper.deleteByStartId(flowStart.getId());
        String groupIds = flowStart.getGroupIds();
        if(StringUtil.isNotBlank(groupIds)){
            String[] split = groupIds.split(",");
            List<String> ids = Arrays.asList(split);
            List<Long> collect = ids.stream().map(s -> Long.valueOf(s)).collect(toList());
            //删除副本组
            evaluationGroupService.deleteByCopyIds(collect,flowStart.getId());
        }
        List<Long> ids = resultRecordMapper.selectIdsByStartId(flowStart.getId());
        if(CollectionUtils.isNotEmpty(ids)){
            log.info("删除resultRecordIds: " + JSON.toJSONString(ids));
            resultRecordMapper.batchDeleteByResultRecordIds(ids);
            //删除flowRecord
            flowRecordMapper.batchDeleteByRecordIds(ids);
            //删除钉钉任务
            try {
                String s = dingtalkBusiness.delWorkMSGWithStart(ids);
                log.info("清除钉钉任务响应，res: " +s);
            } catch (Exception e) {
                log.error("调用钉钉清除任务异常,e:" ,e);
            }
        }

        return ;
    }


    @Override
    public R assessChange(AssessChangeReq req) {
        if(req.getStartId()==null){
            throw new RRException("考核id不能为空");
        }
        if(req.getChangeType()==null){
            throw new RRException("变动类型无效");
        }
        if(StringUtil.isBlank(req.getStaffIds())){
            throw new RRException("变动人员不能为空");
        }
        FlowStart flowStart = flowStartMapper.selectFlowStartById(req.getStartId());
        if(flowStart == null){
            throw new RRException("暂无此考核组信息");
        }
        //获取本次考的所有考评组信息
        String[] split = flowStart.getGroupIds().split(",");
        List<String> strings = Arrays.asList(split);
        List<Long> ids = strings.stream().map(s -> Long.valueOf(s)).collect(toList());
        List<EvaluationGroup> evaluationGroups = evaluationGroupService.selectEvaluationGroupByIds(ids);

        //获取变更人员
        String[] changeStaffIds = req.getStaffIds().split(",");
        List<String> change = new ArrayList<>(Arrays.asList(changeStaffIds));

        if(req.getChangeType() == 0){
            //获取所有考核人员
            List<String> all = Lists.newArrayList();

            //根据组id成员分组
            Map<Long,List<String>> map = Maps.newHashMap();
            for(EvaluationGroup group:evaluationGroups){
                List<String> staff = evaluationGroupService.selectAllStaffIdsByGroupId(group.getId());
                all.addAll(staff);
                map.put(group.getId(),staff);
            }

            //获取不在考核组成员
            List<String> notInGroup = change.stream().filter(item -> !all.contains(item)).collect(toList());

            //获取不在考评组的人员
            if(CollectionUtils.isNotEmpty(notInGroup)){
                List<Long> collect = notInGroup.stream().map(s -> Long.valueOf(s)).distinct().collect(toList());
                List<StaffSimpleDto> staffSimpleDtos = staffService.selectStaffSimpleInfoByIds(collect);
                String notInGroupNames = StringUtil.EMPTY;
                for(StaffSimpleDto dto:staffSimpleDtos){
                    notInGroupNames = notInGroupNames + dto.getName() + " ";
                }

                return R.error(503,notInGroupNames + "未加入月度类型考评组，被考核人需要加入月度考评组后才能参与当前月度考核。").put("data",staffSimpleDtos);
            }

            //初始化添加用户的数据
            List<GroupStaffs> groupS = Lists.newArrayList();

            //排除已发起过的
            List<Long> longs = evaluationStartStaffMapper.selectStaffIdsByStart(req.getStartId());

            for(EvaluationGroup group:evaluationGroups){
                GroupStaffs groupStaffs = new GroupStaffs();
                groupStaffs.setEvaluationGroup(group);

                List<String> staffs = map.get(group.getId());
                staffs.retainAll(change);
                List<Long> collect = staffs.stream().distinct().map(s -> Long.valueOf(s)).collect(toList());
                collect.removeAll(longs);
                if(CollectionUtils.isNotEmpty(collect)){
                    groupStaffs.setStaffIds(collect);
                    groupS.add(groupStaffs);
                }
            }
            if(CollectionUtils.isEmpty(groupS)){
                log.info("暂无人员需要添加");
                return R.ok("暂无人员需要添加");
            }

            StartGroups startGroups = new StartGroups();
            startGroups.setStartId(req.getStartId());
            startGroups.setGroups(groupS);
            log.info("添加人员初始化请求：" + JSON.toJSONString(startGroups));
            R r = flowStartService.startStaffs(startGroups);
            log.info("添加人员初始化返回：" + JSON.toJSONString(r));
            return r;

        }
        if(req.getChangeType() == 1){
            //删除本次考核任务
            resultRecordMapper.batchDeleteByStartIdAndStaffId(req.getStartId(),change);
            evaluationStartStaffMapper.deleteEvaluationStartStaffChangeAssess(req.getStartId(),change);
            //删除钉钉任务
            try {
                List<Long> recordIds = resultRecordMapper.selectIdsByStartId(req.getStartId());
                String s = dingtalkBusiness.delWorkMSGWithStart(recordIds);
                log.info("清除钉钉任务响应，res: " +s);
            } catch (Exception e) {
                log.error("调用钉钉清除任务异常,e:" ,e);
            }
            return R.ok();
        }
        return R.ok();

    }


    @Override
    public void toScore(AssessToScoreReq req) {
        String[] split = req.getEvaluationIds().split(",");
        List<StaffSimpleInfo> toStaffids  = new ArrayList<>();
        for(String s:split){
            //更新评分
            EvaluationGroup group = evaluationGroupMapper.selectEvaluationGroupByCopyId(Long.valueOf(s),req.getStartId());
            if(group==null){
                log.info("未找到主组信息，copyId: " + s);
                continue;
            }
            Long evaluation = group.getId();
            int i = evaluationStartStaffService.updateBatchToScore(req.getStartId(), group.getId());
            log.info("更新evaluationStartStaff 数据 为已评分 " + i);
            List<ResultRecord> dtos = resultRecordMapper.selectToScoreList(req.getStartId(), evaluation);
            if(CollectionUtils.isNotEmpty(dtos)){
                log.info("本次评分更新操作 num: " + dtos.size());
                dtos.forEach(dto -> {
                    Long recordId = dto.getId();
                    //更新流程绩效
                    ApprovalDto approvalDto = new ApprovalDto();
                    approvalDto.setStatus(1);
                    approvalDto.setResultRecordId(recordId);
                    approvalDto.setMenuName("开始评分");
                    try {
                        R r = resultRecordService.newApproval(approvalDto);
                        log.info("绩效id aLong :" + recordId  + " ,res" + JSON.toJSONString(r));
                    } catch (Exception e) {
                        log.error("执行中状态跳过失败 recorId:" + recordId,e);
                    }
                    //钉钉通知评分构建
                    StaffSimpleInfo staffSimpleInfo = new StaffSimpleInfo();
                    staffSimpleInfo.setId(dto.getStaffId());
                    staffSimpleInfo.setResultRecord(dto);
                    FlowStart start = flowStartMapper.selectFlowStartById(req.getStartId());
                    staffSimpleInfo.setFlowStart(start);
                    toStaffids.add(staffSimpleInfo);

                });
            }
            else {
                log.info("该考评组无数据  evaluationId:" + evaluation);
            }

            //更新flowRecord记录
            List<Object> objects = resultRecordService.listObjs(new QueryWrapper<ResultRecord>()
                    .eq("is_delete", 0)
                    .eq("start_id", req.getStartId())
                    .eq("evaluation_id", evaluation).select("id"));

            List<Long> collect = objects.stream().map(o -> Long.valueOf(String.valueOf(o))).collect(toList());

            int updateExecution = flowRecordMapper.batchUpdateSkip(collect);
            log.info("更新flowRecord记录,i:" + updateExecution);

        }

        if(CollectionUtils.isNotEmpty(toStaffids)){
            //通知评分
            try {
                String s = dingtalkBusiness.sendWorkMSGWithAsyn(toStaffids, WorkMsgTypeEnum.START_SCORE.getType());
                log.info("钉钉评分响应返回，res：" + s);
            } catch (Exception e) {
                log.error("通知评分异常：ids: " + JSON.toJSONString(toStaffids) + " ,e: " ,e);
            }
        }

    }


}