package jnpf.cultivate.utils;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import com.google.common.collect.ImmutableMap;
import jnpf.base.UserInfo;
import jnpf.cultivate.service.*;
import jnpf.database.util.TenantDataSourceUtil;
import jnpf.exception.LoginException;
import jnpf.model.cultivate.event.JnpfApplicationEvent;
import jnpf.model.cultivate.event.dto.certificate.CertificateEventDTO;
import jnpf.model.cultivate.po.exam.FtbCultivateExam;
import jnpf.model.cultivate.po.exam.FtbCultivateExamHistoryPaper;
import jnpf.model.cultivate.po.exam.FtbCultivateExamUser;
import jnpf.model.cultivate.po.learn.FtbCultivateLearnTaskIdentification;
import jnpf.model.cultivate.po.paper.FtbCultivateTestPaper;
import jnpf.model.cultivate.po.paper.FtbCultivateTestPaperQuestion;
import jnpf.model.cultivate.po.question.FtbCultivateQuestion;
import jnpf.model.cultivate.req.paper.PaperConfigReq;
import jnpf.model.cultivate.resp.*;
import jnpf.model.enums.CourseEnums;
import jnpf.model.personnels.dto.staff.roster.WorkerGroupDataDto;
import jnpf.model.personnels.po.FtbPersonnelsStaffRoster;
import jnpf.permission.PositionApi;
import jnpf.permission.vo.v2.position.PositionVO;
import jnpf.permission.vo.v2.user.UserBoundVO;
import jnpf.personnels.service.FtbPersonnelsStaffRosterService;
import jnpf.util.Constants;
import jnpf.util.StringUtil;
import jnpf.util.UserProvider;
import jnpf.util.context.SpringContext;
import jnpf.util.data.DataSourceContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

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

@Component
@Slf4j
public class UserExamUtil {
    /**
     * 考试服务（试卷）
     */
    @Autowired
    private FtbCultivateExamHistoryPaperService examHistoryPaperService;

    @Autowired
    private FtbCultivateExamService examService;

    @Autowired
    private FtbCultivateQuestionService questionService;

    @Autowired
    private FtbPersonnelsStaffRosterService rosterService;


    @Autowired
    private FtbCultivateTestPaperService paperService;

    @Autowired
    private FtbCultivateExamUserService examUserService;


    @Autowired
    private FtbCultivateTestPaperService testPaperService;

    @Autowired
    private CultivateIdentifyApplyService cultivateIdentifyApplyService;

    @Autowired
    private FtbCultivateLearnTaskIdentificationService taskIdentificationService;

    @Autowired
    private UserApiV2Util userApiV2Util;

    /**
     * @param userIds 用户id集合
     * @return user->roster的map
     */
    public Map<String, FtbPersonnelsStaffRoster> queryRosterSimpleInfo(List<String> userIds) {
        if (CollectionUtil.isEmpty(userIds)) {
            return new HashMap<>();
        }
        List<FtbPersonnelsStaffRoster> rosterList = rosterService.queryWorkerIdByUserIds(userIds);
        if (CollectionUtil.isEmpty(rosterList)) {
            return new HashMap<>();
        }
        return rosterList.stream().collect(Collectors.toMap(FtbPersonnelsStaffRoster::getUserId, roster -> roster));
    }

    /**
     * 查询并检查考试信息
     *
     * @param exam         考试信息
     * @param versionBatch 批次
     * @return
     */
    public FtbCultivateExam checkAndUpdateExam(FtbCultivateExam exam, String versionBatch) {
        if (versionBatch.equals(exam.getVersionBatch())) {
            return exam;
        }
        FtbCultivateExamHistoryPaper ftbCultivateExamHistoryPaper = examHistoryPaperService.queryByEamIdAndVersionBatch(exam.getId(), versionBatch);
        if (null == ftbCultivateExamHistoryPaper) {
            return exam;
        }
        return HistoryPaperUtils.converToExam(ftbCultivateExamHistoryPaper);
    }

    public void publishExam(String userId, String positionId, Integer issuanceType, String courseId) {
        log.info("考试成功颁发证书，userId={},positionId={}", userId, positionId);
        SpringContext.getApplicationContext()
                .publishEvent(new JnpfApplicationEvent<>(
                        CertificateEventDTO.builder()
                                .source(1)
                                .postId(positionId)
                                .courseId(courseId)
//                                .issuanceType(1)
                                .issuanceType(issuanceType)
                                .userId(userId).build()));
    }

