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

import cn.hutool.core.util.PageUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.lz.common.utils.*;
import com.lz.modules.app.dao.DepartmentsDao;
import com.lz.modules.app.dao.DepartmentsStaffRelateDao;
import com.lz.modules.app.dao.StaffDao;
import com.lz.modules.app.dto.*;
import com.lz.modules.app.entity.DepartmentsEntity;
import com.lz.modules.app.entity.DepartmentsStaffRelateEntity;
import com.lz.modules.app.enums.ResultRecordStatusEnum;
import com.lz.modules.app.enums.ResultRecordTypeEnum;
import com.lz.modules.app.req.ReportListReq;
import com.lz.modules.app.req.ResultDistributionReq;
import com.lz.modules.app.resp.ReportChartResp;
import com.lz.modules.app.service.StaffService;
import com.lz.modules.flow.dao.StaffRoleMapper;
import com.lz.modules.flow.entity.StaffRole;
import com.lz.modules.sys.dao.app.ResultDetailMapper;
import com.lz.modules.sys.dao.app.ResultRecordMapper;
import com.lz.modules.sys.entity.app.ResultRecord;
import com.lz.modules.sys.service.app.ChartService;
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.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Author: djc
 * @Desc:
 * @Date: 2020/9/14 16:54
 */
@Slf4j
@Service
public class ChartServiceImpl implements ChartService {
    @Autowired
    private ResultRecordService resultRecordService;
    @Autowired
    private StaffService staffService;
    @Autowired
    private ResultRecordMapper resultRecordMapper;
    @Autowired
    private DepartmentsStaffRelateDao departmentsStaffRelateDao;
    @Autowired
    private StaffDao staffDao;
    @Autowired
    private DepartmentsDao departmentsDao;
    @Autowired
    private StaffRoleMapper staffRoleMapper;
    @Autowired
    private ResultDetailMapper resultDetailMapper;

    static final String[] levels = new String[]{"3.25","3.5-","3.5","3.5+","3.75-","3.75","3.75+","4"};


    //如果多次提交会统计有问题
    @Override
    public List<GraphicsStatisticalDto> resultProgressDistribution(int type, String monthTime,String departmentId) {
        List<GraphicsStatisticalDto> dtos = Lists.newArrayList();
        //获取所有人员总数
        List<String> allDeparmentIds = staffService.selectAllDeparmentIdsByDepartmentParentId(departmentId);

        //审核中
        int apprvel = resultRecordService.count(new QueryWrapper<ResultRecord>()
                .eq("is_delete", type==1?2:0)
                .eq("type", type)
                .like("month_time",monthTime)
                .in("status", ResultRecordStatusEnum.AUDIT.getStatus(),ResultRecordStatusEnum.WAIT_COMMIT.getStatus(),ResultRecordStatusEnum.REJECT.getStatus(),ResultRecordStatusEnum.APPEAL.getStatus())
                .in("department_id",allDeparmentIds)
                .select("DISTINCT staff_id"));
        int noCommit = resultRecordService.count(new QueryWrapper<ResultRecord>()
                .eq("is_delete", type==1?2:0)
                .eq("type", type)
                .like("month_time",monthTime)
                .eq("status", ResultRecordStatusEnum.CREATE.getStatus())
                .in("department_id",allDeparmentIds)
                .select("DISTINCT staff_id"));
        //已完成
        int finished = resultRecordService.count(new QueryWrapper<ResultRecord>()
                .eq("is_delete", type==1?2:0)
                .eq("type", type)
                .like("month_time",monthTime)
                .in("status", ResultRecordStatusEnum.REFUSE.getStatus(),ResultRecordStatusEnum.AGREE.getStatus(),ResultRecordStatusEnum.SUSPEND.getStatus())
                .in("department_id",allDeparmentIds)
                .select("DISTINCT staff_id"));

        GraphicsStatisticalDto dto = new GraphicsStatisticalDto();
        if(noCommit>0){
            dto.setCategory("未提交");
            dto.setNumber(noCommit);
            dtos.add(dto);
        }
        if(finished>0){
            dto = new GraphicsStatisticalDto();
            dto.setCategory("已完成");
            dto.setNumber(finished);
            dtos.add(dto);
        }
       if(apprvel>0){
           dto = new GraphicsStatisticalDto();
           dto.setCategory("审核中");
           dto.setNumber(apprvel);
           dtos.add(dto);
       }
        return dtos;
    }


