package cn.wisenergy.service.impl;

import cn.wisenergy.common.utils.DateUtil;
import cn.wisenergy.common.utils.exception.BASE_RESP_CODE_ENUM;
import cn.wisenergy.common.utils.exception.BaseCustomException;
import cn.wisenergy.mapper.WorkCentreMapper;
import cn.wisenergy.mapper.WorkDeptMapper;
import cn.wisenergy.mapper.WorkProjectMapper;
import cn.wisenergy.model.app.*;
import cn.wisenergy.model.dto.ManagerProjectsDto;
import cn.wisenergy.model.dto.ProjectDto;
import cn.wisenergy.model.dto.UserProjectDto;
import cn.wisenergy.model.enums.LevelEnum;
import cn.wisenergy.model.enums.LevelRankEnum;
import cn.wisenergy.model.enums.ManagerEnum;
import cn.wisenergy.model.vo.CreateProjectVo;
import cn.wisenergy.model.vo.GetManagerProjectsVo;
import cn.wisenergy.model.vo.ModifyProjectVo;
import cn.wisenergy.service.WorkProjectChangeService;
import cn.wisenergy.service.WorkProjectService;
import cn.wisenergy.service.WorkUserProjectService;
import cn.wisenergy.service.WorkUserService;
import cn.wisenergy.service.utils.UserRoleLevelUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author chenqi
 * @since 2021-01-19
 */
@Service
@Slf4j
public class WorkProjectServiceImpl implements WorkProjectService {

    @Autowired
    private WorkProjectMapper workProjectMapper;

    @Autowired
    private WorkUserService workUserService;

    @Autowired
    private WorkDeptMapper workDeptMapper;

    @Autowired
    private WorkCentreMapper workCentreMapper;

    @Autowired
    private WorkUserProjectService workUserProjectService;

    @Autowired
    private WorkProjectChangeService workProjectChangeService;

    @Autowired
    private UserRoleLevelUtils userRoleLevelUtils;

