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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import com.alibaba.fastjson.JSON;
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.google.common.collect.Sets;
import com.hz.pm.api.common.model.constant.BizConst;
import com.hz.pm.api.common.model.constant.RegionConst;
import com.hz.pm.api.common.helper.RegionCacheHelper;
import com.hz.pm.api.common.helper.UserInfoHelper;
import com.hz.pm.api.datascope.model.DataScopeDTO;
import com.hz.pm.api.datascope.utils.DataScopeUtil;
import com.hz.pm.api.projectdeclared.contants.DeclaredProjectConst;
import com.hz.pm.api.projectdeclared.model.dto.ReviewChecklistApproveDTO;
import com.hz.pm.api.projectdeclared.model.entity.ReviewChecklistApprove;
import com.hz.pm.api.projectdeclared.service.IReviewChecklistApproveService;
import com.hz.pm.api.projectlib.model.enumeration.ProjectStatusEnum;
import com.hz.pm.api.projectlib.helper.ProjectHelper;
import com.hz.pm.api.projectlib.model.entity.Project;
import com.hz.pm.api.projectlib.model.req.ProjectListReq;
import com.hz.pm.api.projectlib.model.vo.ProjectReviewCheckListItemVO;
import com.hz.pm.api.projectlib.service.IProjectService;
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 com.ningdatech.basic.util.CollUtils;
import com.ningdatech.basic.util.StrPool;
import com.wflow.bean.dto.FormsReviewChecklistDto;
import com.wflow.bean.dto.ReviewChecklistModuleDto;
import com.wflow.enums.ReviewChecklistResultEnum;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Classname ReviewChecklistManage
 * @Description
 * @Date 2023/11/7 17:04
 * @Author PoffyZhang
 */
@Component
@Slf4j
@RequiredArgsConstructor
public class ReviewChecklistManage {

    @Value("${spring.profiles.active}")
    private String active;

    private final IProjectService projectService;

    private final RegionCacheHelper regionCacheHelper;

    private final IReviewChecklistApproveService reviewChecklistApproveService;

    private final UserInfoHelper userInfoHelper;

    public PageVo<ProjectReviewCheckListItemVO> projectLibList(ProjectListReq req) {
        LambdaQueryWrapper<Project> query = ProjectHelper.projectQuery(req);
        //项目查最新
        query.eq(Project::getNewest, Boolean.TRUE);
        //建设方案提交后的状态
        query.ge(Project::getStatus, ProjectStatusEnum.SCHEME_UNDER_REVIEW.getCode())
                .ne(Project::getStatus, ProjectStatusEnum.PLAN_TO_BE_DECLARED.getCode());
        UserInfoDetails user = LoginUserUtil.loginUserDetail();
        buildReviewCheckPermission(query, user);

        Page<Project> page = projectService.page(req.page(), query);
        if (CollUtil.isEmpty(page.getRecords())) {
            return PageVo.empty();
        }

        List<String> projectCodes = page.getRecords().stream().map(Project::getProjectCode)
                .collect(Collectors.toList());
        //求出 审查了的 信息
        List<ReviewChecklistApprove> approves = reviewChecklistApproveService.list(Wrappers.lambdaQuery(ReviewChecklistApprove.class)
                .in(ReviewChecklistApprove::getProjectCode, projectCodes));
        Map<String, List<ReviewChecklistApprove>> approveMap =
                approves.stream().collect(Collectors.groupingBy(ReviewChecklistApprove::getProjectCode));

        List<Long> reviewHumans;
        // TODO
        if (BizConst.DEV.equals(active)) {
            reviewHumans = new ArrayList<>();
        } else {
            reviewHumans = new ArrayList<>();
        }
        Map<Long, String> userMap;
        if (!reviewHumans.isEmpty()) {
            List<UserFullInfoDTO> users = userInfoHelper.listUserFullInfoByUserIds(reviewHumans);
            userMap = CollUtils.listToMap(users, UserFullInfoDTO::getUserId, UserFullInfoDTO::getUsername);
        } else {
            userMap = Collections.emptyMap();
        }

        List<ProjectReviewCheckListItemVO> records = CollUtils.convert(page.getRecords(), w -> {
            ProjectReviewCheckListItemVO item = new ProjectReviewCheckListItemVO();
            item.setId(w.getId());
            item.setProjectName(w.getProjectName());
            item.setProjectCode(w.getProjectCode());
            item.setArea(w.getArea());
            item.setAreaCode(w.getAreaCode());
            item.setCreateOn(w.getCreateOn());
            item.setDeclaredAmount(w.getDeclareAmount());
            item.setStage(w.getStage());
            item.setStatus(w.getStatus());
            item.setProjectType(w.getProjectType());
            item.setProjectYear(w.getProjectYear());
            item.setBuildOrg(w.getBuildOrgName());
            item.setBizDomain(w.getBizDomain());
            item.setProcessStatus(w.getProcessStatus());
            item.setInstCode(w.getInstCode());
            item.setApprovedAmount(w.getApprovalAmount());
            item.setAnnualPlanAmount(w.getAnnualPlanAmount());
            // 审查人员情况
            item.setVerifiedHumans(computeVerify(item, approveMap.get(w.getProjectCode()), userMap, user));
            item.setReviewCheckFinish(w.getReviewCheckFinish());
            return item;
        });
        return PageVo.of(records, page.getTotal());
    }