    @Override
    public ReportChartResp reportChart(String selectMonthTime, String departmentId) {
        ReportChartResp data = new ReportChartResp();
        //月初目标
        List<GraphicsStatisticalDto> start = this.resultProgressDistribution(ResultRecordTypeEnum.TARGET.getType(),selectMonthTime,departmentId);
        //月末结果
        List<GraphicsStatisticalDto> end = this.resultProgressDistribution(ResultRecordTypeEnum.RESULT.getType(),selectMonthTime,departmentId);
        //人员等级分布
        List<String> allDeparmentIds = staffService.selectAllDeparmentIdsByDepartmentParentId(departmentId);
        List<String> staffIds = staffService.staffsByAllDeparmentIds(allDeparmentIds);
        int total = staffIds.size();
        List<GraphicsStatisticalDto> staffLevels = resultRecordService.staffDistribution(selectMonthTime,staffIds);
        List<String> names  = Lists.newArrayList();
        List<Double> datas  = Lists.newArrayList();
        int konwn = 0;
        for (GraphicsStatisticalDto staffLevel : staffLevels) {
            names.add(staffLevel.getCategory());
            datas.add(BigDecimalUtil.div(Double.valueOf(staffLevel.getNumber()),Double.valueOf(total),2));
            konwn = konwn + staffLevel.getNumber();
            log.info("等级：" + staffLevel.getCategory() + " 人数：" + staffLevel.getNumber());
        }
        names.add("未知");
        datas.add(BigDecimalUtil.div(Double.valueOf((total - konwn)),Double.valueOf(total),2));
        //部门等级占比
        GraphicsDto dto = new GraphicsDto();
        dto.setRows(start);
        data.setTargetDistribution(dto);
        dto = new GraphicsDto();
        dto.setRows(end);
        data.setResultDistribution(dto);
        CharBarDto barDto= new CharBarDto();
        barDto.setNames(names);
        barDto.setDatas(datas);
        barDto.setTotal(total);
        data.setStaffDistribution(barDto);
        return data;
    }

