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.google.common.collect.Sets;
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.entity.DepartmentsEntity;
import com.lz.modules.app.entity.DepartmentsStaffRelateEntity;
import com.lz.modules.app.entity.StaffEntity;
import com.lz.modules.app.service.*;
import com.lz.modules.flow.dao.EvaluationGroupMapper;
import com.lz.modules.flow.dao.FlowChartMapper;
import com.lz.modules.flow.dao.FlowStartMapper;
import com.lz.modules.flow.entity.FlowChart;
import com.lz.modules.flow.entity.FlowStart;
import com.lz.modules.flow.service.EvaluationGroupService;
import com.lz.modules.flow.service.FlowChartService;
import com.lz.modules.flow.service.FlowStartService;
import com.lz.modules.performance.dto.LevelDetailExportDto;
import com.lz.modules.performance.dto.StaffTypeDto;
import com.lz.modules.performance.enums.ResultFlowProcessEnum;
import com.lz.modules.performance.req.AssessDetailReq;
import com.lz.modules.performance.req.ChartResultReq;
import com.lz.modules.performance.req.ChartStartsReq;
import com.lz.modules.performance.res.ChartStartsRes;
import com.lz.modules.performance.res.ChartStatistical;
import com.lz.modules.performance.res.ChartStatisticalRes;
import com.lz.modules.performance.res.LevelDetailExportRes;
import com.lz.modules.performance.service.AssessService;
import com.lz.modules.performance.service.ChartResultService;
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.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Author: djc
 * @Desc:
 * @Date: 2020/10/14 16:53
 */
@Service("chartResultService")
@Slf4j
public class ChartResultServiceImpl implements ChartResultService {

    @Autowired
    private ResultRecordService resultRecordService;
    @Autowired
    private DepartmentsStaffRelateService departmentsStaffRelateService;
    @Autowired
    private EvaluationGroupService evaluationGroupService;
    @Autowired
    private ResultRecordMapper resultRecordMapper;
    @Autowired
    private StaffService staffService;
    @Autowired
    private FlowStartService flowStartService;
    @Autowired
    private FlowStartMapper flowStartMapper;
    @Autowired
    private DepartmentsService departmentsService;
    @Autowired
    private FlowChartService flowChartService;
    @Autowired
    private AssessService assessService;
    @Autowired
    private EvaluationGroupMapper evaluationGroupMapper;
    @Autowired
    private StaffOccupationService staffOccupationService;

    private static final Long processId = 1L;


    @Override
    public List<ChartStatisticalRes> chartReport(Long startId,Long staffId) {
        String defaultTime = StringUtil.EMPTY;
        Integer defaultCycleType = null;
        FlowStart flowStart = null;
        if(startId==null){
            //取最近一条记录
            flowStart = flowStartMapper.selectRecentlyLimt();
            if(flowStart!=null){
                log.info("首次进入，默认返回最新记录 flowStartId:" + flowStart.getId());
                startId = flowStart.getId();
                defaultTime = flowStart.getName();
                defaultCycleType = flowStart.getCycleType();
            }else {
                return new ArrayList<>();
            }
        }
        //自己管理的部门
        List<String> mandepartmentIds = assessService.roleDepartments(staffId);
        if(mandepartmentIds!=null && mandepartmentIds.size()==0){
            return Lists.newArrayList();
        }
        List<ChartStatisticalRes> data = Lists.newArrayList();
        ChartStatisticalRes res;

        List<ChartStatistical> process = resultRecordService.countNumByFlowProcess(startId,null,mandepartmentIds);

        res = new ChartStatisticalRes();
        res.setType(0);
        res.setStatisticals(buildProcess(process,startId,mandepartmentIds,null));
        res.setDefaultTime(defaultTime);
        if(StringUtil.isNotBlank(defaultTime)){
            res.setDefaultId(startId);
            res.setDefaultCycleType(defaultCycleType);
        }
        data.add(res);

        List<ChartStatistical> scoreLevel = resultRecordService.countNumByScoreLevel(startId,null,mandepartmentIds);
        res = new ChartStatisticalRes();
        res.setType(1);
        res.setStatisticals(scoreLevel);
        res.setDefaultTime(defaultTime);
        if(StringUtil.isNotBlank(defaultTime)){
            res.setDefaultId(startId);
            res.setDefaultCycleType(defaultCycleType);
        }
        data.add(res);

        //如果不是默认，获得发起考核信息

        List<Object> objects = resultRecordService.listObjs(new QueryWrapper<ResultRecord>()
                .eq("is_delete", 0)
                .eq("start_id", startId)
                .in(mandepartmentIds != null, "department_id", mandepartmentIds).select("staff_id"));
        if(CollectionUtils.isEmpty(objects)){
            return data;
        }
        List<String> collect = objects.stream().map(o -> String.valueOf(o)).collect(Collectors.toList());
        List<ChartStatistical> depstaff = this.countDepartmentAndStaffNum(collect);
        res = new ChartStatisticalRes();
        res.setType(2);
        res.setStatisticals(buildDepStaffs(depstaff));
        res.setDefaultTime(defaultTime);
        if(StringUtil.isNotBlank(defaultTime)){
            res.setDefaultId(startId);
            res.setDefaultCycleType(defaultCycleType);
        }
        data.add(res);
        return data;

    }

