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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.hz.pm.api.performance.constant.ProjectBizConst;
import com.hz.pm.api.performance.enumration.AppIndexTypeEnum;
import com.hz.pm.api.performance.model.dto.AppAppraisalInfoDTO;
import com.hz.pm.api.performance.model.dto.ProjectAppraisalDTO;
import com.hz.pm.api.performance.model.entity.*;
import com.hz.pm.api.performance.model.req.PerformanceAppraisalListReq;
import com.hz.pm.api.performance.model.vo.*;
import com.hz.pm.api.performance.service.*;
import com.hz.pm.api.projectlib.model.entity.ProjectApplication;
import com.hz.pm.api.projectlib.service.IProjectApplicationService;
import com.hz.pm.api.sys.model.entity.Role;
import com.hz.pm.api.sys.service.IRoleService;
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 java.math.BigDecimal;
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;

/**
 * AppAppraisalManage
 *
 * @author CMM
 * @return
 * @since 2023/08/10 8:55
 */
@Component
@Slf4j
@AllArgsConstructor
public class AppAppraisalManage {
    private final IPerformanceAppraisalService performanceAppraisalService;
    private final IRoleService roleService;
    private final IPerformanceAppraisalAppScoreInfoService performanceAppraisalAppScoreInfoService;
    private final IPerformanceAppraisalProjectGroupService groupService;
    private final IProjectApplicationService projectApplicationService;
    private final IPerformanceAppraisalApplicationService performanceAppraisalApplicationService;
    private final IPerformanceAppraisalAppIndicatorService performanceAppraisalAppIndicatorService;
    private final IProjectCoreBusinessIndicatorsService projectCoreBusinessIndicatorsService;

