package com.hz.pm.api.performance.manage;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hz.pm.api.common.helper.UserInfoHelper;
import com.hz.pm.api.common.util.StrUtils;
import com.hz.pm.api.performance.enumration.RectifyStatusEnum;
import com.hz.pm.api.performance.model.dto.ProjectAppraisalDTO;
import com.hz.pm.api.performance.model.entity.PerformanceAppraisal;
import com.hz.pm.api.performance.model.entity.PerformanceAppraisalProject;
import com.hz.pm.api.performance.model.req.PerformanceAppraisalListReq;
import com.hz.pm.api.performance.model.vo.PerformanceAppraisalProjectVO;
import com.hz.pm.api.performance.model.vo.PerformanceAppraisalVO;
import com.hz.pm.api.performance.model.vo.RectifyDetailVO;
import com.hz.pm.api.performance.service.IPerformanceAppraisalProjectService;
import com.hz.pm.api.performance.service.IPerformanceAppraisalService;
import com.hz.pm.api.projectlib.model.enumeration.ProjectStatusEnum;
import com.hz.pm.api.projectlib.model.enumeration.ProjectTypeNewEnum;
import com.hz.pm.api.projectlib.model.entity.Project;
import com.hz.pm.api.projectlib.service.IProjectService;
import com.hz.pm.api.sys.model.entity.Role;
import com.hz.pm.api.sys.service.IRoleService;
import com.hz.pm.api.user.model.enumeration.RoleEnum;
import com.hz.pm.api.user.security.model.UserFullInfoDTO;
import com.hz.pm.api.user.security.model.UserInfoDetails;
import com.hz.pm.api.user.util.LoginUserUtil;
import com.ningdatech.basic.exception.BizException;
import com.ningdatech.basic.function.VUtils;
import com.ningdatech.basic.model.PageVo;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * RectifyManage
 *
 * @author CMM
 * @since 2023/08/12 17:36
 */
@Component
@Slf4j
@AllArgsConstructor
public class RectifyManage {

    private final IPerformanceAppraisalService performanceAppraisalService;
    private final IPerformanceAppraisalProjectService performanceAppraisalProjectService;
    private final IProjectService projectService;
    private final IRoleService roleService;
    private final UserInfoHelper userInfoHelper;