    private String computeVerify(ProjectReviewCheckListItemVO item, List<ReviewChecklistApprove> reviewChecklistApproves,
                                 Map<Long, String> userMap, UserInfoDetails user) {
        List<String> reviewHumans;
        if (BizConst.DEV.equals(active)) {
            reviewHumans = DeclaredProjectConst.ReviewChecklist.REVIEW_HUMANS_ZYD;
        } else {
            reviewHumans = DeclaredProjectConst.ReviewChecklist.REVIEW_HUMANS_ZZD;
        }

        int maxNums = reviewHumans.size();
        Integer finishNums = 0;
        Set<String> computeHumanSet = new HashSet<>(reviewHumans);
        if (CollUtil.isEmpty(reviewChecklistApproves)) {
            item.setReviewCheckNotApprove(convertUser(userMap, computeHumanSet));
            return finishNums + StrPool.SLASH + maxNums;
        }
        for (ReviewChecklistApprove approve : reviewChecklistApproves) {
            if (StringUtils.isNotBlank(approve.getCreateByCode()) ||
                    computeHumanSet.contains(approve.getCreateByCode())) {
                if (StringUtils.isNotBlank(user.getEmployeeCode()) &&
                        user.getEmployeeCode().equals(approve.getCreateByCode())) {
                    item.setApproved(Boolean.TRUE);
                }
                if (computeHumanSet.remove(approve.getCreateByCode())) {
                    //说明 有指定人 审核过
                    finishNums++;
                }
            }
        }
        item.setReviewCheckNotApprove(convertUser(userMap, computeHumanSet));

        return finishNums + StrPool.SLASH + maxNums;
    }

    private String convertUser(Map<Long, String> userMap, Set<String> computeHumanSet) {
        if (CollUtil.isEmpty(userMap) || CollUtil.isEmpty(computeHumanSet)) {
            return StringUtils.EMPTY;
        }
        return computeHumanSet.stream()
                .filter(NumberUtil::isNumber)
                .map(w -> userMap.get(Long.parseLong(w)))
                .collect(Collectors.joining(StrPool.COMMA));
    }