    /**
     * 考试完成回调
     *
     * @param userId     用户ID
     * @param positionId 岗位id
     * @param status     用户考试合格状态
     * @return 0-不需要提醒  1-需要提醒
     */
    public Integer publishExamCallBack(String userId, String positionId, Integer status) {
        log.info("考试完成回调，userId={},positionId={},status={}", userId, positionId, status);
        //查询是否配置了考试完成才能鉴定
        Integer flag = examService.queryExamAndIdentifyConfig(positionId);
        log.info("queryExamAndIdentifyConfig={},flag={}", positionId, flag);
        if (flag == 1) {
            if (status.equals(CourseEnums.ExamStatus.PASS.getCode()) || status.equals(CourseEnums.ExamStatus.VERY_PASS.getCode())) {
                cultivateIdentifyApplyService.turnOnVisibility(positionId, userId);
            }
        } else {
            cultivateIdentifyApplyService.turnOnVisibility(positionId, userId);
        }
        return flag;

    }

    /**
     * 任务考试完成回调
     *
     * @param userId 用户id
     * @param taskId 任务id
     * @param status 考试状态
     * @return
     */
    public Integer publishTaskExamCallBack(String userId, String taskId, Integer status) {
        log.error("task考试完成回调，userId={},taskId={},status={}", userId, taskId, status);
        //查询是否配置了考试完成才能鉴定
        FtbCultivateLearnTaskIdentification ftbCultivateLearnTaskIdentification = taskIdentificationService.queryByTaskId(taskId);
        Integer flag = 0;
        if (ftbCultivateLearnTaskIdentification != null && ftbCultivateLearnTaskIdentification.getIdentificationRule().equals(1)) {
            flag = 1;
        }
        if (flag.equals(1)) {
            if (status.equals(CourseEnums.ExamStatus.PASS.getCode()) || status.equals(CourseEnums.ExamStatus.VERY_PASS.getCode())) {
                cultivateIdentifyApplyService.turnOnVisibilityWithTaskId(taskId, userId, status);
            }
        } else {
            cultivateIdentifyApplyService.turnOnVisibilityWithTaskId(taskId, userId, status);
        }
        return flag;

    }

    public Map<String, String> getHeadersForLogin() {
        UserInfo userInfo = UserProvider.getUser();
        String token = userInfo.getToken();
        if (StringUtils.isEmpty(token)) {
            token = "";
        }
        Map<String, String> headers = ImmutableMap.of(Constants.AUTHORIZATION.toLowerCase(), token);
        return headers;
    }

    /**
     * 获取租户id
     * @return tenantId
     */
    public String getTenantId() {
        UserInfo userInfo = UserProvider.getUser();
        return userInfo.getTenantId();
    }

    /**
     * 对应字符串list去重复
     *
     * @param list 字符串id集合
     * @return 去重复的id集合
     */
    public List<String> uniqueStringList(List<String> list) {
        if (CollectionUtil.isEmpty(list)) {
            return new ArrayList<>();
        }
        return list.stream()
                .filter(Objects::nonNull) // 过滤掉 null 值
                .filter(str -> !str.isEmpty()) // 过滤掉空字符串
                .distinct() // 去重
                .collect(Collectors.toList()); // 收集为 List
    }

    public List<FtbCultivateQuestion> queryHalfFullQuestionList(List<ExamQuestionBakVo> questionList) {
        if (CollectionUtil.isEmpty(questionList)) {
            return new ArrayList<>();
        }
        List<String> questionIds = questionList.stream().map(ExamQuestionBakVo::getQuestionId).collect(Collectors.toList());
        List<FtbCultivateQuestion> list = questionService.listByIds(questionIds);
        return list;
    }

    public Map<String, List<WorkerGroupDataDto>> getUserOrgBoundInfoForUserList(List<String> examUserList) {
        Map<String, UserBoundVO> map = userApiV2Util.getUserPrimaryBoundBatch(examUserList, null);
        if (CollectionUtil.isEmpty(map)) {
            return new HashMap<>();
        }
        Map<String, List<WorkerGroupDataDto>> retMap = new HashMap<>();
        for (Map.Entry<String, UserBoundVO> entry : map.entrySet()) {
            String userId = entry.getKey(); // 用户ID
            UserBoundVO vo = entry.getValue(); // 获取值列表
            List<WorkerGroupDataDto> workerGroupDataDtoList = new ArrayList<>();
            if (vo !=null) {
                WorkerGroupDataDto dto = new WorkerGroupDataDto();
                dto.setIsDefault(true);
                dto.setReportsTo(vo.getLeaderId());
                dto.setAffiliatedOrg(vo.getOrganizeId());
                dto.setAffiliatedOrgName(vo.getOrganizeName());
                dto.setAffiliatedPosition(vo.getPositionId());
                dto.setAffiliatedPositionName(vo.getPositionName());
                dto.setAffiliatedRank(vo.getGradeId());
                dto.setAffiliatedRankName(vo.getGradeName());
                dto.setOrgEncode(vo.getOrganizeEnCode());
                dto.setPositionEncode(vo.getPositionEnCode());
                dto.setIsDefaultOrganize(true);
                dto.setIsDefaultPosition(true);
                dto.setIsPrimaryPosition(true);
                workerGroupDataDtoList.add(dto);
            }
            retMap.put(userId, workerGroupDataDtoList);
        }
        return retMap;
    }

