package com.ankaibei.workFlow.webadmin.ankaibei.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ankaibei.workFlow.common.core.object.ResponseResult;
import com.ankaibei.workFlow.common.core.object.TokenData;
import com.ankaibei.workFlow.common.flow.constant.FlowConstant;
import com.ankaibei.workFlow.common.flow.constant.FlowTaskStatus;
import com.ankaibei.workFlow.common.flow.dto.FlowTaskCommentDto;
import com.ankaibei.workFlow.common.flow.model.FlowEntry;
import com.ankaibei.workFlow.common.flow.model.FlowEntryPublish;
import com.ankaibei.workFlow.common.flow.vo.TaskInfoVo;
import com.ankaibei.workFlow.webadmin.ankaibei.entity.*;
import com.ankaibei.workFlow.webadmin.ankaibei.enums.CodeEnum;
import com.ankaibei.workFlow.webadmin.ankaibei.enums.ProjectPeriodEnum;
import com.ankaibei.workFlow.webadmin.ankaibei.enums.ProjectStatusEnum;
import com.ankaibei.workFlow.webadmin.ankaibei.mapper.*;
import com.ankaibei.workFlow.webadmin.ankaibei.service.ProjectInfoService;
import com.ankaibei.workFlow.webadmin.ankaibei.utils.FlowTaskStart;
import com.ankaibei.workFlow.webadmin.ankaibei.vo.EchartsEntityVo;
import com.ankaibei.workFlow.webadmin.ankaibei.vo.ProjectInfoVo;
import com.ankaibei.workFlow.webadmin.ankaibei.vo.ResMsg;
import com.ankaibei.workFlow.webadmin.upms.dao.SysDeptMapper;
import com.ankaibei.workFlow.webadmin.upms.model.SysDept;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author lwq
 * @version 1.0
 * @description:
 * @date 2022/9/14 11:13
 */
@Service
public class ProjectInfoServiceImpl implements ProjectInfoService {

    @Resource
    private ProjectInfoMapper projectInfoMapper;
    @Resource
    private UserInfoMapper userInfoMapper;
    @Resource
    private SysDeptMapper sysDeptMapper;
    @Resource
    private AccesoryInfoMapper accesoryInfoMapper;
    @Resource
    private ProjectAuditInfoMapper projectAuditInfoMapper;
    @Autowired
    private FlowTaskStart flowTaskStart;


    @Override
    public ResMsg findProjectInfo(Integer pageIndex, Integer pageSize, ProjectInfoEntity projectInfoEntity) {
        Pageable page = PageRequest.of(pageIndex - 1, pageSize);
        Page<Map<String, String>> projectInfo = projectInfoMapper.findProjectInfo(projectInfoEntity.getProjectStatus(), projectInfoEntity.getProjectName(), page);
        return new ResMsg(CodeEnum.OK, ResMsg.getMap(projectInfo.map(map -> {
            Map<Object, Object> map1 = new HashMap<>();
            map1.putAll(map);
            UserInfoEntity userInfoEntity = userInfoMapper.findByUserIdEquals((map.get("projectPrincipal")));
            map1.put("projectPrincipal", userInfoEntity != null ? userInfoEntity.getShowName() : null);
            String projectStage = map.get("projectStage");
            switch (ProjectPeriodEnum.getEnumByCode(projectStage)) {
                case BUSINESS_RESEARCHB:
                    map1.put("projectStage", ProjectPeriodEnum.BUSINESS_RESEARCHB.getReason());
                    break;
                case PRE_SALES:
                    map1.put("projectStage", ProjectPeriodEnum.PRE_SALES.getReason());
                    break;
                case PROJECT_START:
                    map1.put("projectStage", ProjectPeriodEnum.PROJECT_START.getReason());
                    break;
                case DELIVERY:
                    map1.put("projectStage", ProjectPeriodEnum.DELIVERY.getReason());
                    break;
                case CHECK_AND_ACCEPT:
                    map1.put("projectStage", ProjectPeriodEnum.CHECK_AND_ACCEPT.getReason());
                    break;
                case POST_PROJECT_THE_RECEIVABLE:
                    map1.put("projectStage", ProjectPeriodEnum.POST_PROJECT_THE_RECEIVABLE.getReason());
                    break;
                case CLOSE:
                    map1.put("projectStage", ProjectPeriodEnum.CLOSE.getReason());
                    break;
                default:
                    break;
            }
            String projectStatus = (String) map.get("projectStatus");
            switch (ProjectStatusEnum.getEnumByCode(projectStatus)) {
                case NORMAL:
                    map1.put("projectStatus", ProjectStatusEnum.NORMAL.getReason());
                    break;
                case POSTPONE:
                    map1.put("projectStatus", ProjectStatusEnum.POSTPONE.getReason());
                    break;
                case CANCEL:
                    map1.put("projectStatus", ProjectStatusEnum.CANCEL.getReason());
                    break;
                case RISKY:
                    map1.put("projectStatus", ProjectStatusEnum.RISKY.getReason());
                    break;
                case OUT_OF_CONTROL:
                    map1.put("projectStatus", ProjectStatusEnum.OUT_OF_CONTROL.getReason());
                    break;
                default:
                    break;
            }
            return map1;
        }).getContent(), projectInfo.getTotalElements()));
    }