    /**
     * 绩效列表
     *
     * @param req
     * @return
     */
    public PageVo<PerformanceAppraisalVO> list(PerformanceAppraisalListReq req) {
        UserInfoDetails user = LoginUserUtil.loginUserDetail();

        // 当前登录用户 单位code
        String mhUnitId = user.getMhUnitIdStr();
        // 获取当前登录用户的角色列表，只有单位管理员才能查看该列表
        List<Role> userRoleList = user.getUserRoleList();
        List<Long> roleIdList = userRoleList.stream().map(Role::getId).collect(Collectors.toList());
        Role role = roleService.getOne(Wrappers.lambdaQuery(Role.class)
                .eq(Role::getName, RoleEnum.COMPANY_MANAGER.getDesc()));
        if (Objects.isNull(role)) {
            throw new BizException("登录用户没有单位管理员角色!");
        }

        // 登录用户不是单位管理员，不能查看本单位的整改计划列表
        if (!roleIdList.contains(role.getId())) {
            return PageVo.empty();
        }

        // 获取登录用户所在单位的所有已终验项目信息
        List<Project> projectLists = projectService.list(Wrappers.lambdaQuery(Project.class)
                .eq(Project::getStatus, ProjectStatusEnum.ACCEPTED.getCode()).eq(Project::getBuildOrgCode, mhUnitId));

        if (CollUtil.isEmpty(projectLists)) {
            return PageVo.empty();
        }
        List<Long> projectIds = projectLists.stream().map(Project::getId).collect(Collectors.toList());
        // 获取添加过该单位项目的所有评价计划信息，且评价计划内包含有需要整改项目
        List<PerformanceAppraisalProject> paps = performanceAppraisalProjectService.list(Wrappers
                .lambdaQuery(PerformanceAppraisalProject.class).in(PerformanceAppraisalProject::getProjectId, projectIds)
                .eq(PerformanceAppraisalProject::getIsRectify, Boolean.TRUE));
        // 按评价计划分组
        Map<Long, List<PerformanceAppraisalProject>> papsMap =
                paps.stream().collect(Collectors.groupingBy(PerformanceAppraisalProject::getAppraisalId));
        if (CollUtil.isEmpty(paps)) {
            return PageVo.empty();
        }
        Set<Long> paIds = paps.stream().map(PerformanceAppraisalProject::getAppraisalId).collect(Collectors.toSet());
        // 获取评价计划列表
        Page<PerformanceAppraisal> page = req.page();
        LambdaQueryWrapper<PerformanceAppraisal> wrapper = Wrappers.lambdaQuery(PerformanceAppraisal.class)
                .in(PerformanceAppraisal::getId, paIds).orderByDesc(PerformanceAppraisal::getUpdateOn);
        performanceAppraisalService.page(page, wrapper);
        if (CollUtil.isEmpty(page.getRecords())) {
            return PageVo.empty();
        }

        List<PerformanceAppraisalVO> res = page.getRecords().stream().map(p -> {
            PerformanceAppraisalVO vo = BeanUtil.copyProperties(p, PerformanceAppraisalVO.class);
            // 统计评价计划待整改项目数量(整改状态为：整改情况待提交、整改核查不通过)
            List<PerformanceAppraisalProject> projects = papsMap.get(p.getId());
            List<PerformanceAppraisalProject> unRectifyProjects = projects.stream()
                    .filter(d -> RectifyStatusEnum.TO_BE_SUBMITTED.getCode().equals(d.getRectifyStatus())
                            || RectifyStatusEnum.NOT_APPROVED.getCode().equals(d.getRectifyStatus()))
                    .collect(Collectors.toList());
            vo.setUnRectifyNumber(unRectifyProjects.size());
            // 统计评价计划已整改项目数量(整改状态为：整改待审核、整改审核通过)
            List<PerformanceAppraisalProject> rectifiedProjects =
                    paps.stream()
                            .filter(d -> RectifyStatusEnum.TO_BE_REVIEWED.getCode().equals(d.getRectifyStatus())
                                    || RectifyStatusEnum.APPROVED.getCode().equals(d.getRectifyStatus()))
                            .collect(Collectors.toList());
            vo.setRectifiedNumber(rectifiedProjects.size());
            return vo;
        }).collect(Collectors.toList());
        return PageVo.of(res, page.getTotal());
    }

    public PageVo<PerformanceAppraisalProjectVO> unRectifyList(Long planId, PerformanceAppraisalListReq req) {
        UserInfoDetails user = LoginUserUtil.loginUserDetail();

        PerformanceAppraisal plan = performanceAppraisalService.getById(planId);
        VUtils.isTrue(Objects.isNull(plan)).throwMessage("该评价计划不存在!");

        // 获取评价计划内已添加的待整改项目信息
        List<PerformanceAppraisalProject> paps =
                performanceAppraisalProjectService.list(Wrappers.lambdaQuery(PerformanceAppraisalProject.class)
                        .eq(PerformanceAppraisalProject::getAppraisalId, plan.getId())
                        .eq(PerformanceAppraisalProject::getIsRectify, Boolean.TRUE)
                        .and(wp -> wp
                                .eq(PerformanceAppraisalProject::getRectifyStatus, RectifyStatusEnum.TO_BE_SUBMITTED.getCode()).or()
                                .eq(PerformanceAppraisalProject::getRectifyStatus, RectifyStatusEnum.NOT_APPROVED.getCode())));
        Map<Long, PerformanceAppraisalProject> papsMap =
                paps.stream().collect(Collectors.toMap(PerformanceAppraisalProject::getProjectId, p -> p));

        if (CollUtil.isEmpty(paps)) {
            return PageVo.empty();
        }

        // 获取本单位在当前评价计划内的项目
        Set<String> projectCodes =
                paps.stream().map(PerformanceAppraisalProject::getProjectCode).collect(Collectors.toSet());
        Page<Project> page = req.page();
        LambdaQueryWrapper<Project> wrapper =
                Wrappers.lambdaQuery(Project.class).in(Project::getProjectCode, projectCodes)
                        .eq(Project::getNewest, Boolean.TRUE).eq(Project::getBuildOrgCode, user.getMhUnitId())
                        .like(StringUtils.isNotBlank(req.getProjectName()), Project::getProjectName, req.getProjectName());
        projectService.page(page, wrapper);

        if (CollUtil.isEmpty(page.getRecords())) {
            return PageVo.empty();
        }

        List<PerformanceAppraisalProjectVO> res = page.getRecords().stream().map(p -> {
            PerformanceAppraisalProjectVO vo = BeanUtil.copyProperties(p, PerformanceAppraisalProjectVO.class);
            PerformanceAppraisalProject appraisalProject = papsMap.get(p.getId());
            BeanUtil.copyProperties(appraisalProject, vo);
            vo.setProjectId(appraisalProject.getProjectId());
            vo.setProjectCode(appraisalProject.getProjectCode());
            vo.setProjectTypeName(ProjectTypeNewEnum.getDesc(p.getProjectType()));
            vo.setAppraisalId(planId);
            vo.setRectifyStatus(appraisalProject.getRectifyStatus());
            vo.setRectifyStatusName(RectifyStatusEnum.getDesc(appraisalProject.getRectifyStatus()));
            return vo;
        }).collect(Collectors.toList());

        return PageVo.of(res, page.getTotal());
    }