    /**
     * 是否有直属主管
     *
     * @param workerGroupDataDtoList
     * @return true-有  false-没有
     */
    public boolean checkIsHasReporter(List<WorkerGroupDataDto> workerGroupDataDtoList) {
        for (WorkerGroupDataDto workerGroupDataDto : workerGroupDataDtoList) {
            if (StringUtils.isNotEmpty(workerGroupDataDto.getReportsTo())) {
                return true;
            }
        }
        return false;
    }

    public List<WebReadOverExamAndPaperDetailVo> convertWebReadOverExamAndPaperDetailVoForHistory(List<FtbCultivateExamHistoryPaper> historyList) {
        if (CollectionUtil.isEmpty(historyList)) {
            return new ArrayList<>();
        }
        List<WebReadOverExamAndPaperDetailVo> retList = new ArrayList<>();
        for (FtbCultivateExamHistoryPaper exam : historyList) {
            WebReadOverExamAndPaperDetailVo vo = new WebReadOverExamAndPaperDetailVo();
            vo.setId(exam.getPrimaryExamId());
            vo.setExamName(exam.getExamName());
            vo.setExamType(exam.getExamType());
            vo.setExamId(exam.getExamId());
            vo.setStartTime(exam.getStartTime());
            vo.setEndTime(exam.getEndTime());
            vo.setPaperId(exam.getPaperId());
            vo.setExamlimitation(exam.getExamlimitation());
            vo.setExamTime(exam.getExamTime());
            vo.setPassMark(exam.getPassMark());
            vo.setPassType(exam.getPassType());
            vo.setExcellentMark(exam.getExcellentMark());
            vo.setExcellentType(exam.getExcellentType());
            vo.setDescription(exam.getDescription());
            vo.setCurrQuestionNumber(exam.getCurrQuestionNumber());
            vo.setCurrTotalScore(exam.getCurrTotalScore());
            vo.setVersionBatch(exam.getVersionBatch());
            if (StringUtils.isNotEmpty(exam.getPaperInfo())) {
                //
                FtbCultivateTestPaper paper = JSONUtil.toBean(exam.getPaperInfo(), FtbCultivateTestPaper.class);
                vo.setPaperVo(convertToPaperVo(paper));
            } else {
                FtbCultivateTestPaper paper = paperService.getById(exam.getPaperId());
                vo.setPaperVo(convertToPaperVo(paper));
            }

            if (StringUtils.isNotEmpty(exam.getPostId())) {
                // 将字符串数组转换为List
                List<String> postionIds = Arrays.asList(exam.getPostId().split(","));
                List<PositionVO> positionEntities = userApiV2Util.listPositionDetailInfoByIds(postionIds, null);
//                List<PositionEntity> positionEntities = personnelOrgUtils.queryPostionInfoForIds(postionIds);
                vo.setPostAndPositionList(convertPostAndPositionList(positionEntities));
            }
            retList.add(vo);
        }

        return retList;

    }