    @Override
    public PageUtils resultReportList(ReportListReq req) {
        List<String> allDeparmentIds = staffService.selectAllDeparmentIdsByDepartmentParentId(req.getDepartmentId());
        //获取部门下所有人员
        List<String> staffIds = staffService.staffsByAllDeparmentIds(allDeparmentIds);
        //获取真实状态
        List<Integer> groupStatus = ResultRecordStatusEnum.getGroupStatus(req.getStatus());
        req.setRealStatus(groupStatus);
        //获取处理过业绩目标的人员
        PageUtils pageUtils = PageUtils.startPage(req.getCurrPage(),req.getPageSize()).doSelect(
                page -> this.targetReportList(req, staffIds, page)
        );
        return pageUtils;


      /*
      List<String> copyStaffIds = Lists.newArrayList();
        ReportListReq copyReq = new ReportListReq();
        copyStaffIds.addAll(staffIds);


      if(req.getStatus()!=null){

            if(req.getStatus() != ResultRecordStatusEnum.CREATE.getStatus()){


            }else { // 状态为0的数据存在两张表，单独处理

                //获取已提交人员
                List<String> commitStaffIds = new ArrayList<>();
                List<Object> collect=resultRecordService.listObjs(new QueryWrapper<ResultRecord>()
                        .eq("is_delete",  req.getType()==1?2:0)
                        .eq("type", req.getType())
                        .like("month_time",req.getSelectMonthTime())
                        .ne("status", ResultRecordStatusEnum.CREATE.getStatus())
                        .in("department_id",allDeparmentIds)
                        .in("staff_id",staffIds)
                        .select(" DISTINCT staff_id"));
                if(CollectionUtils.isNotEmpty(collect)){
                    commitStaffIds = collect.stream().map(o -> o.toString()).collect(Collectors.toList());
                }
                //去除已经提交的
                staffIds.removeAll(commitStaffIds);
                return buildPageByStaffIds(req,staffIds);

            }

        }else{  // 查询所有，需要拼装数据 ,先查询已提交得剩余得 用未提交缺多少补多少

            //查询全部    思路     result record  全部查完，记录的用户id 取出，  部门下所有的用户剔除掉这些 就是剩下未提交的用户

            PageUtils pageUtils = PageUtils.startPage(req.getCurrPage(),req.getPageSize()).doSelect(
                    page -> this.targetReportList(req, staffIds, page)
            );
            List<ReportProgressListDto> list = pageUtils.getList();


            List<ReportProgressListDto> copyList = new ArrayList<>();
            copyList.addAll(list);
            int totalPage = pageUtils.getTotalPage();

            if(StringUtil.isNotBlank(req.getLevel()) || StringUtil.isNotBlank(req.getStaffName())){
                *//*************************************数据拼接逻辑****************************************//*
                if(list.size()<req.getPageSize()){
                    List<String> commitStaffIds = new ArrayList<>();
                    //已提交
                    List<Object> objects = resultRecordService.listObjs(new QueryWrapper<ResultRecord>()
                            .eq("is_delete", req.getType()==1?2:0)
                            .eq("type", req.getType())
                            .like("month_time", req.getSelectMonthTime())
                            .in("department_id", allDeparmentIds)
                            .select("DISTINCT staff_id"));
                    if(CollectionUtils.isNotEmpty(objects)){
                        commitStaffIds = objects.stream().map(o -> o.toString()).collect(Collectors.toList());
                    }
                    //去除已提交的
                    staffIds.removeAll(commitStaffIds);
                    //防止真实状态为未提交的 又重新拼接
                    if(CollectionUtils.isNotEmpty(list)){
                        List<String> collect = list.stream().map(reportProgressListDto -> reportProgressListDto.getStaffId()).collect(Collectors.toList());
                        staffIds.removeAll(collect);
                    }

                    if(CollectionUtils.isEmpty(staffIds)){
                        return pageUtils;
                    }
                    int addSize = req.getPageSize()-list.size();
                    int addStart = req.getCurrPage() -totalPage;
                    //如果相差大于0 则需找到最后一页得个数 补齐得时候减去这些个数
                    if(addStart>0){

                        copyReq.setCurrPage(pageUtils.getTotalPage());
                        copyReq.setPageSize(req.getPageSize());
                        PageUtils ps = PageUtils.startPage(copyReq.getCurrPage(),copyReq.getPageSize()).doSelect(
                                page -> this.targetReportList(copyReq, copyStaffIds, page)
                        );
                        int sub = ps.getList().size();
                        addStart = (addStart-1) * req.getPageSize() + (copyReq.getPageSize()-sub);
                    }
                    int addEnd = addSize + addStart;
                    addEnd = addEnd>staffIds.size()?staffIds.size():addEnd;
                    addStart = addStart>staffIds.size()?0:addStart;
                    List<String> addList = staffIds.subList(addStart,addEnd);
                    copyReq.setCurrPage(0);
                    copyReq.setPageSize(addSize);
                    PageUtils addResult = buildPageByStaffIds(copyReq, addList);
                    staffIds.addAll(commitStaffIds);
                    PageUtils data = new PageUtils();
                    copyList.addAll(addResult.getList());
                    data.setList(copyList);
                    data.setPageSize(req.getPageSize());
                    data.setCurrPage(req.getCurrPage());
                    data.setTotalCount(copyStaffIds.size());
                    data.setTotalPage(PageUtil.totalPage(copyStaffIds.size(),req.getPageSize()));
                    return data;
                }
            }


            PageUtils data = new PageUtils();
            data.setList(list);
            data.setPageSize(req.getPageSize());
            data.setCurrPage(req.getCurrPage());
            data.setTotalCount(copyStaffIds.size());
            data.setTotalPage(PageUtil.totalPage(copyStaffIds.size(),req.getPageSize()));
            return data;


        }*/
    }