    public PageVo<PerformanceAppraisalProjectVO> rectifiedList(Long planId, PerformanceAppraisalListReq req) {
        UserInfoDetails user = LoginUserUtil.loginUserDetail();

        PerformanceAppraisal plan = performanceAppraisalService.getById(planId);
        Assert.notNull(plan, "该评价计划不存在!");

        // 获取评价计划内已添加的已整改项目信息
        List<PerformanceAppraisalProject> paps =
                performanceAppraisalProjectService.list(Wrappers.lambdaQuery(PerformanceAppraisalProject.class)
                        .eq(PerformanceAppraisalProject::getAppraisalId, plan.getId())
                        .eq(PerformanceAppraisalProject::getIsRectify, Boolean.TRUE)
                        .and(wp -> wp
                                .eq(PerformanceAppraisalProject::getRectifyStatus, RectifyStatusEnum.TO_BE_REVIEWED.getCode()).or()
                                .eq(PerformanceAppraisalProject::getRectifyStatus, RectifyStatusEnum.APPROVED.getCode())));

        if (CollUtil.isEmpty(paps)) {
            return PageVo.empty();
        }

        // 获取本单位在当前评价计划内的项目
        Set<String> projectCodes =
                paps.stream().map(PerformanceAppraisalProject::getProjectCode).collect(Collectors.toSet());
        Page<Project> page = req.page();
        LambdaQueryWrapper<Project> wrapper = Wrappers.lambdaQuery(Project.class)
                .in(Project::getProjectCode, projectCodes)
                .eq(Project::getNewest, Boolean.TRUE)
                .eq(Project::getBuildOrgCode, user.getMhUnitId())
                .like(StrUtils.isNotBlank(req.getProjectName()), Project::getProjectName, req.getProjectName());
        projectService.page(page, wrapper);

        if (CollUtil.isEmpty(page.getRecords())) {
            return PageVo.empty();
        }
        Map<Long, PerformanceAppraisalProject> papsMap = paps.stream()
                .collect(Collectors.toMap(PerformanceAppraisalProject::getProjectId, p -> p));

        List<PerformanceAppraisalProjectVO> res = page.getRecords().stream().map(p -> {
            PerformanceAppraisalProjectVO vo = BeanUtil.copyProperties(p, PerformanceAppraisalProjectVO.class);
            PerformanceAppraisalProject appraisalProject = papsMap.get(p.getId());
            BeanUtil.copyProperties(appraisalProject, vo);
            vo.setProjectId(appraisalProject.getProjectId());
            vo.setProjectCode(appraisalProject.getProjectCode());
            vo.setProjectTypeName(ProjectTypeNewEnum.getDesc(p.getProjectType()));
            vo.setAppraisalId(planId);
            vo.setRectifyStatus(appraisalProject.getRectifyStatus());
            vo.setRectifyStatusName(RectifyStatusEnum.getDesc(appraisalProject.getRectifyStatus()));
            return vo;
        }).collect(Collectors.toList());

        return PageVo.of(res, page.getTotal());
    }