    public UserFullInfoDTO buildReviewCheckPermission(LambdaQueryWrapper<Project> query, UserInfoDetails user) {
        UserFullInfoDTO userDto = BeanUtil.copyProperties(user, UserFullInfoDTO.class);
        Optional<DataScopeDTO> currentUserDataScope = DataScopeUtil.getCurrentUserDataScope(userDto);
        if (!currentUserDataScope.isPresent()) {
            log.warn("没有取到权限信息 当前查询 没有权限条件");
            query.eq(Project::getId, 0L);
            return userDto;
        }

        switch (currentUserDataScope.get().getRole()) {
            case NORMAL_MEMBER:
                //普通用户 看不了
                query.eq(Project::getId, 0L);
                break;
            case COMPANY_MANAGER:
            case VISITOR:
            case DASHBOARD:
                //单位管理员 看
                query.eq(Project::getId, 0L);
                break;
            case SUPER_ADMIN:
                //超级管理员 可以看
                break;
            case REGION_MANAGER:
                //区域管理员 可以看
                break;
            default:
                //没有权限的话 就让它查不到
                query.eq(Project::getId, 0L);
                break;
        }
        return userDto;
    }

    /**
     * 去审批
     *
     * @param dtos \
     * @return \
     */
    public String approve(List<ReviewChecklistApproveDTO> dtos) {
        if (CollUtil.isEmpty(dtos)) {
            throw new BizException("传入数据不能为空!");
        }
        ReviewChecklistApproveDTO reviewChecklistApproveFirst = dtos.get(0);
        String projectCode = reviewChecklistApproveFirst.getProjectCode();

        UserInfoDetails user = LoginUserUtil.loginUserDetail();
        Long userId = user.getUserId();
        String employeeCode = user.getEmployeeCode();
        String username = user.getUsername();
        List<String> reviewHumans;
        ;
        if (BizConst.DEV.equals(active)) {
            reviewHumans = DeclaredProjectConst.ReviewChecklist.REVIEW_HUMANS_ZYD;
        } else {
            reviewHumans = DeclaredProjectConst.ReviewChecklist.REVIEW_HUMANS_ZZD;
        }

        if (StringUtils.isBlank(employeeCode) || !reviewHumans.contains(employeeCode)) {
            throw new BizException("当前操作员 不是七大审查人之一!");
        }

        VUtils.isTrue(reviewChecklistApproveService.count(Wrappers.lambdaQuery(ReviewChecklistApprove.class)
                        .eq(ReviewChecklistApprove::getProjectCode, projectCode)
                        .eq(ReviewChecklistApprove::getCreateByCode, employeeCode)) > 0)
                .throwMessage("此项目 当前审查员 已经审批过 请不要重复审批");

        for (ReviewChecklistApproveDTO dto : dtos) {
            ReviewChecklistApprove saveEntity = new ReviewChecklistApprove();
            saveEntity.setCreateBy(username);
            saveEntity.setCreateById(userId);
            saveEntity.setCreateByCode(employeeCode);
            saveEntity.setTitle(dto.getTitle());
            saveEntity.setContent(dto.getContent());
            saveEntity.setSubTitle(dto.getSubTitle());
            saveEntity.setCorrPageNum(dto.getCorrPageNum());
            saveEntity.setRejectionSituation(dto.getRejectionSituation());
            saveEntity.setResponseSituation(dto.getResponseSituation());
            saveEntity.setReviewComments(dto.getReviewComments());
            saveEntity.setReviewResult(dto.getReviewResult());
            saveEntity.setProjectCode(dto.getProjectCode());
            reviewChecklistApproveService.save(saveEntity);
        }

        return BizConst.OP_SUCCESS;
    }

    /**
     * 查看待意见汇总 列表
     *
     * @param projectCode
     * @return
     */
    public List<FormsReviewChecklistDto> summaryList(String projectCode) {
        List<ReviewChecklistApprove> approves = reviewChecklistApproveService.list(Wrappers.lambdaQuery(ReviewChecklistApprove.class)
                .eq(ReviewChecklistApprove::getProjectCode, projectCode)
                .orderByAsc(ReviewChecklistApprove::getCreateOn));
        if (CollUtil.isEmpty(approves)) {
            return Collections.emptyList();
        }

        //做成map
        Map<String, List<ReviewChecklistApprove>> groupTitleMap = approves.stream()
                .collect(Collectors.groupingBy(ReviewChecklistApprove::getTitle));
        //去重标题
        Set<String> titleSet = Sets.newHashSet();
        List<ReviewChecklistApprove> dupTitle = approves.stream().filter(r -> titleSet.add(r.getTitle()))
                .collect(Collectors.toList());

        return dupTitle.stream()
                .map(r -> {
                    FormsReviewChecklistDto vo = new FormsReviewChecklistDto();
                    vo.setTitle(r.getTitle());
                    if (groupTitleMap.containsKey(r.getTitle())) {
                        List<ReviewChecklistApprove> reviewChecklistApproves = groupTitleMap.get(r.getTitle());
                        vo.setModules(convertModules(reviewChecklistApproves));
                    }
                    return vo;
                })
                .collect(Collectors.toList());
    }

