package jnpf.cultivate.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jnpf.base.UserInfo;
import jnpf.base.vo.PageListVO;
import jnpf.cultivate.mapper.FtbCultivatePositionIdentifyResultMapper;
import jnpf.cultivate.mapper.FtbCultivatePromotionPostApplyMapper;
import jnpf.cultivate.service.*;
import jnpf.cultivate.utils.UserApiV2Util;
import jnpf.model.cultivate.CultivatePage;
import jnpf.model.cultivate.dto.apply.FtbCultivatePromotionPostApplyCreateDto;
import jnpf.model.cultivate.dto.apply.FtbCultivatePromotionPostApplyDto;
import jnpf.model.cultivate.event.JnpfApplicationEvent;
import jnpf.model.cultivate.event.dto.file.FileEventDTO;
import jnpf.model.cultivate.po.FtbCultivateFile;
import jnpf.model.cultivate.po.apply.FtbCultivatePromotionPostApply;
import jnpf.model.cultivate.po.org.FtbPositionGradesInfoBoundVO;
import jnpf.model.cultivate.po.position.FtbCultivatePositionIdentifyResult;
import jnpf.model.cultivate.po.promotion.FtbCultivatePromotionPost;
import jnpf.model.cultivate.resp.UserExamDetailVo;
import jnpf.model.cultivate.vo.apply.FtbCultivatePromotionPostApplyVO;
import jnpf.model.cultivate.vo.apply.FtbCultivatePromotionPostApplyWithPerVO;
import jnpf.model.cultivate.vo.course.web.PromotionChannelLearnCourseVO;
import jnpf.model.cultivate.vo.identify.IdentifyApplyInfoApiVo;
import jnpf.model.cultivate.vo.offline.FtbCultivateOfflineFileVO;
import jnpf.model.cultivate.vo.promotion.FtbCultivatePromotionVO;
import jnpf.permission.PositionApi;
import jnpf.permission.UserApi;
import jnpf.permission.dto.v2.UserBoundInfoDTO;
import jnpf.permission.entity.UserEntity;
import jnpf.permission.model.position.PositionGradesInfoBoundVO;
import jnpf.permission.model.user.UserInfoVO;
import jnpf.permission.vo.v2.user.UserBoundVO;
import jnpf.util.UserProvider;
import jnpf.util.context.SpringContext;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class FtbCultivatePromotionPostApplyServiceImpl extends ServiceImpl<FtbCultivatePromotionPostApplyMapper, FtbCultivatePromotionPostApply> implements FtbCultivatePromotionPostApplyService {


    @Resource
    private FtbCultivatePromotionPostService postService;

    @Resource
    private FtbCultivatePromotionService promotionService;

    @Resource
    private FtbCultivateFileService ftbCultivateFileService;

    @Resource
    private FtbCultivateCourseService ftbCultivateCourseService;

    @Resource
    private CultivateIdentifyApplyService cultivateIdentifyApplyService;

    @Resource
    private FtbCultivateExamUserService ftbCultivateExamUserService;

    @Resource
    private FtbCultivatePositionIdentifyResultMapper ftbCultivatePositionIdentifyResultMapper;

    @Autowired
    private UserApi userApi;

    @Autowired
    private UserApiV2Util userApiV2Util;

    @Override
    public void initiateAPromotionApplication(FtbCultivatePromotionPostApplyCreateDto createDto) {
        FtbCultivatePromotionPostApply promotionPostApply = FtbCultivatePromotionPostApplyCreateDto.
                coverFtbCultivatePromotionPostApplyCreateDto(createDto);
        //晋升时需要判断是否不处于同一个组织
        if (!promotionPostApply.getOrgId().equals(promotionPostApply.getOrgCurrentId())) {
            throw new RuntimeException("当前岗位和晋升岗位不在同一组织无法进行申请!");
        }
        if (promotionPostApply.getUserId().equals(promotionPostApply.getReviewUserId())) {
            throw new RuntimeException("当前审批人无法指定自己,无法进行申请!");
        }
        LambdaQueryWrapper<FtbCultivatePromotionPostApply> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(FtbCultivatePromotionPostApply::getUserId, promotionPostApply.getUserId());
        wrapper.eq(FtbCultivatePromotionPostApply::getState, 0);
        FtbCultivatePromotionPostApply postApply = baseMapper.selectOne(wrapper);
        if (ObjectUtil.isNotNull(postApply)) {
            throw new RuntimeException("您上次提交的晋升申请还在审核中,请等待审核完成再提交!");
        }
        // 指定审批人web端
        if (promotionPostApply.getReviewUserId() == null) {
            // app端默认为当前主管
            UserInfoVO apiBossByUser = userApiV2Util.getBossByUserId(promotionPostApply.getUserId(),null);
            if (ObjectUtil.isNull(apiBossByUser)) {
                throw new RuntimeException("当前用户未分配上级,无法进行申请!");
            }
            // 获取当前用户上级
            promotionPostApply.setReviewUserId(apiBossByUser.getId());
        }
        List<FtbPositionGradesInfoBoundVO> positionGradesInfoBoundVOS = getPositionGradesInfoBoundVOS(promotionPostApply.getUserId(), promotionPostApply.getOrgId());
        if (ObjectUtil.isEmpty(positionGradesInfoBoundVOS)) {
            throw new RuntimeException("当前用户未分配岗位,无法进行申请!");
        }
        Set<String> collect = positionGradesInfoBoundVOS.stream().map(FtbPositionGradesInfoBoundVO::getPositionGradesId).collect(Collectors.toSet());
        if (!collect.contains(promotionPostApply.getPostRankId())) {
            throw new RuntimeException("当前申请变更岗位,在个人岗位中不存在请重新选择进行重试!");
        }
        // 根据管理id查询上级
        UserEntity infoById = userApi.getInfoById(promotionPostApply.getReviewUserId());
        if (ObjectUtil.isNotEmpty(infoById)) {
            promotionPostApply.setReviewUserName(infoById.getRealName());
        } else {
            throw new RuntimeException("当前用户未分配上级,无法进行申请!");
        }
        if (StringUtils.isNotEmpty(promotionPostApply.getReviewComment()) && promotionPostApply.getReviewComment().length() > 500) {
            throw new RuntimeException("审核评语过长,不能超过500个字,请修改后重试!");
        }
        if (StringUtils.isNotEmpty(promotionPostApply.getPromotionReason()) && promotionPostApply.getPromotionReason().length() > 500) {
            throw new RuntimeException("晋升原因过长,不能超过500个字,请修改后重试!");
        }
        promotionPostApply.setState(0);
        this.save(promotionPostApply);
        //通过文件事件监听信息
        SpringContext.getApplicationContext().publishEvent(new JnpfApplicationEvent<>(FileEventDTO.builder()
                .files(createDto.getFiles())
                .businessTypeID(promotionPostApply.getId())
                .type(FileEventDTO.FileType.JOB_PROMOTION_APPLICATION)
                .build()));
    }

    /**
     * 过滤当前组织用户
     *
     * @param userId
     * @param orgId
     * @return
     */
    @NotNull
    public List<FtbPositionGradesInfoBoundVO> getPositionGradesInfoBoundVOS(String userId, String orgId) {
//        List<PositionGradesInfoBoundVO> orgPositionInfoList = positionApi.getOrgPositionInfoList(userId);
        List<UserBoundVO> orgPositionInfoList = new ArrayList<>();
        Map<String, List<UserBoundVO>> userPrimaryBoundBatchCompatible = userApiV2Util.getUserPrimaryBoundBatchCompatible(List.of(userId), null);
        if(CollUtil.isNotEmpty(userPrimaryBoundBatchCompatible)){
            orgPositionInfoList = userPrimaryBoundBatchCompatible.get(userId);
        }
        List<FtbPositionGradesInfoBoundVO> list = new ArrayList<>();
        if (CollUtil.isNotEmpty(orgPositionInfoList)) {
            orgPositionInfoList.forEach(item -> {
                FtbPositionGradesInfoBoundVO post = new FtbPositionGradesInfoBoundVO();
                if (StringUtils.isEmpty(item.getOrganizeId())) {
                    return;
                }
                List<String> organizeIds = List.of(item.getOrganizeId());
                List<String> organizeNames = List.of(item.getOrganizeName());
                for (int i = 0; i < organizeIds.size(); i++) {
                    if (organizeIds.get(i).equals(orgId)) {
                        post.setOrganizeId(organizeIds.get(i));
                        post.setOrganizeName(organizeNames.get(i));
                        post.setPositionId(item.getPositionId());
                        post.setPositionName(item.getPositionName());
                        post.setPositionGradesName(item.getGradeName());
                        post.setPositionGradesId(item.getGradeId());
                        post.setUserId(item.getId());
                        list.add(post);
                    }
                }
            });
        }
        return list;
    }


    @Override
    public PageListVO<FtbCultivatePromotionPostApplyVO> getList(FtbCultivatePromotionPostApplyDto dto, CultivatePage cultivatePage) {
        Page<FtbCultivatePromotionPostApplyVO> page = cultivatePage.coverCultivatePage();
        //查询当前申请列表
        UserInfo user = UserProvider.getUser();
        String userId = user.getUserId();
        dto.setUserId(userId);
        Page<FtbCultivatePromotionPostApplyVO> mapperList = baseMapper.getListInfo(page, dto);
        //根据对应的人岗位获取对应的不同 晋升岗位通道
        mapperList.getRecords().forEach(item -> {
            // 当前岗位的id 反查询对应的晋升通道id
            String postId = item.getPostId();
            LambdaQueryChainWrapper<FtbCultivatePromotionPost> lambdaQuery = postService.lambdaQuery();
            lambdaQuery.eq(FtbCultivatePromotionPost::getPostId, postId);
            // 根据岗位确定该岗位启用的晋升通道
            List<String> promotionIds = lambdaQuery.list().stream().map(FtbCultivatePromotionPost::getPromotionId).collect(Collectors.toList());
            item.setChannelCount(promotionIds.size());
            if (CollUtil.isNotEmpty(promotionIds)) {
                //获取对应的查询信息
                List<FtbCultivatePromotionVO> promotionVOList = promotionService.queryListByIds(promotionIds);
                item.setChannelInfos(promotionVOList);
            }
        });
        return CultivatePage.coverPageList(mapperList);
    }

    @Override
    @Transactional(rollbackFor = {Exception.class, RuntimeException.class})
    public void auditPromotionPostApplication(FtbCultivatePromotionPostApplyDto dto) {
        if (dto.getState().equals(2) && !ObjectUtil.isNotEmpty(dto.getReviewComment())) {
            throw new RuntimeException("请填写审核意见!");
        }
        FtbCultivatePromotionPostApply postApply = this.getById(dto.getApplyId());
        if (ObjectUtil.isNull(postApply)) {
            throw new RuntimeException("该申请不存在!");
        }
        UserInfo user = UserProvider.getUser();
        String userId = user.getUserId();
        if (!userId.equals(postApply.getReviewUserId())) {
            throw new RuntimeException("当前指定审批人与登录用户不合符,无法审核该岗位晋升申请!");
        }
        LambdaUpdateWrapper<FtbCultivatePromotionPostApply> wrapper = Wrappers.lambdaUpdate();
        //审核评语
        wrapper.set(FtbCultivatePromotionPostApply::getReviewComment, dto.getReviewComment());
        wrapper.set(FtbCultivatePromotionPostApply::getState, dto.getState());
        wrapper.eq(FtbCultivatePromotionPostApply::getId, dto.getApplyId());
        int update = baseMapper.update(new FtbCultivatePromotionPostApply(), wrapper);
        if (update == 0) {
            throw new RuntimeException("审核失败!");
        }
        // 申请组织接口额变更
        // 记录通过时间和历史岗位职等及对应的在岗时长，
        // 同步至员工主页的用户成长板块
        // （相关功能模块：人事入转调离，若本需求上线时人事未上线，
        // 则将晋升申请放置在培训板块；待人事入转调离上线后再进行迁移
        if (dto.getState().equals(1)) {
            LambdaQueryWrapper<FtbCultivatePromotionPostApply> lambdaQuery = Wrappers.lambdaQuery();
            lambdaQuery.eq(FtbCultivatePromotionPostApply::getId, dto.getApplyId());
            FtbCultivatePromotionPostApply promotionPostApply = baseMapper.selectOne(lambdaQuery);
            // 当前岗位职等
            String postRankId = promotionPostApply.getPostRankId();
            // 晋升岗位职等
            String postRankPromotionId = promotionPostApply.getPostRankPromotionId();
            // 变更用户id
            String userId1 = promotionPostApply.getUserId();
            String orgId = postApply.getOrgId();
            String orgCurrentId = postApply.getOrgCurrentId();
            // 晋升通过后，变更当前人员岗位职等，
//            userApiV2Util.updateUserBoundInfo(userId1, new UserBoundInfoDTO(orgCurrentId, postRankPromotionId));
            Boolean b = userApi.changeUserPosition(userId1, postRankId, postRankPromotionId, orgId, orgCurrentId);
            if (!b) {
                throw new RuntimeException("审核变更岗位失败!");
            }
        }
    }

    @Override
    public FtbCultivatePromotionPostApplyWithPerVO viewPromotionApplications(FtbCultivatePromotionPostApplyDto dto, String appFlag) {
        LambdaQueryWrapper<FtbCultivatePromotionPostApply> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(FtbCultivatePromotionPostApply::getId, dto.getApplyId());
        FtbCultivatePromotionPostApply postApply = baseMapper.selectOne(wrapper);
        FtbCultivatePromotionPostApplyWithPerVO withPerVO = FtbCultivatePromotionPostApplyWithPerVO.coverFtbCultivatePromotionPostApplyWithPerVO(postApply);
        // 查询当前申请时上传的文件信息
        LambdaQueryWrapper<FtbCultivateFile> wrapperFile = Wrappers.lambdaQuery();
        wrapperFile.eq(FtbCultivateFile::getBusinessId, postApply.getId());
        LambdaQueryChainWrapper<FtbCultivateFile> fileLambdaQueryChainWrapper = ftbCultivateFileService.lambdaQuery();
        fileLambdaQueryChainWrapper.eq(FtbCultivateFile::getBusinessId, postApply.getId());
        List<FtbCultivateFile> fileLists = ftbCultivateFileService.list(wrapperFile);
        List<FtbCultivateOfflineFileVO> fileVOS = fileLists.stream()
                .map(FtbCultivateOfflineFileVO::convertFtbCultivateOfflineFileVO).collect(Collectors.toList());
        withPerVO.setFiles(fileVOS);
        if (appFlag.equals("1")) {
            return withPerVO;
        }
        String userId = withPerVO.getUserId();
        // 考试成绩列表
        List<UserExamDetailVo> userExamDetailVos = ftbCultivateExamUserService.queryCompleteExamListForUserId(userId);
        withPerVO.setAListOfTestScores(userExamDetailVos);
        // 实操鉴定列表
        LambdaQueryWrapper<FtbCultivatePositionIdentifyResult> wrapperIdentify = Wrappers.lambdaQuery();
        wrapperIdentify.select(FtbCultivatePositionIdentifyResult::getIdentifyRecordId);
        wrapperIdentify.eq(FtbCultivatePositionIdentifyResult::getUserId, userId);
        wrapperIdentify.eq(FtbCultivatePositionIdentifyResult::getPostRankId, postApply.getPostRankId());
        List<FtbCultivatePositionIdentifyResult> identifyResultList = ftbCultivatePositionIdentifyResultMapper.selectList(wrapperIdentify);
        List<String> identifyRecordIds = identifyResultList.stream().map(FtbCultivatePositionIdentifyResult::getIdentifyRecordId).distinct().collect(Collectors.toList());
        List<IdentifyApplyInfoApiVo> userIdentifyInfoApi = new ArrayList<>();
        if (CollUtil.isNotEmpty(identifyRecordIds)) {
            userIdentifyInfoApi = cultivateIdentifyApplyService.getUserIdentifyInfoApi(identifyRecordIds);
        }
        withPerVO.setListOfPracticalQualifications(userIdentifyInfoApi);
        // 已学习课程列表
        // 当前申请人id
        List<PromotionChannelLearnCourseVO> promotionChannelLearnCourseVOS = ftbCultivateCourseService.promotionPathwayCourses(userId);
        withPerVO.setHaveStudyCourseLists(promotionChannelLearnCourseVOS);
        return withPerVO;
    }

    @Override
    public Boolean isThereAnAppForThePosLevel(String postId, String grandId, String userId) {
        LambdaQueryWrapper<FtbCultivatePromotionPostApply> lambdaQuery = Wrappers.lambdaQuery();
        lambdaQuery.eq(FtbCultivatePromotionPostApply::getUserId, userId);
        lambdaQuery.eq(FtbCultivatePromotionPostApply::getPostId, postId);
        lambdaQuery.eq(FtbCultivatePromotionPostApply::getPostRankId, grandId);
        lambdaQuery.eq(FtbCultivatePromotionPostApply::getState, 0);
        List<FtbCultivatePromotionPostApply> ftbCultivatePromotionPostApplies = baseMapper.selectList(lambdaQuery);
        return !CollUtil.isNotEmpty(ftbCultivatePromotionPostApplies);
    }
}
