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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.alibaba.excel.EasyExcel;
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.google.common.collect.Lists;
import com.hz.pm.api.common.enumeration.CommonEnum;
import com.hz.pm.api.common.util.ExcelDownUtil;
import com.hz.pm.api.common.util.ExcelExportStyle;
import com.hz.pm.api.performance.constant.ProjectBizConst;
import com.hz.pm.api.performance.enumration.AppraisalTypeEnum;
import com.hz.pm.api.performance.helper.TemplateDetailBuildHelper;
import com.hz.pm.api.performance.model.dto.ProjectAppraisalDTO;
import com.hz.pm.api.performance.model.dto.ProjectAppraisalInfoDTO;
import com.hz.pm.api.performance.model.dto.SelfAppraisalScoreExportDTO;
import com.hz.pm.api.performance.model.entity.*;
import com.hz.pm.api.performance.model.req.PerformanceAppraisalExportReq;
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.ProjectAppraisalIndexDetailVO;
import com.hz.pm.api.performance.model.vo.ProjectTemplateDetailVO;
import com.hz.pm.api.performance.service.*;
import com.hz.pm.api.performance.util.ExcelFillCellMergeStrategy;
import com.hz.pm.api.performance.util.MultiColumnMergeStrategy;
import com.hz.pm.api.portrait.model.entity.ProjectTag;
import com.hz.pm.api.portrait.service.IProjectTagService;
import com.hz.pm.api.projectlib.model.entity.Project;
import com.hz.pm.api.projectlib.model.enumeration.ProjectStatusEnum;
import com.hz.pm.api.projectlib.model.enumeration.ProjectTypeNewEnum;
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.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 com.ningdatech.basic.util.StrPool;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
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;

/**
 * @Classname OrgSelfAppraisalManage
 * @Description
 * @Date 2023/6/19 14:18
 * @Author PoffyZhang
 */
@Component
@Slf4j
@AllArgsConstructor
public class OrgSelfAppraisalManage {

    private final IPerformanceAppraisalService performanceAppraisalService;
    private final IPerformanceAppraisalProjectService performanceAppraisalProjectService;
    private final IProjectService projectService;
    private final IRoleService roleService;
    private final IPerformanceIndicatorProjectTemplateService indicatorProjectTemplateService;
    private final TemplateDetailBuildHelper templateDetailBuildHelper;
    private final IPerformanceIndicatorProjectTemplateDetailService indicatorProjectTemplateDetailService;
    private final IProjectTagService projectTagService;
    private final IPerformanceAppraisalScoreInfoService performanceAppraisalScoreInfoService;