    public String summary(String projectCode) {
        // 修改到 项目里去
        Project project = projectService.getProjectByCode(projectCode);
        VUtils.isTrue(Objects.isNull(project)).throwMessage("项目不存在");
        VUtils.isTrue(Objects.nonNull(project.getReviewCheckFinish()) && project.getReviewCheckFinish())
                .throwMessage("项目的审查清单已经合并过了!");

        List<ReviewChecklistApprove> approves = reviewChecklistApproveService.list(Wrappers.lambdaQuery(ReviewChecklistApprove.class)
                .eq(ReviewChecklistApprove::getProjectCode, projectCode)
                .orderByAsc(ReviewChecklistApprove::getCreateOn));
        if (CollUtil.isEmpty(approves)) {
            throw new BizException("该项目 未被七大审查人 审批!");
        }

        List<String> reviewHumans;
        if (BizConst.DEV.equals(active)) {
            reviewHumans = DeclaredProjectConst.ReviewChecklist.REVIEW_HUMANS_ZYD;
        } else {
            reviewHumans = DeclaredProjectConst.ReviewChecklist.REVIEW_HUMANS_ZZD;
        }
        Set<String> computeHumanSet = new HashSet<>(reviewHumans);
        for (ReviewChecklistApprove approve : approves) {
            computeHumanSet.remove(approve.getCreateByCode());
        }
        if (CollUtil.isNotEmpty(computeHumanSet)) {
            throw new BizException("此项目的审查清单 未被七大审核人 审批完!");
        }

        //做成map 并且还要 未通过的
        Map<String, List<ReviewChecklistApprove>> groupTitleMap = approves.stream()
                .filter(r -> Objects.nonNull(r.getReviewResult()) && Lists.newArrayList(
                                ReviewChecklistResultEnum.NOT_PASS.getCode(), ReviewChecklistResultEnum.ONE_VOTE_VETO.getCode())
                        .contains(r.getReviewResult()))
                .collect(Collectors.groupingBy(ReviewChecklistApprove::getTitle));
        //去重子标题
        Set<String> titleSet = Sets.newHashSet();
        List<ReviewChecklistApprove> dupTitle = approves.stream().filter(r -> titleSet.add(r.getTitle())).collect(Collectors.toList());

        List<FormsReviewChecklistDto> res = dupTitle.stream()
                .map(r -> {
                    FormsReviewChecklistDto vo = new FormsReviewChecklistDto();
                    vo.setTitle(r.getTitle());
                    if (groupTitleMap.containsKey(r.getTitle())) {
                        List<ReviewChecklistApprove> reviewChecklistApproves = groupTitleMap.get(r.getTitle());
                        vo.setModules(convertModulesFinal(reviewChecklistApproves));
                    }
                    return vo;
                })
                .collect(Collectors.toList());
        //修改 并且 已经合并
        project.setReviewChecklist(JSON.toJSONString(res));
        project.setReviewCheckFinish(Boolean.TRUE);
        projectService.updateById(project);

        return BizConst.OP_SUCCESS;
    }