    /**
     * 数据转换
     *
     * @param exam 考试
     * @return
     */
    public WebReadOverExamAndPaperDetailVo convertToWebReadOverExamAndPaperDetailVo(FtbCultivateExam exam) {
        WebReadOverExamAndPaperDetailVo vo = new WebReadOverExamAndPaperDetailVo();
        vo.setId(exam.getId());
        vo.setExamName(exam.getExamName());
        vo.setExamType(exam.getExamType());
        vo.setExamId(exam.getExamId());
        vo.setStartTime(exam.getStartTime());
        vo.setEndTime(exam.getEndTime());
        vo.setPaperId(exam.getPaperId());
        vo.setExamlimitation(exam.getExamlimitation());
        vo.setExamTime(exam.getExamTime());
        vo.setPassMark(exam.getPassMark());
        vo.setPassType(exam.getPassType());
        vo.setExcellentMark(exam.getExcellentMark());
        vo.setExcellentType(exam.getExcellentType());
        vo.setDescription(exam.getDescription());
        vo.setCurrQuestionNumber(exam.getCurrQuestionNumber());
        vo.setCurrTotalScore(exam.getCurrTotalScore());
        vo.setVersionBatch(exam.getVersionBatch());
        if (StringUtils.isNotEmpty(exam.getPaperInfo())) {
            //
            FtbCultivateTestPaper paper = JSONUtil.toBean(exam.getPaperInfo(), FtbCultivateTestPaper.class);
            vo.setPaperVo(convertToPaperVo(paper));
        } else {
            FtbCultivateTestPaper paper = paperService.getById(exam.getPaperId());
            vo.setPaperVo(convertToPaperVo(paper));
        }

        if (StringUtils.isNotEmpty(exam.getPostId())) {
            // 将字符串数组转换为List
            List<String> postionIds = Arrays.asList(exam.getPostId().split(","));
//            List<PositionEntity> positionEntities = personnelOrgUtils.queryPostionInfoForIds(postionIds);
            List<PositionVO> positionEntities = userApiV2Util.listPositionDetailInfoByIds(postionIds, null);
            vo.setPostAndPositionList(convertPostAndPositionList(positionEntities));
        }
        return vo;

    }

    private PaperVo convertToPaperVo(FtbCultivateTestPaper paper) {
        if (null == paper) {
            return null;
        }
       return BeanUtil.copyProperties(paper, PaperVo.class);
    }

    private List<PostAndPosition> convertPostAndPositionList(List<PositionVO> positionEntities) {
        List<PostAndPosition> list = new ArrayList<>();
        for (PositionVO positionEntity : positionEntities) {
            PostAndPosition postAndPosition = new PostAndPosition();
            postAndPosition.setEnCode(positionEntity.getEnCode());
            postAndPosition.setId(positionEntity.getId());
            postAndPosition.setPostName(positionEntity.getFullName());

            list.add(postAndPosition);
        }
        return list;
    }


    public FtbCultivateExam queryExamByIdAndBatch(String examId, String versionBatch) {
        FtbCultivateExam exam = examService.getById(examId);
        if (null != exam && exam.getVersionBatch().equals(versionBatch)) {
            return exam;
        }
        FtbCultivateExamHistoryPaper ftbCultivateExamHistoryPaper = examHistoryPaperService.queryByEamIdAndVersionBatch(examId, versionBatch);
        if (null == ftbCultivateExamHistoryPaper) {
            return null;
        }
        return HistoryPaperUtils.converToExam(ftbCultivateExamHistoryPaper);
    }

    public void updateUserExamNullify(String userExamId) {
        FtbCultivateExamUser entity = new FtbCultivateExamUser();
        entity.setId(userExamId);
        entity.setAppShow(1);
        entity.setIsJoinCount(1);
        examUserService.updateById(entity);
    }