    /**
     * 应用评价-评价计划列表
     *
     * @param req
     * @return
     */
    public PageVo<PerformanceAppraisalVO> list(PerformanceAppraisalListReq req) {
        UserInfoDetails user = LoginUserUtil.loginUserDetail();
        // 获取当前登录用户的角色列表，只有绩效复评人员才能查看该列表
        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, ProjectBizConst.REAPPRAISAL_ROLE));
        if (Objects.isNull(role)) {
            throw new BizException("登录用户没有复评员角色!");
        }

        // 登录用户不是复评员，不能查看复评计划列表
        if (!roleIdList.contains(role.getId())) {
            return PageVo.empty();
        }

        // 获取所有已添加到评价计划中的应用信息
        List<PerformanceAppraisalApplication> paas = performanceAppraisalApplicationService.list();
        // 没有包含应用的评价计划
        if (CollUtil.isEmpty(paas)) {
            return PageVo.empty();
        }
        Set<Long> paIds = paas.stream().map(PerformanceAppraisalApplication::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);
        List<PerformanceAppraisalVO> res = page.getRecords().stream()
                .map(p -> BeanUtil.copyProperties(p, PerformanceAppraisalVO.class))
                .collect(Collectors.toList());
        return PageVo.of(res, page.getTotal());
    }


    public PageVo<PerformanceAppraisalAppVO> unEvaluateList(Long planId, PerformanceAppraisalListReq req) {
        UserInfoDetails user = LoginUserUtil.loginUserDetail();
        String employeeCode = user.getEmployeeCode();

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

        // 获取分组所在评价计划添加的未完成评价的应用信息
        List<PerformanceAppraisalApplication> paas = performanceAppraisalApplicationService.list(Wrappers.lambdaQuery(PerformanceAppraisalApplication.class)
                .eq(PerformanceAppraisalApplication::getAppraisalId, planId)
                .eq(PerformanceAppraisalApplication::getIsCompleteAppraisal, Boolean.FALSE));
        // 没有当前用户待评价的应用信息
        if (CollUtil.isEmpty(paas)) {
            return PageVo.empty();
        }
        List<Long> ids = paas.stream().map(PerformanceAppraisalApplication::getApplicationId).collect(Collectors.toList());
        // 从绩效评价打分信息表中获取上述绩效评价计划应用的打分信息
        List<PerformanceAppraisalAppScoreInfo> appraisalScoreInfos = performanceAppraisalAppScoreInfoService.list(Wrappers.lambdaQuery(PerformanceAppraisalAppScoreInfo.class)
                .eq(PerformanceAppraisalAppScoreInfo::getAppraisalId, planId));
        List<Long> appIds;
        if (CollUtil.isNotEmpty(appraisalScoreInfos)) {
            // 筛选出当前登录用户已进行打分的应用信息
            List<Long> scoredAppIds = appraisalScoreInfos.stream()
                    .filter(a -> employeeCode.equals(a.getAppraisalEmployeeCode()))
                    .map(PerformanceAppraisalAppScoreInfo::getApplicationId)
                    .collect(Collectors.toList());
            ids.removeAll(scoredAppIds);
        }
        appIds = ids;
        // 没有当前用户待评价的应用信息
        if (CollUtil.isEmpty(appIds)) {
            return PageVo.empty();
        }
        Page<ProjectApplication> page = req.page();
        LambdaQueryWrapper<ProjectApplication> wrapper = Wrappers.lambdaQuery(ProjectApplication.class)
                .in(ProjectApplication::getId, appIds)
                .like(StringUtils.isNotBlank(req.getApplicationName()), ProjectApplication::getApplicationName, req.getApplicationName());
        projectApplicationService.page(page, wrapper);

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

        List<PerformanceAppraisalAppVO> res = page.getRecords().stream()
                .map(p -> {
                    PerformanceAppraisalAppVO vo = BeanUtil.copyProperties(p, PerformanceAppraisalAppVO.class);
                    vo.setCanAppraisal(checkCanAppraisal(employeeCode, p.getId(), planId));
                    vo.setApplicationName(StringUtils.isNotBlank(p.getApplicationName()) ? p.getApplicationName() : p.getRelatedExistsApplication());
                    vo.setAppraisalId(planId);
                    return vo;
                })
                .collect(Collectors.toList());

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

    public PageVo<PerformanceAppraisalAppVO> evaluatedList(Long planId, PerformanceAppraisalListReq req) {

        UserInfoDetails user = LoginUserUtil.loginUserDetail();
        String employeeCode = user.getUserIdStr();

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

        // 获取评价计划添加的已完成评价的应用信息
        List<PerformanceAppraisalApplication> paas = performanceAppraisalApplicationService.list(Wrappers.lambdaQuery(PerformanceAppraisalApplication.class)
                .eq(PerformanceAppraisalApplication::getAppraisalId, planId)
                .eq(PerformanceAppraisalApplication::getIsCompleteAppraisal, Boolean.TRUE));
        if (CollUtil.isEmpty(paas)) {
            return PageVo.empty();
        }
        // 从绩效评价打分信息表中获取上述绩效评价计划应用的打分信息
        List<PerformanceAppraisalAppScoreInfo> appraisalScoreInfos = performanceAppraisalAppScoreInfoService.list(Wrappers.lambdaQuery(PerformanceAppraisalAppScoreInfo.class)
                .eq(PerformanceAppraisalAppScoreInfo::getAppraisalId, planId));
        List<Long> appIds = Lists.newArrayList();
        if (CollUtil.isNotEmpty(appraisalScoreInfos)) {
            // 筛选出当前登录用户已进行打分的应用信息
            appIds = appraisalScoreInfos.stream()
                    .filter(a -> employeeCode.equals(a.getAppraisalEmployeeCode()))
                    .map(PerformanceAppraisalAppScoreInfo::getApplicationId)
                    .collect(Collectors.toList());
        }

        // 没有当前用户已评价的应用信息
        if (CollUtil.isEmpty(appIds)) {
            return PageVo.empty();
        }

        Page<ProjectApplication> page = req.page();
        LambdaQueryWrapper<ProjectApplication> wrapper = Wrappers.lambdaQuery(ProjectApplication.class)
                .in(ProjectApplication::getId, appIds)
                .like(StringUtils.isNotBlank(req.getApplicationName()), ProjectApplication::getApplicationName, req.getApplicationName());
        projectApplicationService.page(page, wrapper);

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

        List<PerformanceAppraisalAppVO> res = page.getRecords().stream()
                .map(p -> {
                    PerformanceAppraisalAppVO vo = BeanUtil.copyProperties(p, PerformanceAppraisalAppVO.class);
                    vo.setCanAppraisal(checkCanAppraisal(employeeCode, p.getId(), planId));
                    vo.setApplicationName(StringUtils.isNotBlank(p.getApplicationName()) ? p.getApplicationName() : p.getRelatedExistsApplication());
                    vo.setAppraisalId(planId);
                    return vo;
                })
                .collect(Collectors.toList());

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

    /**
     * 是否可以评价
     *
     * @param employeeCode
     * @param appId
     * @param appraisalId
     * @return
     */
    private Boolean checkCanAppraisal(String employeeCode, Long appId, Long appraisalId) {
        // 从绩效评价应用打分信息表中查询打分人员为当前登录复评用户的打分信息
        // 如果没有相关的打分信息，说明是当前登录复评用户是首次评价
        List<PerformanceAppraisalAppScoreInfo> scoreInfos = performanceAppraisalAppScoreInfoService.list(Wrappers.lambdaQuery(PerformanceAppraisalAppScoreInfo.class)
                .eq(PerformanceAppraisalAppScoreInfo::getApplicationId, appId)
                .eq(PerformanceAppraisalAppScoreInfo::getAppraisalId, appraisalId)
                .eq(PerformanceAppraisalAppScoreInfo::getAppraisalEmployeeCode, employeeCode));
        if (CollUtil.isEmpty(scoreInfos)) {
            return true;
        }
        return Boolean.FALSE;
    }


    public AppAppraisalIndexDetailVO detail(Long planId, Long appId) {

        ProjectApplication projectApplication = projectApplicationService.getById(appId);
        Assert.notNull(projectApplication, "应用不存在!");

        AppAppraisalIndexDetailVO resVo = new AppAppraisalIndexDetailVO();
        if (StringUtils.isNotBlank(projectApplication.getApplicationName())) {
            resVo.setApplicationName(projectApplication.getApplicationName());
        } else {
            resVo.setApplicationName(projectApplication.getRelatedExistsApplication());
        }
        resVo.setBuildOrgName(projectApplication.getBuildOrgName());
        // todo 应用状态 需通过appCode通过IRS接口获取，这里暂时写死 已验收
        resVo.setApplicationStatus("已验收");
        // 获取指标配置的应用指标信息
        // 通用指标
        List<PerformanceAppraisalAppIndicator> commonIndexList = performanceAppraisalAppIndicatorService.list(Wrappers.lambdaQuery(PerformanceAppraisalAppIndicator.class)
                .eq(PerformanceAppraisalAppIndicator::getIndexType, AppIndexTypeEnum.COMMON.getCode())
                .eq(PerformanceAppraisalAppIndicator::getIsDisplay, Boolean.TRUE)
                .orderBy(Boolean.TRUE, Boolean.TRUE, PerformanceAppraisalAppIndicator::getSort));
        // 获取当前应用通用指标的的打分信息
        Map<Long, PerformanceAppraisalAppScoreInfo> commonScoreInfoMap = performanceAppraisalAppScoreInfoService.list(Wrappers.lambdaQuery(PerformanceAppraisalAppScoreInfo.class)
                        .eq(PerformanceAppraisalAppScoreInfo::getAppraisalId, planId)
                        .eq(PerformanceAppraisalAppScoreInfo::getApplicationId, appId)
                        .eq(PerformanceAppraisalAppScoreInfo::getIndexType, AppIndexTypeEnum.COMMON.getCode()))
                .stream().collect(Collectors.toMap(PerformanceAppraisalAppScoreInfo::getIndexId, p -> p));
        if (CollUtil.isNotEmpty(commonIndexList)) {
            List<AppIndexDetailVO> commonIndexDetails = commonIndexList.stream().map(i -> {
                AppIndexDetailVO vo = new AppIndexDetailVO();
                BeanUtils.copyProperties(i, vo);
                PerformanceAppraisalAppScoreInfo scoreInfo = commonScoreInfoMap.get(i.getId());
                if (Objects.nonNull(scoreInfo)) {
                    vo.setAppraisalScore(scoreInfo.getAppraisalScore());
                }
                return vo;
            }).collect(Collectors.toList());
            resVo.setCommonIndexDetails(commonIndexDetails);
        }

        // 辅助指标
        List<PerformanceAppraisalAppIndicator> auxIndexList = performanceAppraisalAppIndicatorService.list(Wrappers.lambdaQuery(PerformanceAppraisalAppIndicator.class)
                .eq(PerformanceAppraisalAppIndicator::getIndexType, AppIndexTypeEnum.AUX.getCode())
                .eq(PerformanceAppraisalAppIndicator::getIsDisplay, Boolean.TRUE)
                .orderBy(Boolean.TRUE, Boolean.TRUE, PerformanceAppraisalAppIndicator::getSort));
        // 获取当前应用辅助指标的的打分信息
        Map<Long, PerformanceAppraisalAppScoreInfo> auxScoreInfoMap = performanceAppraisalAppScoreInfoService.list(Wrappers.lambdaQuery(PerformanceAppraisalAppScoreInfo.class)
                        .eq(PerformanceAppraisalAppScoreInfo::getAppraisalId, planId)
                        .eq(PerformanceAppraisalAppScoreInfo::getApplicationId, appId)
                        .eq(PerformanceAppraisalAppScoreInfo::getIndexType, AppIndexTypeEnum.AUX.getCode()))
                .stream().collect(Collectors.toMap(PerformanceAppraisalAppScoreInfo::getIndexId, p -> p));
        if (CollUtil.isNotEmpty(auxIndexList)) {
            List<AppIndexDetailVO> auxIndexDetails = auxIndexList.stream().map(i -> {
                AppIndexDetailVO vo = new AppIndexDetailVO();
                BeanUtils.copyProperties(i, vo);
                PerformanceAppraisalAppScoreInfo scoreInfo = auxScoreInfoMap.get(i.getId());
                if (Objects.nonNull(scoreInfo)) {
                    vo.setAppraisalScore(scoreInfo.getAppraisalScore());
                }
                return vo;
            }).collect(Collectors.toList());
            resVo.setAuxIndexDetails(auxIndexDetails);
        }
        // 获取应用的核心业务指标
        List<ProjectCoreBusinessIndicators> coreBusinessIndicators = projectCoreBusinessIndicatorsService.list(Wrappers.lambdaQuery(ProjectCoreBusinessIndicators.class)
                .eq(ProjectCoreBusinessIndicators::getApplicationId, appId));
        // 获取当前应用业务指标的的打分信息
        Map<Long, PerformanceAppraisalAppScoreInfo> businessScoreInfoMap = performanceAppraisalAppScoreInfoService.list(Wrappers.lambdaQuery(PerformanceAppraisalAppScoreInfo.class)
                        .eq(PerformanceAppraisalAppScoreInfo::getAppraisalId, planId)
                        .eq(PerformanceAppraisalAppScoreInfo::getApplicationId, appId)
                        .eq(PerformanceAppraisalAppScoreInfo::getIndexType, AppIndexTypeEnum.BUSINESS.getCode()))
                .stream().collect(Collectors.toMap(PerformanceAppraisalAppScoreInfo::getIndexId, p -> p));
        if (CollUtil.isNotEmpty(coreBusinessIndicators)) {
            List<AppBusinessIndexDetailVO> businessIndexDetails = coreBusinessIndicators.stream().map(c -> {
                AppBusinessIndexDetailVO appBusinessIndexDetailVo = new AppBusinessIndexDetailVO();
                BeanUtils.copyProperties(c, appBusinessIndexDetailVo);
                PerformanceAppraisalAppScoreInfo scoreInfo = businessScoreInfoMap.get(c.getId());
                if (Objects.nonNull(scoreInfo)) {
                    appBusinessIndexDetailVo.setAppraisalScore(scoreInfo.getAppraisalScore());
                }
                return appBusinessIndexDetailVo;
            }).collect(Collectors.toList());
            resVo.setBusinessIndexDetails(businessIndexDetails);
        }
        return resVo;
    }

    public String saveAppraisal(ProjectAppraisalDTO param) {
        UserInfoDetails userDetail = LoginUserUtil.loginUserDetail();
        String employeeCode = userDetail.getEmployeeCode();
        String username = userDetail.getUsername();

        Long applicationId = param.getApplicationId();
        Long appraisalId = param.getAppraisalId();
        List<AppAppraisalInfoDTO> appAppraisalInfoList = param.getAppAppraisalInfoList();

        // 获取评价应用
        PerformanceAppraisalApplication appraisalApplication = performanceAppraisalApplicationService.getOne(Wrappers.lambdaQuery(PerformanceAppraisalApplication.class)
                .eq(PerformanceAppraisalApplication::getAppraisalId, appraisalId)
                .eq(PerformanceAppraisalApplication::getApplicationId, applicationId));

        List<Long> indexIds = appAppraisalInfoList.stream().filter(a -> AppIndexTypeEnum.COMMON.getCode().equals(a.getIndexType()) ||
                        AppIndexTypeEnum.AUX.getCode().equals(a.getIndexType()))
                .map(AppAppraisalInfoDTO::getIndexId)
                .collect(Collectors.toList());
        List<Long> businessIndexIds = appAppraisalInfoList.stream()
                .filter(a -> AppIndexTypeEnum.BUSINESS.getCode().equals(a.getIndexType()))
                .map(AppAppraisalInfoDTO::getIndexId)
                .collect(Collectors.toList());
        // 查出通用、辅助应用指标分数信息
        Map<Long, PerformanceAppraisalAppIndicator> indexMap = MapUtil.newHashMap();
        if (CollUtil.isNotEmpty(indexIds)) {
            List<PerformanceAppraisalAppIndicator> indexList = performanceAppraisalAppIndicatorService.list(Wrappers.lambdaQuery(PerformanceAppraisalAppIndicator.class)
                    .in(PerformanceAppraisalAppIndicator::getId, indexIds));
            if (CollUtil.isEmpty(indexList)) {
                throw new BizException("通用/辅助评价指标不存在!");
            }
            indexMap = indexList.stream().collect(Collectors.toMap(PerformanceAppraisalAppIndicator::getId, d -> d));
        }

        // 查出应用业务指标分数信息
        Map<Long, ProjectCoreBusinessIndicators> businessIndexMap = MapUtil.newHashMap();
        if (CollUtil.isNotEmpty(businessIndexIds)) {
            List<ProjectCoreBusinessIndicators> businessIndexList = projectCoreBusinessIndicatorsService.list(Wrappers.lambdaQuery(ProjectCoreBusinessIndicators.class)
                    .in(ProjectCoreBusinessIndicators::getId, businessIndexIds));
            if (CollUtil.isEmpty(businessIndexList)) {
                throw new BizException("核心业务评价指标不存在!");
            }
            businessIndexMap = businessIndexList.stream().collect(Collectors.toMap(ProjectCoreBusinessIndicators::getId, d -> d));
        }

        Map<Long, PerformanceAppraisalAppIndicator> finalIndexMap = indexMap;
        Map<Long, ProjectCoreBusinessIndicators> finalBusinessIndexMap = businessIndexMap;
        List<PerformanceAppraisalAppScoreInfo> scoreInfos = appAppraisalInfoList.stream().map(a -> {
            if (AppIndexTypeEnum.COMMON.getCode().equals(a.getIndexType()) ||
                    AppIndexTypeEnum.AUX.getCode().equals(a.getIndexType())) {
                PerformanceAppraisalAppIndicator appIndicator = finalIndexMap.get(a.getIndexId());
                BigDecimal score = a.getScore();
                BigDecimal indexScore = appIndicator.getIndexScore();
                if (score.compareTo(indexScore) > 0 || score.compareTo(BigDecimal.ZERO) < 0) {
                    throw new BizException("评价得分必须大于等于0且小于等于指标分值!");
                }
            } else if (AppIndexTypeEnum.BUSINESS.getCode().equals(a.getIndexType())) {
                ProjectCoreBusinessIndicators coreBusinessIndicators = finalBusinessIndexMap.get(a.getIndexId());
                BigDecimal score = a.getScore();
                BigDecimal indexScore = coreBusinessIndicators.getScore();
                if (score.compareTo(indexScore) > 0 || score.compareTo(BigDecimal.ZERO) < 0) {
                    throw new BizException("评价得分必须大于等于0且小于等于指标分值!");
                }
            }
            // 保存评价分数信息
            PerformanceAppraisalAppScoreInfo scoreInfo = new PerformanceAppraisalAppScoreInfo();
            scoreInfo.setAppraisalScore(a.getScore());
            scoreInfo.setAppraisalId(appraisalId);
            scoreInfo.setAppraisalEmployeeCode(employeeCode);
            scoreInfo.setAppraisalEmployeeName(username);
            scoreInfo.setApplicationId(applicationId);
            scoreInfo.setIndexId(a.getIndexId());
            scoreInfo.setIndexType(a.getIndexType());
            scoreInfo.setCreateOn(LocalDateTime.now());
            scoreInfo.setCreateBy(username);
            scoreInfo.setUpdateOn(LocalDateTime.now());
            scoreInfo.setUpdateBy(username);
            return scoreInfo;
        }).collect(Collectors.toList());
        if (performanceAppraisalAppScoreInfoService.saveBatch(scoreInfos)) {
            // 计算评价总分并保存
            BigDecimal appraisalTotalScore = appAppraisalInfoList.stream()
                    .map(AppAppraisalInfoDTO::getScore)
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            appraisalApplication.setAppraisalTotalScore(appraisalTotalScore);
            appraisalApplication.setAppraisalScoreTime(LocalDateTime.now());
            // 一个复评员打完分就认为完成了打分
            appraisalApplication.setIsCompleteAppraisal(Boolean.TRUE);
            appraisalApplication.setUpdateBy(username);
            performanceAppraisalApplicationService.updateById(appraisalApplication);
            return "提交成功";
        }
        return "提交失败";
    }

}