    @Override
    public ResMsg findProjectInfoAll(String projectName) {
        List<ProjectInfoEntity> all = projectInfoMapper.findAllByProjectName(projectName);
        return new ResMsg(CodeEnum.OK, all);
    }

    @Override
    public ResMsg findProjectParticulars(ProjectInfoEntity projectInfoEntity) {
        Optional<ProjectInfoEntity> byId = projectInfoMapper.findById(projectInfoEntity.getProjectId());
        ProjectInfoEntity projectInfoEntity1 = byId.orElse(null);
        Optional<UserInfoEntity> projectPrincipal = userInfoMapper.findById(projectInfoEntity1.getProjectPrincipal());
        UserInfoEntity userInfoEntity = projectPrincipal.orElse(null);
        projectInfoEntity1.setProjectPrincipal(userInfoEntity != null ? userInfoEntity.getShowName() : null);
        return new ResMsg(CodeEnum.OK, projectInfoEntity1);
    }

    @Override
    public ResMsg addProject(ProjectInfoEntity projectInfoEntity) {
        List<ProjectInfoEntity> all = projectInfoMapper.findAll();
        for (ProjectInfoEntity pro : all) {
            if (projectInfoEntity.getProjectName().equals(pro.getProjectName())) {
                return new ResMsg(CodeEnum.TNE_PROJECT_NAME_ALREADY_EXISTS);
            }
        }
        projectInfoEntity.setProjectStage(ProjectPeriodEnum.BUSINESS_RESEARCHB.getCode());
        projectInfoEntity.setProjectStatus(ProjectStatusEnum.NORMAL.getCode());
        projectInfoEntity.setCreateDate(new Date());

        /**
         *调用新增项目信息申请流程的启动
         *获取流程开始节点之后的第一个任务节点的数据
         *param processDefinitionKey 新建项目信息审批流程--流程标识。
         */
        String processDefinitionKey = "ProjectAddApplyFlow";
        ResponseResult<FlowEntry> flowEntryResult = flowTaskStart.verifyAndGetFlowEntry(processDefinitionKey);
        if (!flowEntryResult.isSuccess()) {
            return ResMsg.newInstance(CodeEnum.FAIL, flowEntryResult);
        }
        FlowEntryPublish flowEntryPublish = flowEntryResult.getData().getMainFlowEntryPublish();
        String initTaskInfo = flowEntryPublish.getInitTaskInfo();
        com.ankaibei.workFlow.common.flow.vo.TaskInfoVo taskInfo = StrUtil.isBlank(initTaskInfo)
                ? null : JSON.parseObject(initTaskInfo, TaskInfoVo.class);
        if (taskInfo != null) {
            String loginName = TokenData.takeFromRequest().getLoginName();
            taskInfo.setAssignedMe(StrUtil.equalsAny(
                    taskInfo.getAssignee(), loginName, FlowConstant.START_USER_NAME_VAR));
        }
        //用户在表单页面配置的操作按钮
        FlowTaskCommentDto flowTaskCommentDto = new FlowTaskCommentDto();
        //提交后进行到第二个节点
        flowTaskCommentDto.setApprovalType("agree");
        HashMap<String, Object> stringObjectHashMap = new HashMap<>();
        stringObjectHashMap.put("project_name", projectInfoEntity.getProjectName());
        stringObjectHashMap.put("project_stage", projectInfoEntity.getProjectStage());
        stringObjectHashMap.put("project_status", projectInfoEntity.getProjectStatus());
        stringObjectHashMap.put("project_type", projectInfoEntity.getProjectType());
        stringObjectHashMap.put("relevance_client", projectInfoEntity.getRelevanceClient());
        stringObjectHashMap.put("peoject_money", projectInfoEntity.getPeojectMoney());
        stringObjectHashMap.put("staff_cost", projectInfoEntity.getStaffCost());
        stringObjectHashMap.put("project_cost", projectInfoEntity.getProjectCost());
        stringObjectHashMap.put("total_cost", projectInfoEntity.getTotalCost());
        stringObjectHashMap.put("linkman_phone", projectInfoEntity.getLinkmanPhone());
        stringObjectHashMap.put("project_principal", projectInfoEntity.getProjectPrincipal());
        stringObjectHashMap.put("project_node", projectInfoEntity.getProjectNode());
        stringObjectHashMap.put("project_describe", projectInfoEntity.getProjectDescribe());
        stringObjectHashMap.put("create_date", projectInfoEntity.getCreateDate());
        ProjectInfoEntity save = projectInfoMapper.save(projectInfoEntity);
        stringObjectHashMap.put("project_id", save.getProjectId());
        JSONObject masterData = (JSONObject) JSONObject.toJSON(stringObjectHashMap);
        Map<String, String> map = flowTaskStart.startAndTakeUserTaskSS(processDefinitionKey, flowTaskCommentDto, null, masterData, null, null).getData();
        save.setProcessDefinitionId(map.get("processDefinitionId"));
        save.setProcessInstanceId(map.get("processInstanceId"));
        save.setFlowTaskStatus(FlowTaskStatus.SUBMITTED);
        save.setIsDelete("1");
        projectInfoMapper.save(save);
        return new ResMsg(CodeEnum.OK);
    }