    @Override
    public PageUtils reportDistribution(ResultDistributionReq req) {
        /*List<String> allDeparmentIds = staffService.selectAllDeparmentIdsByDepartmentParentId(req.getDepartmentId());
        // 去除存在子部门得id
        allDeparmentIds.removeIf(s -> {
            List<DepartmentsEntity> departmentsEntities = departmentsDao.selectEntityByParentDepartmentId(s);
            if(CollectionUtils.isNotEmpty(departmentsEntities)){
                return true;
            }
            return false;
        });

        // 由于deparmentIds 递归所得无法分页  则list分页
        List<String> list = ListUtils.startPage(allDeparmentIds, req.getCurrPage(), req.getPageSize());
        return buildPages(list,req,allDeparmentIds.size());*/
        //获取一级目录
        List<DepartmentsDto> departmentsParentsList = departmentsDao.getDepartmentsByparentId("1");
        if(CollectionUtils.isEmpty(departmentsParentsList)){
            return new PageUtils();
        }
        List<DepartmentsDto> oneDepartmentsParentsList = Lists.newArrayList();
        departmentsParentsList.forEach(departmentsDto -> {
            List<DepartmentsDto> departmentsParentsList1 = departmentsDao.getDepartmentsByparentId(departmentsDto.getDepartmentId());
            oneDepartmentsParentsList.addAll(departmentsParentsList1);
        });

        List<DepartmentsDto> list = ListUtils.startPage(oneDepartmentsParentsList, req.getCurrPage(), req.getPageSize());
        if(CollectionUtils.isEmpty(list)){
            return new PageUtils();
        }
        List<String> collect = list.stream().map(DepartmentsDto::getDepartmentId).collect(Collectors.toList());
        return buildPages(collect,req,oneDepartmentsParentsList.size());
    }


    @Override
    public String businessLineByStaffId(String staffId) {
        DepartmentsStaffRelateEntity departmentsStaffRelateEntity = departmentsStaffRelateDao.selectByStaffId(Long.valueOf(staffId));
        String departmentId = departmentsStaffRelateEntity.getDepartmentId();
        return getBussinessLine(departmentId);
    }


    @Override
    public boolean hrOrBoss(Long staffId) {
        log.info("hrOrBoss判断 : " + staffId);
        //超级管理员
        if(Constant.SUPER_ADMIN==staffId){
            return true;
        }
        StaffRole staffRole = staffRoleMapper.selectByStaffId(staffId);
        if(staffRole!=null){
            return true;
        }
        return false;
    }

    @Override
    public boolean leader(Long staffId) {
        log.info("leader判断 : " + staffId);
        //超级管理员
        if(Constant.SUPER_ADMIN==staffId){
            return true;
        }
        DepartmentsStaffRelateEntity departmentsStaffRelateEntity = departmentsStaffRelateDao.selectByStaffId(staffId);
        if(departmentsStaffRelateEntity!=null && 1 == departmentsStaffRelateEntity.getIsLeader()){
            return true;
        }
        return false;
    }


    @Override
    public List<ReportProgressListDto> targetReportList(ReportListReq req, List<String> staffIds, IPage page) {
        List<ReportProgressListDto> reportProgressListDtos = resultRecordMapper.targetReportList(req, staffIds,page);
        //由于使用了 maxId  需要拿到id 获取最新数据
        if(CollectionUtils.isNotEmpty(reportProgressListDtos)){
            reportProgressListDtos.forEach(reportProgressListDto -> {
                Long id = reportProgressListDto.getId();
                String staffId = reportProgressListDto.getStaffId();
                ResultRecord resultRecord = resultRecordMapper.selectById(id);
                reportProgressListDto.setAllScore(resultRecord.getAllScore() + "");
                reportProgressListDto.setStatus(resultRecord.getStatus());
                reportProgressListDto.setScoreLevel(resultRecord.getScoreLevel());

                //获取业务 ，价值观得分
                BigDecimal businessScore = resultDetailMapper.calculateScore(id, Long.valueOf(staffId), 1);
                BigDecimal valueScore = resultDetailMapper.calculateScore(id, Long.valueOf(staffId), 2);
                if(businessScore!=null && !businessScore.equals(new BigDecimal("0.0"))){
                    reportProgressListDto.setBusinessScore(businessScore + "");
                }
                if(valueScore!=null && !valueScore.equals(new BigDecimal("0.0"))){
                    reportProgressListDto.setValueScore(valueScore + "");
                }
            });
            return reportProgressListDtos;
        }
        return Lists.newArrayList();
    }