    @Override
    public List<ChartStatistical> countDepartmentAndStaffNum(List<String> staffIds) {
        if(CollectionUtils.isEmpty(staffIds)){
            return Collections.EMPTY_LIST;
        }

        List<ChartStatistical> data = Lists.newArrayList();
        List<DepartmentsStaffRelateEntity> list = departmentsStaffRelateService.list(new QueryWrapper<DepartmentsStaffRelateEntity>()
                .eq("is_delete", 0)
                .in("staff_id", staffIds));

        Map<String,Integer> map = Maps.newHashMap();
        for(DepartmentsStaffRelateEntity entity:list){
            String departmentId = entity.getDepartmentId();
            Integer count = map.get(departmentId);
            if(null != count){
                map.put(departmentId,count + 1);
            }else {
                map.put(departmentId,1);
            }
        }
        for(String s:map.keySet()){
            ChartStatistical statistical = new ChartStatistical();
            statistical.setDesc(s);
            statistical.setNum(map.get(s));
            data.add(statistical);
        }
        return data;
    }

    @Override
    public PageUtils selectChartDetailList(ChartResultReq req) {
        List<String> mandepartmentIds = getMandepartmentIds(req.getDepartmentIds(), req.getLoginUserId());
        List<String> finalMandepartmentIds = mandepartmentIds;
        PageUtils pageUtils = PageUtils.startPage(req.getCurrPage(), req.getPageSize()).doSelect(
                page -> resultRecordMapper.selectChartDetailList(page, finalMandepartmentIds,req.getStartId(),req.getScoreLevel())
        );
        return pageUtils;
    }

