package com.ruoyi.project.business.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.importExcel.excel.helper.BasicTableInfoHelper;
import com.ruoyi.common.importExcel.excel.tempInfo.TrainQuestionHelper;
import com.ruoyi.common.importExcel.utils.ExcelUtils;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.PageUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.project.business.domain.dto.TtQuestionDatabaseDto;
import com.ruoyi.project.business.domain.train.TtQuestionDatabase;
import com.ruoyi.project.business.domain.vo.train.QuestionDatabaseReq;
import com.ruoyi.project.business.domain.vo.train.QuestionDatabaseRes;
import com.ruoyi.project.business.enums.train.TrainQuestionStatusEnum;
import com.ruoyi.project.business.enums.train.TrainQuestionTypeEnum;
import com.ruoyi.project.business.enums.train.TrainStatusEnum;
import com.ruoyi.project.business.mapper.TtQuestionDatabaseMapper;
import com.ruoyi.project.business.service.train.ITtQuestionDatabaseService;
import com.ruoyi.project.system.domain.SysDictData;
import com.ruoyi.project.system.domain.SysUser;
import com.ruoyi.project.system.mapper.SysDictDataMapper;
import com.ruoyi.project.system.service.ISysUserService;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static net.sf.jsqlparser.parser.feature.Feature.valuesList;

/**
 * @author fangk
 * @description 针对表【tt_question_database】的数据库操作Service实现
 * @createDate 2024-05-20 15:28:25
 */