    /**
     * 功能：根据项目id获取项目
     *
     * @param id 项目id
     * @return WorkProject
     */
    @Override
    public WorkProject getById(Integer id) {
        log.info("WorkProjectServiceImpl[]getById[]input.param.id:" + id);
        if (null == id) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INPUT_PARAM_IS_NULL);
        }
        WorkProject workProject = workProjectMapper.selectById(id);
        if (null == workProject) {
            return null;
        }
        return workProject;
    }

    @Override
    public List<WorkProject> getNameByIds(List<Integer> ids, Integer isConclusion) {
        log.info("WorkProjectServiceImpl[]getNameById[]input.param.ids:" + ids);
        if (CollectionUtils.isEmpty(ids)) {
            return null;
        }
        List<WorkProject> workProjects = workProjectMapper.getProjectsByIds(ids, isConclusion);
        if (CollectionUtils.isEmpty(workProjects)) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.MANAGER_NOT_PROJECT);
        }
        return workProjects;
    }

    /**
     * 功能： 查询当前用户所管理的项目
     *
     * @param id 用户id
     * @return dto
     */
    @Override
    public List<ProjectDto> getByManagerId(Integer id, Integer isConclusion) {
        log.info("WorkProjectServiceImpl[]getByManagerId[]input.param.id:" + id);
        if (null == id) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INPUT_PARAM_IS_NULL);
        }
        QueryWrapper<WorkProject> wrapper = new QueryWrapper<>();
        wrapper.eq("manager_id", id);
        wrapper.eq("is_conclusion", isConclusion);
        List<WorkProject> workProjects = workProjectMapper.selectList(wrapper);
        if (!CollectionUtils.isEmpty(workProjects)) {
            return workProjectToDto(workProjects);
        }
        return null;
    }

    /**
     * WorkProject转ProjectDto
     */
    private List<ProjectDto> workProjectToDto(List<WorkProject> workProjects) {
        List<ProjectDto> projectDtos = new ArrayList<>();

        for (WorkProject workProject : workProjects) {
            ProjectDto projectDto = new ProjectDto();
            BeanUtils.copyProperties(workProject, projectDto);
            projectDtos.add(projectDto);
        }

        return projectDtos;
    }


    @Override
    public List<WorkProject> getUserManageProjects(Integer userId) {
        log.info("WorkProjectServiceImpl[]getUserManageProjects[]input.param" + userId);
        if (userId == null) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INPUT_PARAM_IS_NULL);
        }
        WorkUser user = workUserService.getById(userId);
        List<Integer> role = userRoleLevelUtils.getRole(user.getId());
        //普通用户
        if (role.contains(ManagerEnum.NOT_MANAGER.getCode())) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.THE_USER_NOT_MANAGER_PLASE_MANAGER_LOGIN);
        }
        //存放项目列表
        List<WorkProject> workProjects;
        //存放查询条件
        HashMap<String, Object> map = new HashMap<>();

        // 查询项目表中管理为用户的项目集合，
        map.put("managerId", userId);
        //用户是部门级别，查询该部门下的所有项目
        if (role.contains(ManagerEnum.IS_DEPARTMENT_DIRECTOR.getCode())) {
            map.remove("managerId");
            map.put("deptId", user.getDeptId());
        }
        //中心级别的用户查看中心下所有部门的所有项目
        if (role.contains(ManagerEnum.IS_CENTRE_DIRECTOR.getCode())) {
            //获取中心信息
            WorkCentre workCentre = workCentreMapper.getByManagerId(user.getId());
            if (workCentre == null) {
                throw new BaseCustomException(BASE_RESP_CODE_ENUM.CENTRE_NOT_FOUND);
            }
            map.put("centreId", workCentre.getId());
            //获取中心下的部门信息
            List<WorkDept> workDepts = workDeptMapper.getDeptByCondition(map);
            if (CollectionUtils.isEmpty(workDepts)) {
                throw new BaseCustomException(BASE_RESP_CODE_ENUM.DEPT_NOT_FOUND);
            }
            //获取这些部门的主键
            List<Integer> deptIds = workDepts.stream().map(WorkDept::getId).collect(Collectors.toList());
            map.clear();
            map.put("deptIds", deptIds);
        }
        workProjects = workProjectMapper.getProjectsByCriteria(map);

        return workProjects;
    }

    @Override
    public PageInfo getManagerProjects(GetManagerProjectsVo gmpv) {
        log.info("WorkProjectServiceImpl[]getManagerProjects[]input.param.GetManagerProjectsVo:{}" + gmpv);
        if (null == gmpv) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INPUT_PARAM_IS_NULL);
        }
        // 判断user是否是管理
        WorkUser user = workUserService.getById(gmpv.getUserId());
        if (null == user) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.QUERY_USER_INFO_FAIL);
        }

        // 判断用户权限
        List<Integer> roles = UserRoleLevelUtils.getRole(gmpv.getUserId());
        if (roles.get(0).equals(ManagerEnum.NOT_MANAGER.getCode())) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.THE_USER_NOT_MANAGER_PLASE_MANAGER_LOGIN);
        }
        List<Integer> levelIds = UserRoleLevelUtils.getlevelIds(roles);
        if (CollectionUtils.isEmpty(levelIds)) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.LEAVE_JOB_USER);
        }
        List<WorkLevel> workLevels = UserRoleLevelUtils.getlevelByIds(levelIds);
        if (CollectionUtils.isEmpty(workLevels)) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.LEAVE_JOB_USER);
        }

        Integer rank = null;
        for (WorkLevel level : workLevels) {
            if (LevelEnum.PROJECT_MANAGER.getLevelName().equals(level.getName())) {
                rank = level.getRank();
                break;
            }
        }
        if (null == rank) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.LEAVE_JOB_USER);
        }

        int page = gmpv.getPage() == null ? 1 : gmpv.getPage();
        int pageSize = gmpv.getPageSize() == null ? 10 : gmpv.getPageSize();
        Integer isConclusion = gmpv.getIsConclusion();
        Integer type = gmpv.getType() == null ? 1 : gmpv.getType();
        PageHelper.startPage(page, pageSize);
        List<ManagerProjectsDto> managerProjectsDto;

        // 中心负责人
        if (rank.equals(LevelRankEnum.CENTRAL_LEVEL.getRank())) {
            List<Integer> deptIds = new ArrayList<>();
            WorkCentre workCentre = workCentreMapper.getByManagerId(user.getId());
            HashMap<String, Object> map = new HashMap<>(5);
            map.put("centre_id", workCentre.getId());
            List<WorkDept> workDeptList = workDeptMapper.getDeptByCondition(map);
            workDeptList.forEach(workDept -> deptIds.add(workDept.getId()));
            managerProjectsDto = workProjectMapper.getManagerProjectsDto(gmpv.getUserId(), type, isConclusion, deptIds);
            return returnPageInfo(managerProjectsDto);
        }
        // 部门经理
        if (rank.equals(LevelRankEnum.DEPARTMENT_LEVEL.getRank())) {
            List<Integer> deptIds = new ArrayList<>();
            deptIds.add(user.getDeptId());
            managerProjectsDto = workProjectMapper.getManagerProjectsDto(gmpv.getUserId(), type, isConclusion, deptIds);
            return returnPageInfo(managerProjectsDto);
        }
        // 项目经理
        if (rank.equals(LevelRankEnum.PROJECT_LEVEL.getRank())) {
            managerProjectsDto = workProjectMapper.getManagerProjectsDto(gmpv.getUserId(), type, isConclusion, null);
            return returnPageInfo(managerProjectsDto);
        }
        throw new BaseCustomException(BASE_RESP_CODE_ENUM.LEAVE_JOB_USER);
    }

    /**
     * 结束项目/商机
     *
     * @param userId    管理id
     * @param projectId 项目/商机id
     * @return 布尔值
     */
    @Transactional
    @Override
    public Boolean endProject(Integer userId, Integer projectId) {
        log.info("WorkProjectServiceImpl[]endProject[]input.param.userId：{},projectId:{}" + userId, projectId);
        if (!UserRoleLevelUtils.isManagerLevel(userId, LevelEnum.PROJECT_MANAGER.getLevelName())) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.THE_USER_NOT_MANAGER_PLASE_MANAGER_LOGIN);
        }
        if (null == projectId) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INPUT_PARAM_IS_NULL);
        }
        WorkProject workProject = workProjectMapper.selectById(projectId);
        if (null == workProject) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.WORK_PROJECT_IS_NULL);
        }
        int i = workProjectMapper.updateIsConclusionById(projectId);
        return i > 0;
    }

    @Transactional
    @Override
    public Boolean modifyProject(ModifyProjectVo modifyProjectVo) {
        log.info("WorkProjectServiceImpl[]modifyProject[]input.param.ModifyProjectVo：{}" + modifyProjectVo);
        // 1.验证项目信息
        if (null == modifyProjectVo) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INPUT_PARAM_IS_NULL);
        }
        // 查询原项目
        WorkProject workProject = workProjectMapper.selectById(modifyProjectVo.getProjectId());
        if (null == workProject) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.WORK_PROJECT_IS_NULL);
        }
        // 查询当前项目的人员
        List<UserProjectDto> users = workUserProjectService.getUserProjectByProjectId(modifyProjectVo.getProjectId());
        List<Integer> userIds = new ArrayList<>();
        for (UserProjectDto user : users) {
            userIds.add(user.getId());
        }
        // 验证项目
        verificationItem(modifyProjectVo, workProject, userIds);

        // 2.更新表数据

        // 更新workProject数据
        if (!StringUtils.isBlank(modifyProjectVo.getStartTimeReason()) ||
                !StringUtils.isBlank(modifyProjectVo.getEndTimeReason()) ||
                !StringUtils.isBlank(modifyProjectVo.getWorkTimeReason()) ||
                !StringUtils.isBlank(modifyProjectVo.getCostBudgetReason())
        ) {
            int i = workProjectMapper.updateProject(modifyProjectVo);
            if (i == 0) {
                throw new BaseCustomException(BASE_RESP_CODE_ENUM.UPDATE_DATA_FAIL);
            }

            // 向workProjectChange插入内容
            List<WorkProjectChange> workProjectChanges = new ArrayList<>();
            WorkProjectChange workProjectChange = new WorkProjectChange();
            workProjectChange.setProjectId(modifyProjectVo.getProjectId());
            workProjectChange.setModifyTime(new Date());
            if (!StringUtils.isBlank(modifyProjectVo.getStartTimeReason())) {
                workProjectChange.setChangeType(3);
                workProjectChange.setModifyBefore(DateUtil.convertDateToStr(modifyProjectVo.getStartTime(), "yyyy-MM-dd"));
                workProjectChange.setModifyAfter(DateUtil.convertDateToStr(modifyProjectVo.getStartTime(), "yyyy-MM-dd"));
                workProjectChange.setReason(modifyProjectVo.getStartTimeReason());
                workProjectChanges.add(workProjectChange);
            }
            if (null != modifyProjectVo.getEndTime()) {
                workProjectChange.setChangeType(4);
                workProjectChange.setModifyBefore(DateUtil.convertDateToStr(modifyProjectVo.getEndTime(), "yyyy-MM-dd"));
                workProjectChange.setModifyAfter(DateUtil.convertDateToStr(modifyProjectVo.getEndTime(), "yyyy-MM-dd"));
                workProjectChange.setReason(modifyProjectVo.getEndTimeReason());
                workProjectChanges.add(workProjectChange);
            }
            if (null != modifyProjectVo.getWorkTime()) {
                workProjectChange.setChangeType(2);
                workProjectChange.setModifyBefore(workProject.getWorkTime().toString());
                workProjectChange.setModifyAfter(modifyProjectVo.getWorkTime().setScale(2, BigDecimal.ROUND_HALF_UP).toString());
                workProjectChange.setReason(modifyProjectVo.getWorkTimeReason());
                workProjectChanges.add(workProjectChange);
            }
            if (null != modifyProjectVo.getCostBudget()) {
                workProjectChange.setChangeType(1);
                workProjectChange.setModifyBefore(workProject.getCostBudget().toString());
                workProjectChange.setModifyAfter(modifyProjectVo.getCostBudget().setScale(2, BigDecimal.ROUND_HALF_UP).toString());
                workProjectChange.setReason(modifyProjectVo.getCostBudgetReason());
                workProjectChanges.add(workProjectChange);
            }
            workProjectChangeService.insertbatch(workProjectChanges);
        }


        // 更新workUserProject数据
        if (!userIds.containsAll(modifyProjectVo.getUserIds()) || !modifyProjectVo.getUserIds().containsAll(userIds)) {
            // 先删除,后插入
            if (!workUserProjectService.deleteByProjectId(modifyProjectVo.getProjectId())) {
                throw new BaseCustomException(BASE_RESP_CODE_ENUM.DELETE_OLD_WORK_ORDER_FAIL);
            }
            if (!workUserProjectService.insertBatch(modifyProjectVo.getUserIds(), modifyProjectVo.getProjectId())) {
                throw new BaseCustomException(BASE_RESP_CODE_ENUM.INSERT_DATA_IS_FAIL);
            }

        }
        return true;
    }

    @Transactional
    @Override
    public Boolean addProject(CreateProjectVo createProjectVo) {
        log.info("WorkProjectServiceImpl[]addProject[]input.param.createProjectVo：{}" + createProjectVo);
        // 1.验证工单
        if (null == createProjectVo) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INPUT_PARAM_IS_NULL);
        }
        if (null == createProjectVo.getManagerId() || null == createProjectVo.getStartTime() || null == createProjectVo.getEndTime() || null == createProjectVo.getOaProjectId() || null == createProjectVo.getWorkTime() || null == createProjectVo.getCostBudget() ||
                null == createProjectVo.getProjectName() || CollectionUtils.isEmpty(createProjectVo.getUserIds()) || null == createProjectVo.getDeptId()) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INPUT_PARAM_IS_NULL);
        }
        if (createProjectVo.getStartTime().compareTo(createProjectVo.getEndTime()) > 0) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.START_NOT_THAN_END_DATE);
        }
        if (BigDecimal.ZERO.compareTo(createProjectVo.getWorkTime()) > 0 || BigDecimal.ZERO.compareTo(createProjectVo.getCostBudget()) > 0) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.BUDGET_CANNOT_BELESSTHAN_ZERO);
        }
        // 判断oa编号是否重复
       /* List<WorkProject> workProjects = workProjectMapper.selectList(new QueryWrapper<>());
        if (CollectionUtils.isEmpty(workProjects)) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.WORK_PROJECT_IS_NULL);
        }
        for (WorkProject workProject : workProjects) {
            if (workProject.getOaProjectId().equals(createProjectVo.getOaProjectId())) {
                throw new BaseCustomException(BASE_RESP_CODE_ENUM.ITEMOADUPLICATE);
            }
        }*/

        // 插入项目信息
        Date date = new Date();
        WorkProject workProject = new WorkProject();
        workProject.setIsConclusion(1);
        workProject.setCreateTime(date);
        workProject.setModifyTime(date);
        BeanUtils.copyProperties(createProjectVo, workProject);
        int insert = workProjectMapper.insert(workProject);
        if (insert == 0) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INSERT_DATA_IS_FAIL);
        }

        // 插入参与人员信息
        return workUserProjectService.insertBatch(createProjectVo.getUserIds(), workProject.getId());
    }

    private PageInfo returnPageInfo(List<ManagerProjectsDto> managerProjectsDto) {

        if (CollectionUtils.isEmpty(managerProjectsDto)) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.WORK_PROJECT_IS_NULL);
        }
        PageInfo pageInfo = new PageInfo<>(managerProjectsDto);
        pageInfo.setList(managerProjectsDto);
        return pageInfo;
    }

    /**
     * 判断更变内容是否等于原内容
     */
    private void verificationItem(ModifyProjectVo modifyProjectVo, WorkProject workProject, List<Integer> userIds) {
        if (null != modifyProjectVo.getStartTime()) {
            if (StringUtils.isBlank(modifyProjectVo.getStartTimeReason())) {
                throw new BaseCustomException(BASE_RESP_CODE_ENUM.REASON_CANNOT_BE_EMPTY);
            }
            if (null == modifyProjectVo.getEndTime()) {
                if (modifyProjectVo.getStartTime().compareTo(workProject.getEndTime()) > 0) {
                    throw new BaseCustomException(BASE_RESP_CODE_ENUM.START_NOT_THAN_END_DATE);
                }
            } else {
                if (modifyProjectVo.getStartTime().compareTo(modifyProjectVo.getEndTime()) > 0) {
                    throw new BaseCustomException(BASE_RESP_CODE_ENUM.START_NOT_THAN_END_DATE);
                }
            }
            if (workProject.getStartTime().compareTo(modifyProjectVo.getStartTime()) == 0) {
                throw new BaseCustomException(BASE_RESP_CODE_ENUM.theNewContent_IsEqual_ToTheOriginal_Content);
            }
        }
        if (null != modifyProjectVo.getEndTime()) {
            if (StringUtils.isBlank(modifyProjectVo.getEndTimeReason())) {
                throw new BaseCustomException(BASE_RESP_CODE_ENUM.REASON_CANNOT_BE_EMPTY);
            }
            if (null != modifyProjectVo.getStartTime()) {
                if (modifyProjectVo.getStartTime().compareTo(modifyProjectVo.getEndTime()) > 0) {
                    throw new BaseCustomException(BASE_RESP_CODE_ENUM.START_NOT_THAN_END_DATE);
                }
            } else {
                if (workProject.getStartTime().compareTo(modifyProjectVo.getEndTime()) > 0) {
                    throw new BaseCustomException(BASE_RESP_CODE_ENUM.START_NOT_THAN_END_DATE);
                }
            }
            if (workProject.getEndTime().compareTo(modifyProjectVo.getEndTime()) == 0) {
                throw new BaseCustomException(BASE_RESP_CODE_ENUM.theNewContent_IsEqual_ToTheOriginal_Content);
            }
        }
        if (null != modifyProjectVo.getCostBudget()) {
            if (StringUtils.isBlank(modifyProjectVo.getCostBudgetReason())) {
                throw new BaseCustomException(BASE_RESP_CODE_ENUM.REASON_CANNOT_BE_EMPTY);
            }
            if (workProject.getCostBudget().compareTo(modifyProjectVo.getCostBudget()) == 0) {
                throw new BaseCustomException(BASE_RESP_CODE_ENUM.theNewContent_IsEqual_ToTheOriginal_Content);
            }
        }
        if (null != modifyProjectVo.getWorkTime()) {
            if (StringUtils.isBlank(modifyProjectVo.getWorkTimeReason())) {
                throw new BaseCustomException(BASE_RESP_CODE_ENUM.REASON_CANNOT_BE_EMPTY);
            }
            if (workProject.getWorkTime().compareTo(modifyProjectVo.getWorkTime()) == 0) {
                throw new BaseCustomException(BASE_RESP_CODE_ENUM.theNewContent_IsEqual_ToTheOriginal_Content);
            }
        }

        if (null == modifyProjectVo.getStartTime() && null == modifyProjectVo.getEndTime() && null == modifyProjectVo.getCostBudget() && null == modifyProjectVo.getWorkTime()) {
            if (userIds.containsAll(modifyProjectVo.getUserIds()) &&
                    modifyProjectVo.getUserIds().containsAll(userIds)) {
                throw new BaseCustomException(BASE_RESP_CODE_ENUM.theNewContent_IsEqual_ToTheOriginal_Content);
            }
        }

    }
}