    public RectifyDetailVO getRectifyDetail(Long planId, String projectCode) {
        RectifyDetailVO vo = new RectifyDetailVO();
        // 根据评价计划ID和项目编号获取评价项目信息
        PerformanceAppraisalProject appraisalProject = performanceAppraisalProjectService.getOne(Wrappers
                .lambdaQuery(PerformanceAppraisalProject.class)
                .eq(PerformanceAppraisalProject::getAppraisalId, planId)
                .eq(PerformanceAppraisalProject::getProjectCode, projectCode));
        Assert.notNull(appraisalProject, "该项目已被移除评价计划，请返回上一页或者刷新重试!");
        BeanUtils.copyProperties(appraisalProject, vo);
        String rectifySubmitUserId = appraisalProject.getRectifySubmitUserId();
        if (StrUtils.isNotBlank(rectifySubmitUserId)) {
            UserFullInfoDTO userFullInfoDto = userInfoHelper.getUserFullInfo(rectifySubmitUserId);
            vo.setRectifySubmitUser(userFullInfoDto);
        }
        String rectifyResSubUserId = appraisalProject.getRectifyResSubUserId();
        if (StrUtils.isNotBlank(rectifyResSubUserId)) {
            UserFullInfoDTO userFullInfoDto = userInfoHelper.getUserFullInfo(rectifyResSubUserId);
            vo.setRectifyResSubUser(userFullInfoDto);
        }
        vo.setRectifyStatusName(RectifyStatusEnum.getDesc(appraisalProject.getRectifyStatus()));
        return vo;
    }

    @Transactional(rollbackFor = Exception.class)
    public String fillOutResult(ProjectAppraisalDTO param) {
        UserInfoDetails userDetail = LoginUserUtil.loginUserDetail();
        String userIdStr = String.valueOf(userDetail.getUserId());
        String username = userDetail.getUsername();

        Long appraisalId = param.getAppraisalId();
        Long appraisalProjectId = param.getAppraisalProjectId();
        String appraisalProjectCode = param.getAppraisalProjectCode();
        String rectifyResult = param.getRectifyResult();
        String rectifyResultAppendix = param.getRectifyResultAppendix();

        // 判断该项目是否还存在于计划或分组中
        Wrapper<PerformanceAppraisalProject> query = Wrappers.lambdaQuery(PerformanceAppraisalProject.class)
                .eq(PerformanceAppraisalProject::getAppraisalId, appraisalId)
                .eq(PerformanceAppraisalProject::getProjectId, appraisalProjectId)
                .eq(PerformanceAppraisalProject::getProjectCode, appraisalProjectCode);
        PerformanceAppraisalProject appraisalProject = performanceAppraisalProjectService.getOne(query);
        if (Objects.isNull(appraisalProject)) {
            throw new BizException("该项目已被移除评价计划，请返回上一页或者刷新重试!");
        }
        appraisalProject.setRectifyResult(rectifyResult);
        appraisalProject.setRectifyResultAppendix(rectifyResultAppendix);
        appraisalProject.setRectifyResSubUserId(userIdStr);
        appraisalProject.setRectifyResSubTime(LocalDateTime.now());
        // 更新整改状态为整改待审核
        appraisalProject.setRectifyStatus(RectifyStatusEnum.TO_BE_REVIEWED.getCode());
        appraisalProject.setUpdateOn(LocalDateTime.now());
        appraisalProject.setUpdateBy(username);
        if (performanceAppraisalProjectService.updateById(appraisalProject)) {
            return "提交审核成功!";
        }
        return "提交审核失败";
    }
}