@Service
@RequiredArgsConstructor
public class TtQuestionDatabaseServiceImpl extends ServiceImpl<TtQuestionDatabaseMapper, TtQuestionDatabase>
        implements ITtQuestionDatabaseService {

    private final ISysUserService sysUserService;

    private final SysDictDataMapper sysDictDataMapper;

    @Autowired
    private ITtQuestionDatabaseService ttQuestionDatabaseService;

    @Override
    public List<QuestionDatabaseRes> list(QuestionDatabaseReq req) {
        LambdaQueryWrapper<TtQuestionDatabase> wrapper = Wrappers.lambdaQuery(TtQuestionDatabase.class)
                .like(StringUtils.isNotBlank(req.getQuestionContext()), TtQuestionDatabase::getQuestionContext, req.getQuestionContext())
                // .eq(StringUtils.isNotBlank(req.getQuestionType()), TtQuestionDatabase::getQuestionType, req.getQuestionType())
                // .eq(null != req.getScore(), TtQuestionDatabase::getScore, req.getScore())
                // .eq(StringUtils.isNotBlank(req.getCorrectAnswer()), TtQuestionDatabase::getCorrectAnswer, req.getCorrectAnswer())
                .in(CollectionUtils.isNotEmpty(req.getQuestionTypes()), TtQuestionDatabase::getQuestionType, req.getQuestionTypes())
                .between(null != req.getCtStart() && null != req.getCtEnd(), TtQuestionDatabase::getCreateTime, req.getCtStart(), req.getCtEnd())
                .between(null != req.getUtStart() && null != req.getUtEnd(), TtQuestionDatabase::getUpdateTime, req.getUtStart(), req.getUtEnd())
                .eq(StringUtils.isNotBlank(req.getStatus()), TtQuestionDatabase::getStatus, req.getStatus());
        List<TtQuestionDatabase> list = list(wrapper);
        if (list.isEmpty()) {
            return Collections.emptyList();
        }

        List<Long> userIds = Stream.concat(list.stream().map(TtQuestionDatabase::getCreateBy), list.stream().map(TtQuestionDatabase::getUpdateBy))
                .filter(Objects::nonNull)
                .distinct()
                .map(Long::valueOf)
                .collect(Collectors.toList());

        Map<Long, String> userId2NameMapping = sysUserService.listByIds(userIds)
                .stream()
                .collect(Collectors.toMap(SysUser::getUserId, SysUser::getNickName));


        List<QuestionDatabaseRes> collect = list.stream().map(QuestionDatabaseRes::from).peek(res -> {
            res.setCreateByName(userId2NameMapping.get(res.getCreateBy()));
            res.setUpdateByName(userId2NameMapping.get(res.getUpdateBy()));
        }).collect(Collectors.toList());
        return PageUtils.copyPageIfPresent(list, collect);
    }

    @Override
    public ExcelUtils.UploadResult<TrainQuestionHelper> checkQuestionInfo(BasicTableInfoHelper basicTableInfoHelper, List<TrainQuestionHelper> list) {
        if (list.size() > 1) {
            for (int i = 1; i < list.size(); i++) {
                if (Objects.equals(list.get(0).getQuestionContext(), list.get(i).getQuestionContext())) {
                    throw new ServiceException(MessageUtils.message("train.question.repeat"));
                }
            }
        }
        QueryWrapper<TtQuestionDatabase> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("del_flag", 0);
        List<TtQuestionDatabase> allQuestions = ttQuestionDatabaseService.list(queryWrapper);
        return ExcelUtils.checkData(list, item -> {
            List<String> businessErrors = Lists.newArrayList();
            // 保证数据库中不存在，新增的题目(不对题目重复做判断)
//            allQuestions.stream().filter(ques -> Objects.equals(ques.getQuestionContext(), item.getQuestionContext())).findFirst().ifPresent(item1 -> businessErrors.add(MessageUtils.message("train.question.repeat")));

            //检验测试名称是否超过500
            // 校验必填项是否必填
            if (StringUtils.isBlank(item.getQuestionContext())) {
                businessErrors.add(MessageUtils.message("train.question.questionContext.required"));
            }else {
                if (item.getQuestionContext().length() > 500) {
                    businessErrors.add(MessageUtils.message("train.question.questionContext.tolong"));
                }
            }

            // 校验必填项是否必填
            if (StringUtils.isBlank(item.getCorrectAnswer())) {
                businessErrors.add(MessageUtils.message("train.question.answer.required"));
            }else {
                if (item.getCorrectAnswer().length() > 500) {
                    businessErrors.add(MessageUtils.message("train.question.answer.tolong"));
                }
            }

            if (StringUtils.isBlank(item.getQuestionType())) {
                businessErrors.add(MessageUtils.message("train.question.questionType.required"));
            }


            // 保证分值都为整数
            try {
                // 如果分数不为null，则判断是否为整数
                if (StringUtils.isBlank(item.getScore())) {
                    businessErrors.add(MessageUtils.message("train.question.score.required"));
                }else{
                    int score = Integer.parseInt(item.getScore());
                    if (score < 0 || score > 100) {
                        businessErrors.add(MessageUtils.message("train.question.score.scoreRange"));
                    }
                }
            } catch (NumberFormatException e) {
                businessErrors.add(MessageUtils.message("train.question.scoreError"));
            }
            // 保证多选题答案，为 ; 分割的多个选项，且选项中包含正确答案
            try {
                // 所有选项数组
                String[] values = new String[10];
                for (int j = 1; j <= 10; j++) {
                    // 如果为填空题，则不做判断
                    if(StringUtils.isBlank(item.getQuestionType())){
                        break;
                    }
                    if (item.getQuestionType().equals(TrainQuestionTypeEnum.content.getMsg())) {
                        break;
                    }
                    Field field = item.getClass().getDeclaredField("option" + j);
                    field.setAccessible(true);
                    Object value = field.get(item);
                    if (value != null) {
                        values[j - 1] = String.valueOf(value);
                    }
                }
                if(ArrayUtils.isEmpty(values)){
                    businessErrors.add(MessageUtils.message("train.question.answer.required"));
                }
                // 正确答案数组
                if (StringUtils.isBlank(item.getCorrectAnswer())) {
                    businessErrors.add(MessageUtils.message("train.question.correctAnswer.required"));
                }else{
                    String[] split = item.getCorrectAnswer().split(";");
                    // 判断正确答案，是否为选项中包含的选项
                    if (!new HashSet<>(Arrays.asList(values)).containsAll(Arrays.asList(split)) && !item.getQuestionType().equals(TrainQuestionTypeEnum.content.getMsg())) {
                        businessErrors.add(MessageUtils.message("train.question.correctError"));
                    }
                }
            } catch (NoSuchFieldException | IllegalAccessException e) {
                e.printStackTrace();
            }
            return businessErrors;
        });
    }

    /**
     * 批量插入培训试题导入数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<TtQuestionDatabase> insertQuestionExcel(BasicTableInfoHelper basicTableInfoHelper, List<TrainQuestionHelper> list) {
        List<String> errorMessages = new ArrayList<>();
        List<SysDictData> typeList = sysDictDataMapper.selectDictDataByType("train_question_type");

        List<TtQuestionDatabase> tQuesList = new ArrayList<>();
        for (TrainQuestionHelper ques : list) {
            TtQuestionDatabase tq = new TtQuestionDatabase();
            tq.setScore(Integer.parseInt(ques.getScore()));
            tq.setStatus(TrainQuestionStatusEnum.ENABLE.getCode());
            BeanUtils.copyProperties(ques, tq);
            // 处理字典 试题类型
            typeList.stream().filter(item -> Objects.equals(item.getDictLabel(), ques.getQuestionType())).findFirst().ifPresent(type -> tq.setQuestionType(type.getDictValue()));

            tq.setCreateBy(SecurityUtils.getUserId().toString());
            tq.setCreateTime(DateUtils.getNowDate());
            tQuesList.add(tq);
        }
        int result = baseMapper.batchInsertTcQuestion(tQuesList);

        return tQuesList;
    }

    @Override
    public List<TtQuestionDatabase> selectRandomQuestionList(Integer num) {
        List<TtQuestionDatabase> ttQuestionDatabases = baseMapper.selectRandomQuestionList(num);
        return ttQuestionDatabases;
    }

    @Override
    public List<TtQuestionDatabase> selectRandomQuestionListByNum(List<TtQuestionDatabaseDto> ttQuestionDatabaseDtos) {
        List<TtQuestionDatabase> ttQuestionDatabases = new ArrayList<>();
        for (TtQuestionDatabaseDto question : ttQuestionDatabaseDtos) {
            // 题型
            ttQuestionDatabases.addAll(baseMapper.selectRandomQuestionListByNum(question));
        }

        return ttQuestionDatabases;
    }
}