    @Override
    public ResMsg updateProject(ProjectInfoEntity projectInfoEntity) {

        projectInfoMapper.updateProject(projectInfoEntity.getProjectStage(), projectInfoEntity.getProjectStatus(), projectInfoEntity.getProjectId());
        return new ResMsg(CodeEnum.OK);
    }

    @Override
    public ResMsg deleteProjects(List<ProjectInfoVo> projectInfoVos) {
        //审批状态   已提交：0; 审批中：1; 被拒绝：2; 已结束：3; 提前停止：4; 已取消：5;
        StringBuffer optional = new StringBuffer("项目：[");
        int count = 0;
        for (ProjectInfoVo info : projectInfoVos) {
            ProjectInfoEntity byId = projectInfoMapper.getById(info.getProjectId());
            if (byId.getFlowTaskStatus() > 1) {
                projectInfoMapper.deleteProject(info.getProjectId());
                count++;
            } else {
                optional.append(byId.getProjectName() + ",");
            }
        }
        optional.replace(optional.length() - 1, optional.length(), "");
        optional.append("] 审批未结束，不可删除！");
        if (count == projectInfoVos.size()) {
            return new ResMsg(CodeEnum.OK, "");
        } else {
            return new ResMsg(CodeEnum.FAIL, optional);
        }
    }

    @Override
    public ResMsg findPrincipalProject(String userId) {
        //审批状态   已提交：0; 审批中：1; 被拒绝：2; 已结束：3; 提前停止：4; 已取消：5;
        List<ProjectInfoEntity> byProjectPrincipalEquals = projectInfoMapper.findByProjectPrincipalEqualsAndIsDeleteEquals(userId, "1");

        return new ResMsg(CodeEnum.OK, byProjectPrincipalEquals);
    }

    @Override
    public ResMsg findAccesoryInfo(ProjectInfoEntity projectInfoEntity) {
        List<AccesoryInfoEntity> byProjectIdEquals = accesoryInfoMapper.findByProjectIdEquals(String.valueOf(projectInfoEntity.getProjectId()));
        return new ResMsg(CodeEnum.OK, byProjectIdEquals.get(0));
    }