    public GeneralPaperQuestionVo randomQuestion(FtbCultivateExam exam) {
        GeneralPaperQuestionVo vo = new GeneralPaperQuestionVo();
        List<ExamQuestionBakVo> oldQuestion = HistoryPaperUtils.convertQuestionList(exam.getCurrQuestionList());
        if (StringUtils.isEmpty(exam.getPaperInfo())) {
            return vo;
        }
        FtbCultivateTestPaper paper = JSONUtil.toBean(exam.getPaperInfo(), FtbCultivateTestPaper.class);
        if (StringUtils.isEmpty(paper.getPaperConfig())) {
            return vo;
        }

        PaperConfigReq configReq = JSONUtil.toBean(paper.getPaperConfig(), PaperConfigReq.class);
        final Map<String, Map<String, PaperConfigReq.QuestionNum>> questionConfig = configReq.getQuestionConfig();
        final Map<String, PaperConfigReq.QuestionScore> scoreConfig = configReq.getScoreConfig();
        if (CollectionUtil.isEmpty(questionConfig) || CollectionUtil.isEmpty(scoreConfig)) {
            return vo;
        }

        // 根据题库ID 查询题目列表
        List<String> questionBankIdList = new ArrayList<>(questionConfig.keySet());
        if (CollectionUtil.isEmpty(questionBankIdList)) {
            return vo;
        }
        Map<String, List<FtbCultivateQuestion>> questionMap = testPaperService.BatchQueryQuestionForQuestionBankIds(questionBankIdList);
        if (CollectionUtil.isEmpty(questionMap)) {
            return vo;
        }

        List<FtbCultivateTestPaperQuestion> randomList = new ArrayList<>();
        for (Map.Entry<String, List<FtbCultivateQuestion>> entry : questionMap.entrySet()) {
            String questionBankId = entry.getKey();
            List<FtbCultivateQuestion> questionList = entry.getValue();
            //获取该题库题型对应的题目列表 Map
            Map<String, List<FtbCultivateQuestion>> questionTypeMap = questionList.stream()
                    .collect(Collectors.groupingBy(ftbCultivateQuestion -> String.valueOf(ftbCultivateQuestion.getType())));
            //获取该题库随机选题的配置
            Map<String, PaperConfigReq.QuestionNum> questionNumMap = questionConfig.get(questionBankId);
            //随机选题
            questionNumMap.forEach((questionType, questionNum) -> {
                //题型 的题目列表
                List<FtbCultivateQuestion> tempList = questionTypeMap.get(questionType);
                if (CollectionUtil.isEmpty(tempList)) {
                    return;
                }
                //题型难度列表
                Map<Integer, List<FtbCultivateQuestion>> difficultyMap = tempList.stream().collect(Collectors.groupingBy(FtbCultivateQuestion::getDifficulty));
                //简单
                Integer simpleNum = questionNum.getSimpleNum();
                List<FtbCultivateQuestion> simpleQuestion = difficultyMap.get(CourseEnums.QuestionDifficulty.EASY.getCode());
                //一般
                Integer generalNum = questionNum.getGeneralNum();
                List<FtbCultivateQuestion> generalQuestion = difficultyMap.get(CourseEnums.QuestionDifficulty.MIDDLE.getCode());
                //难
                Integer hardNum = questionNum.getHardNum();
                List<FtbCultivateQuestion> hardQuestion = difficultyMap.get(CourseEnums.QuestionDifficulty.MAX.getCode());
                randomList.addAll(randomGetQuestion(paper.getId(), simpleQuestion, simpleNum, scoreConfig.get(questionType).getSimpleScore()));
                randomList.addAll(randomGetQuestion(paper.getId(), generalQuestion, generalNum, scoreConfig.get(questionType).getGeneralScore()));
                randomList.addAll(randomGetQuestion(paper.getId(), hardQuestion, hardNum, scoreConfig.get(questionType).getHardSore()));
            });
        }

        if (oldQuestion.size() == randomList.size()) {
            vo.setSuccess(true);
            vo.setRandomList(BeanUtil.copyToList(randomList, ExamQuestionBakVo.class));
            List<String> questionIds = new ArrayList<>();
            for (FtbCultivateTestPaperQuestion paperQuestion : randomList) {
                questionIds.add(paperQuestion.getQuestionId());
            }
            List<FtbCultivateQuestion> selectQuestionList = questionService.listByIds(questionIds);
            vo.setQuestionList(selectQuestionList);
            return vo;
        }
        return vo;
    }

    private List<FtbCultivateTestPaperQuestion> randomGetQuestion(String paperId, List<FtbCultivateQuestion> questionList, Integer randomSize, Integer score) {
        if (CollectionUtil.isEmpty(questionList) || randomSize <= 0) {
            return new ArrayList<>();
        }
        List<FtbCultivateQuestion> random = new ArrayList<>();
        if (questionList.size() < randomSize) {
            random = questionList;
        } else {
            // 打乱列表
            Collections.shuffle(questionList);
            // 抽取样本
            random = questionList.subList(0, randomSize);
        }

        return random.stream().map(question -> {
            FtbCultivateTestPaperQuestion paperQuestion = new FtbCultivateTestPaperQuestion();
            paperQuestion.setPaperId(paperId);
            paperQuestion.setQuestionId(question.getId());
            paperQuestion.setBankId(question.getClassifyId());
            paperQuestion.setScore(score);
            paperQuestion.setEnabledMark(CourseEnums.EnabledMarkType.VALID.getCode());
            paperQuestion.setCreatorTime(new Date());
            return paperQuestion;
        }).collect(Collectors.toList());
    }

    public List<PositionVO> getPostInfoList(List<String> ids) {
        if (CollUtil.isEmpty(ids)) {
            return new ArrayList<>();
        }
        ids = ids.stream().distinct().collect(Collectors.toList());
//        List<PositionEntity> positionEntities = positionApi.getPositionName(ids);
        return userApiV2Util.listPositionDetailInfoByIds(ids, null);
    }

    /**
     * 获取当天的开始时间
     *
     * @return
     */
    public static Date getTodayStart() {
        return DateUtil.beginOfDay(DateUtil.date());
    }

    /**
     * 获取本周的开始时间
     *
     * @return
     */
    public static Date getWeekStart() {
        return DateUtil.beginOfWeek(DateUtil.date());
    }

    /**
     * 获取本月的开始时间
     *
     * @return
     */
    public static Date getMonthStart() {
        return DateUtil.beginOfMonth(DateUtil.date());
    }
}