    @Override
    public PageUtils chartStarts(ChartStartsReq req) {
        List<ChartStartsRes> data = Lists.newArrayList();
        PageUtils pageUtils = PageUtils.startPage(req.getCurrPage(), req.getPageSize()).doSelect(
                page -> flowStartMapper.selectListByPage(page,req.getCycleType())
        );
        List<FlowStart> starts = pageUtils.getList();
        starts.forEach(flowStart -> {
            ChartStartsRes start = new ChartStartsRes();
            start.setStartId(flowStart.getId());
            start.setTime(flowStart.getName());
            data.add(start);
        });


        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 List<ChartStatistical> countAssessNumByFlowProcess(AssessDetailReq req) {
        if(req.getStartId()==null){
            throw new RRException("考核id不能为空");
        }
        req.setCopyEvaluationIds(evaluationGroupService.getEvaluationCopyIdsByEvaluationIds(req.getEvaluationIds(),req.getStartId()));
        //获取自己管理的部门
        List<String> mandepartmentIds = assessService.roleDepartments(req.getLoginUserId());
        if(mandepartmentIds!=null && mandepartmentIds.size()==0){
            return Lists.newArrayList();
        }
        req.setDepartmentIds(mandepartmentIds);
        List<ChartStatistical> process = resultRecordMapper.countAssessNumByFlowProcess(req);
        List<ChartStatistical> data = buildProcess(process, req.getStartId(),mandepartmentIds,req);
        return data;
    }


    @Override
    public List<LevelDetailExportRes> selectLevelDetailList(ChartResultReq req) {
        List<String> mandepartmentIds = getMandepartmentIds(req.getDepartmentIds(), req.getLoginUserId());
        List<LevelDetailExportDto> levelDetailExportDtos = resultRecordMapper.selectLevelDetailList(mandepartmentIds, req.getStartId(), req.getScoreLevel());

        if(CollectionUtils.isEmpty(levelDetailExportDtos)){
            return Collections.EMPTY_LIST;
        }
        List<Long> staffIds = levelDetailExportDtos.stream().map(LevelDetailExportDto::getStaffId).collect(Collectors.toList());
        List<String> depIds = levelDetailExportDtos.stream().map(levelDetailExportDto -> levelDetailExportDto.getDepartmentId().toString()).collect(Collectors.toList());

        List<StaffTypeDto> staffTypeDtos = staffOccupationService.selectStaffTypesByStaffIds(staffIds);
        //状态
        Map<Long,Integer> types = Maps.newHashMap();
        //职位
        Map<Long,String> positions = Maps.newHashMap();

        for(StaffTypeDto dto: staffTypeDtos){
            types.put(dto.getStaffId(),dto.getStaffType());
            positions.put(dto.getStaffId(),dto.getPosition());
        }
        Map<Long, List<String>> map = departmentsService.selectDepartmentTreeByDepIds(depIds);

        for(LevelDetailExportDto res: levelDetailExportDtos){
            Integer integer = types.get(res.getStaffId());
            String position = positions.get(res.getStaffId());
            if(integer !=null){
                res.setStaffType(integer);
            }
            if(StringUtil.isNotBlank(position)){
                res.setPosition(position);
            }
            List<String> names = map.get(res.getDepartmentId());
            if(CollectionUtils.isNotEmpty(names)){
                Collections.reverse(names);
                int size = names.size();
                if(size>0 && StringUtils.isNotBlank(names.get(0))){
                    res.setDepartmentOne(names.get(0));
                }
                if(size>1 && StringUtils.isNotBlank(names.get(1))){
                    res.setDepartmentTwo(names.get(1));
                }
                if(size>2 && StringUtils.isNotBlank(names.get(2))){
                    res.setDepartmentThree(names.get(2));
                }
            }
        }

        //拷贝为excel格式
        List<LevelDetailExportRes> levelDetailExportRes = levelDetailExportDtos.stream().map(levelDetailExportDto -> {
            LevelDetailExportRes res = new LevelDetailExportRes();
            BeanUtils.copyProperties(levelDetailExportDto,res);
            if(1 == levelDetailExportDto.getStaffType()){
                res.setStaffType("已转正");
            }
            if(2 == levelDetailExportDto.getStaffType()){
                res.setStaffType("试用期");
            }
            return res;
        }).collect(Collectors.toList());

        return levelDetailExportRes;

    }

    //构建流程默认人数
    private List<ChartStatistical> buildProcess(List<ChartStatistical> process,Long startId,List<String> mandepartmentIds,AssessDetailReq req){
        List<ChartStatistical> data = Lists.newArrayList();
        Map map = Maps.newHashMap();
        int count;
        if(req == null){
            count = resultRecordService.count(new QueryWrapper<ResultRecord>()
                    .eq("is_delete", 0)
                    .eq("start_id", startId)
                    .in(CollectionUtils.isNotEmpty(mandepartmentIds),"department_id",mandepartmentIds));
        }
        else {
            count = resultRecordMapper.countAssessNumJoin(req);
        }
        ChartStatistical all = new ChartStatistical();
        all.setDesc("参与人数");
        all.setNum(count);
        data.add(all);

        for(ChartStatistical statistical:process){
            map.put(statistical.getDesc(),statistical.getNum());
        }
        List<FlowChart> charts = flowChartService.selectFlowChartByFlowManagerId(processId);

        for(FlowChart chart:charts){
            ChartStatistical statistical = new ChartStatistical();
            statistical.setDesc(chart.getName());
            statistical.setNum(0);
            statistical.setFlowProcess(Long.valueOf(chart.getFlowProcess()));
            statistical.setTip(chart.getDesc());
            Object o = map.get(chart.getFlowProcess() + StringUtil.EMPTY);
            if(o!=null){
                statistical.setNum(Integer.valueOf(o.toString()));
            }
            data.add(statistical);
        }

        return data;
    }




    private List<ChartStatistical> buildDepStaffs(List<ChartStatistical> depStaffs){
        depStaffs.stream().forEach(chartStatistical -> {
            String desc = chartStatistical.getDesc();
            DepartmentsEntity departmentsEntity = departmentsService.selectByDepartmentId(desc);
            if(departmentsEntity!=null && StringUtil.isNotBlank(departmentsEntity.getDepartmentName())){
                chartStatistical.setDesc(departmentsEntity.getDepartmentName());
            }
        });
        return depStaffs;
    }

    private List<String> getMandepartmentIds(String departmentIds,Long loginUserId){
        Set<String> allDepart = Sets.newHashSet();
        if(StringUtil.isNotBlank(departmentIds)){
            String[] split = departmentIds.split(",");
            for(String s:split){
                List<String> deparmentIds = staffService.selectAllDeparmentIdsByDepartmentParentId(s);
                allDepart.addAll(deparmentIds);
            }
        }
        List<String> allDeparmentIds = new ArrayList<>(allDepart);
        //自己管理的和所有的部门交集
        log.info("selectChartDetailList 查询部门：" + JSON.toJSONString(allDeparmentIds));
        List<String> mandepartmentIds = assessService.roleDepartments(loginUserId);
        if(mandepartmentIds!=null ){
            if(mandepartmentIds.size()==0){
                return Collections.EMPTY_LIST;
            }
            log.info("selectChartDetailList 管理部门：" + JSON.toJSONString(mandepartmentIds));
            mandepartmentIds.retainAll(allDeparmentIds);
            if(mandepartmentIds.size()==0){
                return Collections.EMPTY_LIST;
            }
        }
        else {
            //如果掌管所有部门，查询请求部门
            mandepartmentIds = allDeparmentIds;
        }
        log.info("selectChartDetailList 交集部门：" + JSON.toJSONString(mandepartmentIds));
        return mandepartmentIds;

    }
}