    /**
     * 绩效列表
     *
     * @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));
        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 -> BeanUtil.copyProperties(p, PerformanceAppraisalVO.class))
                .collect(Collectors.toList());
        return PageVo.of(res, page.getTotal());
    }

    public PageVo<PerformanceAppraisalProjectVO> pendingList(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())).stream()
                .filter(p -> Objects.isNull(p.getSelfAppraisalScoreTime())).collect(Collectors.toList());
        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.getMhUnitIdStr())
                .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 = new PerformanceAppraisalProjectVO();
                    BeanUtil.copyProperties(p, vo);
                    PerformanceAppraisalProject appraisalProject = papsMap.get(p.getId());
                    BeanUtil.copyProperties(appraisalProject, vo);
                    vo.setProjectId(appraisalProject.getProjectId());
                    vo.setProjectTypeName(ProjectTypeNewEnum.getDesc(p.getProjectType()));
                    vo.setCanSelfAppraisal(checkCanSelfAppraisal(appraisalProject));
                    vo.setAppraisalId(planId);
                    return vo;
                })
                .collect(Collectors.toList());

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

    /**
     * 已经自评表
     *
     * @param planId
     * @param req
     * @return
     */
    public PageVo<PerformanceAppraisalProjectVO> appraisaledList(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())).stream()
                .filter(p -> Objects.nonNull(p.getSelfAppraisalScoreTime())).collect(Collectors.toList());
        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.getMhUnitIdStr())
                .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.setProjectTypeName(ProjectTypeNewEnum.getDesc(p.getProjectType()));
                    vo.setCanSelfAppraisal(checkCanSelfAppraisal(appraisalProject));
                    vo.setAppraisalId(planId);
                    return vo;
                })
                .collect(Collectors.toList());

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

    /**
     * 是否可以自评
     *
     * @param appraisalProject
     * @return
     */
    private Boolean checkCanSelfAppraisal(PerformanceAppraisalProject appraisalProject) {
        // 在自评时间段内，且是首次自评(打分时间为空)
        if (LocalDateTime.now().compareTo(appraisalProject.getSelfAppraisalStart()) > 0 &&
                LocalDateTime.now().compareTo(appraisalProject.getSelfAppraisalEnd()) < 0 &&
                Objects.isNull(appraisalProject.getSelfAppraisalScoreTime())) {
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

    public ProjectAppraisalIndexDetailVO getAppraisalTemplateDetail(String projectCode) {
        ProjectAppraisalIndexDetailVO vo = new ProjectAppraisalIndexDetailVO();
        // 根据项目编码获取最新版本的项目信息
        Project project = projectService.getProjectByCode(projectCode);
        VUtils.isTrue(Objects.isNull(project)).throwMessage("项目不存在!");
        // 根据项目类型、预算年度、批复金额、项目标签匹配本区域指标模版
        String projectType = project.getProjectType();
        Integer projectYear = project.getProjectYear();
        BigDecimal approvalAmount = project.getApprovalAmount();
        VUtils.isTrue(Objects.isNull(approvalAmount)).throwMessage("未获取到该项目的立项批复金额");
        // 根据项目code获取项目标签ID列表
        List<Long> tagIdList = projectTagService.list(Wrappers.lambdaQuery(ProjectTag.class)
                        .eq(ProjectTag::getProjectCode, projectCode)).stream()
                .map(ProjectTag::getTagId).collect(Collectors.toList());
        VUtils.isTrue(CollUtil.isEmpty(tagIdList)).throwMessage("当前项目未设置标签,匹配不到指标模板,请至项目库或评价计划编辑页面设置标签!");

        List<String> strIdList = tagIdList.stream().map(String::valueOf).collect(Collectors.toList());
        String projectTagIds = String.join(StrPool.COMMA, strIdList);

        Integer amountRange = null;
        if (approvalAmount.compareTo(BigDecimal.valueOf(ProjectBizConst.FIVE_MILLION)) < 0) {
            amountRange = ProjectBizConst.AMOUNT_RANGE_ONE;
        } else if (approvalAmount.compareTo(BigDecimal.valueOf(ProjectBizConst.FIVE_MILLION)) >= 0 &&
                approvalAmount.compareTo(BigDecimal.valueOf(ProjectBizConst.TWENTY_MILLION)) < 0) {
            amountRange = ProjectBizConst.AMOUNT_RANGE_TWO;
        } else if (approvalAmount.compareTo(BigDecimal.valueOf(ProjectBizConst.TWENTY_MILLION)) >= 0) {
            amountRange = ProjectBizConst.AMOUNT_RANGE_THREE;
        }
        LambdaQueryWrapper<PerformanceIndicatorProjectTemplate> wrapper = Wrappers.lambdaQuery(PerformanceIndicatorProjectTemplate.class)
                .eq(PerformanceIndicatorProjectTemplate::getProjectType, projectType)
                .eq(PerformanceIndicatorProjectTemplate::getProjectYear, projectYear)
                .eq(PerformanceIndicatorProjectTemplate::getAmountRange, amountRange)
                .eq(PerformanceIndicatorProjectTemplate::getProjectTagIds, projectTagIds)
                .eq(PerformanceIndicatorProjectTemplate::getStatus, CommonEnum.YES.getCode())
                .orderByDesc(PerformanceIndicatorProjectTemplate::getUpdateOn);
        List<PerformanceIndicatorProjectTemplate> templates = indicatorProjectTemplateService.list(wrapper);
        VUtils.isTrue(CollUtil.isEmpty(templates)).throwMessage("该项目匹配不到指标模板，请返回上一页或者刷新重试。");
        if (templates.size() > 1) {
            throw new BizException("当前项目匹配到多个模板，请返回模板库检查模板配置!");
        }
        PerformanceIndicatorProjectTemplate projectTemplate = templates.get(0);
        // 装配项目指标详情及分数信息
        // 获取模版绩效指标详情
        List<PerformanceIndicatorProjectTemplateDetail> templateDetails = indicatorProjectTemplateDetailService.list(Wrappers.lambdaQuery(PerformanceIndicatorProjectTemplateDetail.class)
                .eq(PerformanceIndicatorProjectTemplateDetail::getTemplateId, projectTemplate.getId())
                .eq(PerformanceIndicatorProjectTemplateDetail::getIsAdditional, Boolean.FALSE));
        // 获取模版附加绩效指标详情
        List<PerformanceIndicatorProjectTemplateDetail> additionalTemplateDetails = indicatorProjectTemplateDetailService.list(Wrappers.lambdaQuery(PerformanceIndicatorProjectTemplateDetail.class)
                .eq(PerformanceIndicatorProjectTemplateDetail::getTemplateId, projectTemplate.getId())
                .eq(PerformanceIndicatorProjectTemplateDetail::getIsAdditional, Boolean.TRUE));
        List<ProjectTemplateDetailVO> templateDetailVos = templateDetailBuildHelper.buildTemplateDetail(templateDetails, projectCode, vo);
        List<ProjectTemplateDetailVO> additionalTemplateDetailVos = templateDetailBuildHelper.buildTemplateDetail(additionalTemplateDetails, projectCode, vo);
        vo.setProjectName(project.getProjectName());
        vo.setBuildOrgName(project.getBuildOrgName());
        vo.setProjectStatus(project.getStatus());
        vo.setProjectYear(projectYear);
        vo.setApprovalAmount(approvalAmount);
        vo.setTemplateDetails(templateDetailVos);
        vo.setAdditionalIndexDetails(additionalTemplateDetailVos);
        return vo;
    }

    @Transactional(rollbackFor = Exception.class)
    public String submitSelfAppraisal(ProjectAppraisalDTO param) {
        UserInfoDetails userDetail = LoginUserUtil.loginUserDetail();
        Long appraisalId = param.getAppraisalId();
        Long appraisalProjectId = param.getAppraisalProjectId();
        String appraisalProjectCode = param.getAppraisalProjectCode();
        List<ProjectAppraisalInfoDTO> appraisalInfoList = param.getAppraisalInfoList();
        // 判断该项目是否还存在于计划或分组中
        PerformanceAppraisalProject appraisalProject = performanceAppraisalProjectService.getOne(Wrappers.lambdaQuery(PerformanceAppraisalProject.class)
                .eq(PerformanceAppraisalProject::getAppraisalId, appraisalId)
                .eq(PerformanceAppraisalProject::getProjectId, appraisalProjectId)
                .eq(PerformanceAppraisalProject::getProjectCode, appraisalProjectCode));
        if (Objects.isNull(appraisalProject)) {
            throw new BizException("该项目已被移除评价计划，请返回上一页或者刷新重试!");
        }
        // 根据项目模板详情ID保存自评得分、打分时间
        if (CollUtil.isEmpty(appraisalInfoList)) {
            throw new BizException("填写所有自评得分后才能提交!");
        }
        List<Long> ids = appraisalInfoList.stream()
                .map(ProjectAppraisalInfoDTO::getProjectTemplateDetailId)
                .collect(Collectors.toList());
        // 查出项目模版详情信息
        List<PerformanceIndicatorProjectTemplateDetail> detailList = indicatorProjectTemplateDetailService.list(Wrappers.lambdaQuery(PerformanceIndicatorProjectTemplateDetail.class)
                .in(PerformanceIndicatorProjectTemplateDetail::getId, ids));
        if (CollUtil.isEmpty(detailList)) {
            throw new BizException("评价指标不存在!");
        }
        Map<Long, PerformanceIndicatorProjectTemplateDetail> detailMap = detailList.stream().collect(Collectors.toMap(PerformanceIndicatorProjectTemplateDetail::getId, d -> d));
        List<PerformanceAppraisalScoreInfo> scoreInfos = appraisalInfoList.stream().map(a -> {
            PerformanceIndicatorProjectTemplateDetail templateDetail = detailMap.get(a.getProjectTemplateDetailId());
            BigDecimal score = a.getScore();
            BigDecimal indexScore = templateDetail.getIndexScore();
            if (score.compareTo(indexScore) > 0 || score.compareTo(BigDecimal.ZERO) < 0) {
                throw new BizException("自评得分必须大于等于0且小于等于指标分值!");
            }
            // 保存自评分数信息
            PerformanceAppraisalScoreInfo scoreInfo = new PerformanceAppraisalScoreInfo();
            scoreInfo.setAppraisalBasis(a.getAppraisalBasis());
            scoreInfo.setAppraisalScore(a.getScore());
            scoreInfo.setAppraisalBasisAppendix(a.getAppraisalBasisAppendix());
            scoreInfo.setAppraisalType(AppraisalTypeEnum.SELF_APPRAISAL.getCode());
            scoreInfo.setTemplateDetailId(templateDetail.getId());
            scoreInfo.setTemplateId(templateDetail.getTemplateId());
            scoreInfo.setAppraisalUserId(String.valueOf(userDetail.getUserId()));
            scoreInfo.setAppraisalUserName(userDetail.getRealName());
            scoreInfo.setAppraisalId(appraisalId);
            scoreInfo.setAppraisalProjectId(appraisalProjectId);
            scoreInfo.setAppraisalProjectCode(appraisalProjectCode);
            scoreInfo.setCreateOn(LocalDateTime.now());
            scoreInfo.setCreateBy(userDetail.getRealName());
            return scoreInfo;
        }).collect(Collectors.toList());

        if (performanceAppraisalScoreInfoService.saveBatch(scoreInfos)) {
            // 计算自评总分并保存
            BigDecimal selfAppraisalTotalScore = appraisalInfoList.stream()
                    .map(ProjectAppraisalInfoDTO::getScore)
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            appraisalProject.setSelfAppraisalTotalScore(selfAppraisalTotalScore);
            appraisalProject.setSelfAppraisalScoreTime(LocalDateTime.now());
            appraisalProject.setIsCompleteSelfAppraisal(Boolean.TRUE);
            appraisalProject.setUpdateOn(LocalDateTime.now());
            appraisalProject.setUpdateBy(userDetail.getRealName());
            performanceAppraisalProjectService.updateById(appraisalProject);
            return "提交成功";
        }
        return "提交失败";
    }

    public void exportScore(HttpServletResponse response, PerformanceAppraisalExportReq param) {
        String projectCode = param.getProjectCode();
        Long appraisalId = param.getAppraisalId();

        // 根据项目编码获取最新版本的项目信息
        Project project = projectService.getProjectByCode(projectCode);
        Assert.notNull(project, "项目不存在!");
        // 根据项目类型、预算年度、批复金额、项目标签匹配本区域指标模版
        String projectType = project.getProjectType();
        Integer projectYear = project.getProjectYear();
        BigDecimal approvalAmount = project.getApprovalAmount();
        Assert.notNull(approvalAmount, "未获取到该项目的立项批复金额");
        // 根据项目code获取项目标签ID列表
        String tagIdStr = projectTagService.list(Wrappers.lambdaQuery(ProjectTag.class)
                        .eq(ProjectTag::getProjectCode, projectCode)).stream()
                .map(w -> w.getTagId().toString()).collect(Collectors.joining(","));
        Assert.notEmpty(tagIdStr, "当前项目未设置标签,匹配不到指标模板,请至项目库或评价计划编辑页面设置标签!");
        Integer amountRange = null;
        if (approvalAmount.compareTo(BigDecimal.valueOf(ProjectBizConst.FIVE_MILLION)) < 0) {
            amountRange = ProjectBizConst.AMOUNT_RANGE_ONE;
        } else if (approvalAmount.compareTo(BigDecimal.valueOf(ProjectBizConst.FIVE_MILLION)) >= 0 &&
                approvalAmount.compareTo(BigDecimal.valueOf(ProjectBizConst.TWENTY_MILLION)) < 0) {
            amountRange = ProjectBizConst.AMOUNT_RANGE_TWO;
        } else if (approvalAmount.compareTo(BigDecimal.valueOf(ProjectBizConst.TWENTY_MILLION)) >= 0) {
            amountRange = ProjectBizConst.AMOUNT_RANGE_THREE;
        }
        LambdaQueryWrapper<PerformanceIndicatorProjectTemplate> wrapper = Wrappers.lambdaQuery(PerformanceIndicatorProjectTemplate.class)
                .eq(PerformanceIndicatorProjectTemplate::getProjectType, projectType)
                .eq(PerformanceIndicatorProjectTemplate::getProjectYear, projectYear)
                .eq(PerformanceIndicatorProjectTemplate::getAmountRange, amountRange)
                .eq(PerformanceIndicatorProjectTemplate::getProjectTagIds, tagIdStr)
                .eq(PerformanceIndicatorProjectTemplate::getStatus, CommonEnum.YES.getCode())
                .orderByDesc(PerformanceIndicatorProjectTemplate::getUpdateOn);
        List<PerformanceIndicatorProjectTemplate> templates = indicatorProjectTemplateService.list(wrapper);
        VUtils.isTrue(CollUtil.isEmpty(templates)).throwMessage("该项目匹配不到指标模板，请返回上一页或者刷新重试。");
        if (templates.size() > 1) {
            throw new BizException("当前项目匹配到多个模板，请返回模板库检查模板配置!");
        }
        PerformanceIndicatorProjectTemplate projectTemplate = templates.get(0);
        // 装配项目指标详情及分数信息
        // 获取模版绩效指标详情
        List<PerformanceIndicatorProjectTemplateDetail> templateDetails = indicatorProjectTemplateDetailService.list(Wrappers.lambdaQuery(PerformanceIndicatorProjectTemplateDetail.class)
                .eq(PerformanceIndicatorProjectTemplateDetail::getTemplateId, projectTemplate.getId()));
        Map<Long, PerformanceIndicatorProjectTemplateDetail> templateDetailMap = templateDetails.stream().collect(Collectors.toMap(PerformanceIndicatorProjectTemplateDetail::getId, t -> t));

        List<SelfAppraisalScoreExportDTO> exportDataList = Lists.newArrayList();
        List<SelfAppraisalScoreExportDTO> exportAdditionalDataList = Lists.newArrayList();
        // 构建指标和打分详情
        List<PerformanceAppraisalScoreInfo> scoreInfoList = performanceAppraisalScoreInfoService.list(Wrappers.lambdaQuery(PerformanceAppraisalScoreInfo.class)
                .eq(PerformanceAppraisalScoreInfo::getAppraisalId, appraisalId)
                .eq(PerformanceAppraisalScoreInfo::getAppraisalType, AppraisalTypeEnum.SELF_APPRAISAL.getCode())
                .eq(PerformanceAppraisalScoreInfo::getAppraisalProjectCode, projectCode)
                .orderBy(Boolean.TRUE, Boolean.TRUE, PerformanceAppraisalScoreInfo::getTemplateDetailId));
        Map<Long, PerformanceAppraisalScoreInfo> scoreInfoMap = scoreInfoList.stream()
                .collect(Collectors.toMap(PerformanceAppraisalScoreInfo::getTemplateDetailId, p -> p));

        // 筛选出所有打分的三级指标模板详情ID
        for (PerformanceAppraisalScoreInfo scoreInfo : scoreInfoList) {
            SelfAppraisalScoreExportDTO thirdDto = new SelfAppraisalScoreExportDTO();
            Long detailId = scoreInfo.getTemplateDetailId();
            PerformanceIndicatorProjectTemplateDetail thirdTemplateDetail = templateDetailMap.get(detailId);
            thirdDto.setThirdIndexName(thirdTemplateDetail.getName());
            thirdDto.setIndexDetail(thirdTemplateDetail.getIndexDetail());
            thirdDto.setGradeDetail(thirdTemplateDetail.getGradeDetail());
            thirdDto.setSupportMaterial(thirdTemplateDetail.getSupportMaterial());
            thirdDto.setIndexScore(thirdTemplateDetail.getIndexScore());
            if (Boolean.TRUE.equals(thirdTemplateDetail.getIsAdditional())) {
                thirdDto.setIsAdditional(CommonEnum.YES.getDesc());
            } else if (Boolean.FALSE.equals(thirdTemplateDetail.getIsAdditional())) {
                thirdDto.setIsAdditional(CommonEnum.NO.getDesc());
            }
            PerformanceAppraisalScoreInfo appraisalScoreInfo = scoreInfoMap.get(thirdTemplateDetail.getId());
            if (Objects.nonNull(appraisalScoreInfo)) {
                thirdDto.setAppraisalBasis(appraisalScoreInfo.getAppraisalBasis());
                thirdDto.setAppraisalScore(appraisalScoreInfo.getAppraisalScore());
            }
            // 二级指标名称
            Long secondId = thirdTemplateDetail.getParentId();
            if (Objects.nonNull(secondId)) {
                PerformanceIndicatorProjectTemplateDetail secondTemplateDetail = templateDetailMap.get(secondId);
                if (Objects.nonNull(secondTemplateDetail)) {
                    thirdDto.setSecondIndexName(secondTemplateDetail.getName());
                    // 一级指标名称
                    Long firstId = secondTemplateDetail.getParentId();
                    if (Objects.nonNull(firstId)) {
                        PerformanceIndicatorProjectTemplateDetail firstTemplateDetail = templateDetailMap.get(firstId);
                        if (Objects.nonNull(firstTemplateDetail)) {
                            thirdDto.setFirstIndexName(firstTemplateDetail.getName());
                        }
                    }
                }
            }
            if (Boolean.FALSE.equals(thirdTemplateDetail.getIsAdditional())) {
                exportDataList.add(thirdDto);
            } else {
                exportAdditionalDataList.add(thirdDto);
            }
        }
        exportDataList.addAll(exportAdditionalDataList);

        String fileName = "绩效评价_单位自评_评分明细表";
        ExcelDownUtil.setFileName(fileName, response);
        int[] mergeColumnIndex = {0};
        // 需要从第几行开始合并
        int mergeRowIndex = 1;
        //数据导出处理函数
        try {
            EasyExcel.write(response.getOutputStream(), SelfAppraisalScoreExportDTO.class)
                    .autoCloseStream(false)
                    .registerWriteHandler(new MultiColumnMergeStrategy(exportDataList.size(), 0, 1))
                    .registerWriteHandler(new ExcelFillCellMergeStrategy(mergeRowIndex, mergeColumnIndex))
                    .registerWriteHandler(ExcelExportStyle.formalStyle())
                    .sheet(fileName)
                    .doWrite(exportDataList);
        } catch (IOException e) {
            throw new BizException(e);
        }
    }
}