    @Override
    public ResMsg findProjectNumber() {
        String startDate = getMonthDayOne();
        String endDate = getToDay();
        List<String> twoDaysDayDes = getTwoDaysDayDes(startDate, endDate);
        List<Map<String, Object>> projectNumber = projectInfoMapper.findProjectNumber(twoDaysDayDes);
        List<EchartsEntityVo> listDate = new ArrayList<>();
        for (String list : twoDaysDayDes) {
            EchartsEntityVo echartsEntity = new EchartsEntityVo();
            echartsEntity.setTime(list);
            boolean b = false;
            for (Map<String, Object> num : projectNumber) {
                if (list.equals(num.get("time"))) {
                    echartsEntity.setNum(Integer.parseInt(num.get("num").toString()));
                    listDate.add(echartsEntity);
                    b = true;
                    break;
                }
            }
            if (!b) {
                echartsEntity.setNum(0);
                listDate.add(echartsEntity);
            }
        }
        return new ResMsg(CodeEnum.OK, listDate);
    }

    @Override
    public ResMsg substepOfProjectNum() {
        //当月第一天         年--月--日
        String startDate = getMonthDayOne();
        //今日              年--月--日
        String endDate = getToDay();
        List<Map<String, Object>> projectNumber = projectInfoMapper.getProjectNumberOfMonth(startDate + " 00:00:00", endDate + " 23:59:59");
        //获取姓名负责人。再查负责人所在公司
        List<String> deptNameList = new ArrayList<>();
        for (Map<String, Object> map : projectNumber) {
            String projectPrincipal = map.get("projectPrincipal").toString();
            UserInfoEntity byId = userInfoMapper.getById(projectPrincipal);
            //部门上一级就是公司级别；
            SysDept dept = sysDeptMapper.selectById(byId.getDeptId());
            if (dept.getParentId() != null) {
                SysDept sysDept = sysDeptMapper.selectById(dept.getParentId());
                deptNameList.add(sysDept.getDeptName());
            } else {
                deptNameList.add(dept.getDeptName());
            }
        }
        //统计数量
        Map map = countListItemNum(deptNameList);
        List<EchartsEntityVo> listDate = new ArrayList<>();
        Set keyset = map.keySet();
        for (Object key : keyset) {
            EchartsEntityVo echartsVo = new EchartsEntityVo();
            echartsVo.setDeptName(key.toString());
            echartsVo.setNum(Integer.parseInt(map.get(key).toString()));
            listDate.add(echartsVo);
            System.out.println(key + "-" + map.get(key));
        }
        return new ResMsg(CodeEnum.OK, listDate);
    }

    @Override
    public ResMsg findLastMonthProjectNumber() {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Calendar cal_1 = Calendar.getInstance();
        cal_1.add(Calendar.MONTH, -1);
        cal_1.set(Calendar.DAY_OF_MONTH, 1);
        cal_1.set(Calendar.HOUR_OF_DAY, 0);
        cal_1.set(Calendar.MINUTE, 0);
        cal_1.set(Calendar.SECOND, 0);
        //获取上个月第一天
        String firstDay = format.format(cal_1.getTime());
        Calendar cal_2 = Calendar.getInstance();
        cal_2.set(Calendar.DAY_OF_MONTH, 0);
        cal_2.set(Calendar.HOUR_OF_DAY, 23);
        cal_2.set(Calendar.MINUTE, 59);
        cal_2.set(Calendar.SECOND, 59);
        //获取上个月最后一天
        String lastDay = format.format(cal_2.getTime());
        List<String> twoDaysDayDes = getTwoDaysDayDes(firstDay, lastDay);
        List<Map<String, Object>> projectNumber = projectInfoMapper.findProjectNumber(twoDaysDayDes);
        List<EchartsEntityVo> listDate = new ArrayList<>();
        for (String list : twoDaysDayDes) {
            EchartsEntityVo echartsEntity = new EchartsEntityVo();
            echartsEntity.setTime(list);
            boolean b = false;
            for (Map<String, Object> num : projectNumber) {
                if (list.equals(num.get("time"))) {
                    echartsEntity.setNum(Integer.parseInt(num.get("num").toString()));
                    listDate.add(echartsEntity);
                    b = true;
                    break;
                }
            }
            if (!b) {
                echartsEntity.setNum(0);
                listDate.add(echartsEntity);
            }
        }
        return new ResMsg(CodeEnum.OK, listDate);
    }