    private List<ReviewChecklistModuleDto> convertModules(List<ReviewChecklistApprove> reviewChecklistApproves) {
        //做成map
        Map<String, List<ReviewChecklistApprove>> groupSubTitleMap = reviewChecklistApproves.stream()
                .collect(Collectors.groupingBy(ReviewChecklistApprove::getSubTitle));
        //去重子标题
        Set<String> subSubTitleSet = Sets.newHashSet();
        List<ReviewChecklistApprove> dupSubTitle = reviewChecklistApproves.stream().filter(r -> subSubTitleSet.add(r.getSubTitle()))
                .collect(Collectors.toList());
        return dupSubTitle.stream()
                .map(r -> {
                    ReviewChecklistModuleDto vo = new ReviewChecklistModuleDto();
                    vo.setSubTitle(r.getSubTitle());
                    vo.setContent(r.getContent());
                    vo.setReviewComments(r.getReviewComments());
                    vo.setRejectionSituation(r.getRejectionSituation());
                    vo.setResponseSituation(r.getResponseSituation());
                    vo.setCorrPageNum(r.getCorrPageNum());
                    if (groupSubTitleMap.containsKey(r.getSubTitle())) {
                        List<ReviewChecklistApprove> approves = groupSubTitleMap.get(r.getSubTitle());
                        StringBuilder reviewCommentsSb = new StringBuilder();
                        for (ReviewChecklistApprove approve : approves) {
                            ReviewChecklistResultEnum match = ReviewChecklistResultEnum.match(approve.getReviewResult());
                            reviewCommentsSb.append(approve.getCreateBy())
                                    .append(StrPool.COLON).append(Objects.nonNull(match) ? match.getDesc() : StringUtils.EMPTY)
                                    .append(StringUtils.isNotBlank(approve.getReviewComments()) ? StrPool.COMMA + approve.getReviewComments() : StringUtils.EMPTY)
                                    .append("\n");
                        }
                        vo.setReviewComments(reviewCommentsSb.toString());
                    }
                    return vo;
                }).collect(Collectors.toList());
    }

    private List<ReviewChecklistModuleDto> convertModulesFinal(List<ReviewChecklistApprove> reviewChecklistApproves) {
        //做成map
        Map<String, List<ReviewChecklistApprove>> groupSubTitleMap = reviewChecklistApproves.stream()
                .collect(Collectors.groupingBy(ReviewChecklistApprove::getSubTitle));
        //去重子标题
        Set<String> subSubTitleSet = Sets.newHashSet();
        List<ReviewChecklistApprove> dupSubTitle = reviewChecklistApproves.stream().filter(r -> subSubTitleSet.add(r.getSubTitle()))
                .collect(Collectors.toList());
        return dupSubTitle.stream()
                .map(r -> {
                    ReviewChecklistModuleDto vo = new ReviewChecklistModuleDto();
                    vo.setSubTitle(r.getSubTitle());
                    vo.setContent(r.getContent());
                    vo.setReviewComments(r.getReviewComments());
                    vo.setRejectionSituation(r.getRejectionSituation());
                    vo.setResponseSituation(r.getResponseSituation());
                    vo.setCorrPageNum(r.getCorrPageNum());
                    if (groupSubTitleMap.containsKey(r.getSubTitle())) {
                        List<ReviewChecklistApprove> approves = groupSubTitleMap.get(r.getSubTitle());
                        StringBuilder reviewCommentsSb = new StringBuilder();
                        if (CollUtil.isEmpty(approves)) {
                            vo.setReviewComments("通过");
                        } else {
                            Integer index = 1;
                            for (ReviewChecklistApprove approve : approves) {
                                ReviewChecklistResultEnum match = ReviewChecklistResultEnum.match(approve.getReviewResult());
                                reviewCommentsSb.append(index).append(StrPool.DOT).append(Objects.nonNull(match) ? match.getDesc() : StringUtils.EMPTY).append(StringUtils.isNotBlank(approve.getReviewComments()) ? StrPool.COMMA + approve.getReviewComments() : StringUtils.EMPTY).append("\n");
                                index++;
                            }
                            vo.setReviewComments(reviewCommentsSb.toString());
                        }
                    }
                    return vo;
                })
                .collect(Collectors.toList());
    }
}