    private String getBussinessLine(String departmentId){
        DepartmentsEntity departmentsEntity = departmentsDao.selectByDepartmentId(departmentId);
        if("1".equals(departmentsEntity.getDepartmentParentId())){
            return departmentsEntity.getDepartmentName();
        }
        return getBussinessLine(departmentsEntity.getDepartmentParentId());

    }


    private PageUtils buildPages( List<String> departments,ResultDistributionReq req, int totalSize){
        List<ReportDistributionDto> data = Lists.newArrayList();
        if(CollectionUtils.isEmpty(departments)){
            return new PageUtils();
        }
        departments.forEach(s -> {
            DepartmentsEntity departmentsEntity = departmentsDao.selectByDepartmentId(s);
            List<String> allDeparmentIds = staffService.selectAllDeparmentIdsByDepartmentParentId(s);
            List<String> staffIds = staffService.staffsByAllDeparmentIds(allDeparmentIds);
            List<GraphicsStatisticalDto> staffLevels = resultRecordService.staffDistribution(req.getSelectMonthTime(),staffIds);
            Map<String,Integer> map = Maps.newHashMap();
            for (GraphicsStatisticalDto staffLevel : staffLevels) {
                map.put(staffLevel.getCategory(),staffLevel.getNumber());
            }
            ReportDistributionDto dto = new ReportDistributionDto();
            dto.setDepartmentId(s);
            dto.setDepartmentName(departmentsEntity.getDepartmentName());
            dto.setBusinessLine(getBussinessLine(s));
            dto.setLevel1(map.get(levels[0])==null?0:map.get(levels[0]));
            dto.setLevel2(map.get(levels[1])==null?0:map.get(levels[1]));
            dto.setLevel3(map.get(levels[2])==null?0:map.get(levels[2]));
            dto.setLevel4(map.get(levels[3])==null?0:map.get(levels[3]));
            dto.setLevel5(map.get(levels[4])==null?0:map.get(levels[4]));
            dto.setLevel6(map.get(levels[5])==null?0:map.get(levels[5]));
            dto.setLevel7(map.get(levels[6])==null?0:map.get(levels[6]));
            dto.setLevel8(map.get(levels[7])==null?0:map.get(levels[7]));
            data.add(dto);

        });

        PageUtils result = new PageUtils();
        result.setList(data);
        result.setTotalCount(totalSize);
        result.setCurrPage(req.getCurrPage());
        result.setPageSize(req.getPageSize());
        result.setTotalPage(PageUtil.totalPage(totalSize,req.getPageSize()));
        return result;
    }


    //根据用户组拼接未提交分页数据
    private PageUtils buildPageByStaffIds(ReportListReq req,List<String> staffIds){
        PageUtils pageUtils = PageUtils.startPage(req.getCurrPage(),req.getPageSize()).doSelect(
                page ->staffDao.getPositionByStaffIds(req,staffIds,page)
        );
        //本次分页数据
        List<ReportProgressListDto> dataList = pageUtils.getList();
        if(dataList.size()<1){
            return pageUtils;
        }
        //拿到用户数据查询部门信息封装
        List<String> selectStaffIds = dataList.stream().map(reportProgressListDto -> reportProgressListDto.getStaffId()).collect(Collectors.toList());
        List<ReportProgressListDto> departmentNameByStaffIds = departmentsStaffRelateDao.getDepartmentNameByStaffIds(selectStaffIds);
        Map<String,String> map = Maps.newHashMap();
        departmentNameByStaffIds.forEach(reportProgressListDto -> {
            map.put(reportProgressListDto.getStaffId(), reportProgressListDto.getDepartmentName());
        });
        dataList.forEach(reportProgressListDto -> {
            reportProgressListDto.setDepartmentName(map.get(reportProgressListDto.getStaffId()));
            reportProgressListDto.setAllScore("0.0");
            reportProgressListDto.setScoreLevel("0");
        });
        return pageUtils;
    }
}