    @Override
    public ResMsg substepOfProjectNumAtLastMonth() {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        //获取上个月第一天
        Calendar cal_1 = Calendar.getInstance();
        cal_1.add(Calendar.MONTH, -1);
        cal_1.set(Calendar.DAY_OF_MONTH, 1);
        cal_1.set(Calendar.HOUR_OF_DAY, 0);
        cal_1.set(Calendar.MINUTE, 0);
        cal_1.set(Calendar.SECOND, 0);
        String firstDay = format.format(cal_1.getTime());
        //获取上个月最后一天
        Calendar cal_2 = Calendar.getInstance();
        cal_2.set(Calendar.DAY_OF_MONTH, 0);
        cal_2.set(Calendar.HOUR_OF_DAY, 23);
        cal_2.set(Calendar.MINUTE, 59);
        cal_2.set(Calendar.SECOND, 59);
        String lastDay = format.format(cal_2.getTime());
        List<Map<String, Object>> projectNumber = projectInfoMapper.getProjectNumberOfMonth(firstDay + " 00:00:00", lastDay + " 23:59:59");
        //获取项目负责人。再查负责人所在公司
        List<String> deptNameList = new ArrayList<>();
        for (Map<String, Object> map : projectNumber) {
            String projectPrincipal = map.get("projectPrincipal").toString();
            UserInfoEntity byId = userInfoMapper.getById(projectPrincipal);
            //部门上一级就是公司级别；
            SysDept dept = sysDeptMapper.selectById(byId.getDeptId());
            if (dept.getParentId() != null) {
                SysDept sysDept = sysDeptMapper.selectById(dept.getParentId());
                deptNameList.add(sysDept.getDeptName());
            } else {
                deptNameList.add(dept.getDeptName());
            }
        }
        //统计数量
        Map map = countListItemNum(deptNameList);
        List<EchartsEntityVo> listDate = new ArrayList<>();
        Set keyset = map.keySet();
        for (Object key : keyset) {
            EchartsEntityVo echartsVo = new EchartsEntityVo();
            echartsVo.setDeptName(key.toString());
            echartsVo.setNum(Integer.parseInt(map.get(key).toString()));
            listDate.add(echartsVo);
            System.out.println(key + "-" + map.get(key));
        }
        return new ResMsg(CodeEnum.OK, listDate);
    }

    /**
     * 获取一段时间内每一天的日期
     */
    private static List<String> getTwoDaysDayDes(String startDate, String endDate) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        List<String> dateList = new ArrayList<>();
        try {
            Date dateOne = sdf.parse(startDate);
            Date dateTwo = sdf.parse(endDate);
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(dateOne);
            dateList.add(startDate);
            while (dateTwo.after(calendar.getTime())) {
                calendar.add(Calendar.DAY_OF_MONTH, 1);
                dateList.add(sdf.format(calendar.getTime()));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return dateList;
    }

    /**
     * 获取当月第一天
     */
    private static String getMonthDayOne() {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        String startDay = df.format(new Date());
        Calendar calendar = Calendar.getInstance();
        calendar.set(Integer.parseInt(startDay.substring(0, 4)), Integer.parseInt(startDay.substring(5, 7)) - 1, 1);
        String firstDayOfMonth = new SimpleDateFormat("yyyy-MM-dd ").format(calendar.getTime());
        return firstDayOfMonth;
    }

    /**
     * 获取当天日期
     */
    private static String getToDay() {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        String startDay = df.format(new Date());
        return startDay;
    }

    /**
     * 使用Lambda表达式实现过滤统计
     */
    public Map countListItemNum(List list) {
// 使用Map存储List中每个元素的数量：key：元素   value:数量
        Map result = new HashMap<>();
        list.forEach(item -> {
            long count = list.stream().filter(f ->
                    item.equals(f)).count();
            result.put(item, count);
        });
//// 遍历结果map
//        result.forEach((k, v) -> {
//            System.out.println(k + ":" + v);
//        });
        return result;
    }


}
