package com.seer.teach.admin.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.seer.teach.admin.convert.BankQuestionsConvert;
import com.seer.teach.admin.convert.KnowledgePointsConvert;
import com.seer.teach.admin.request.BankQuestionsBatchSaveReq;
import com.seer.teach.admin.request.BankQuestionsQueryReq;
import com.seer.teach.admin.request.BankQuestionsReq;
import com.seer.teach.admin.request.CheckAndScoreReq;
import com.seer.teach.admin.response.BankOptionsResp;
import com.seer.teach.admin.response.BankQuestionsResp;
import com.seer.teach.admin.response.KnowledgePointsResp;
import com.seer.teach.admin.service.AdminBankQuestionsService;
import com.seer.teach.common.enums.QuestionTypesEnums;
import com.seer.teach.common.enums.ResultCodeEnum;
import com.seer.teach.common.utils.AssertUtils;
import com.seer.teach.teacher.module.entity.BankOptionsEntity;
import com.seer.teach.teacher.module.entity.BankQuestionsEntity;
import com.seer.teach.teacher.module.entity.KnowledgePointEntity;
import com.seer.teach.teacher.module.entity.ModificationLogEntity;
import com.seer.teach.teacher.service.BankOptionsService;
import com.seer.teach.teacher.service.BankQuestionsService;
import com.seer.teach.teacher.service.KnowledgePointQueryService;
import com.seer.teach.teacher.service.MaterialService;
import com.seer.teach.teacher.util.ModificationLogUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 题库管理服务实现类
 * </p>
 *
 * @author Lingma
 * @since 2025-10-27
 */
@Slf4j
@Service
public class AdminBankQuestionsServiceImpl implements AdminBankQuestionsService {

    @Autowired
    private BankQuestionsService bankQuestionsService;

    @Autowired
    private  BankOptionsService bankOptionsService;

    @Autowired
    private  TransactionTemplate transactionTemplate;

    @Autowired
    private  MaterialService materialService;

    @Autowired
    private  KnowledgePointQueryService knowledgePointQueryService;

    private  BankQuestionsConvert bankQuestionsConvert = BankQuestionsConvert.INSTANCE;

    @Override
    public IPage<BankQuestionsResp> pageBankQuestions(BankQuestionsQueryReq req) {
        log.info("分页查询题库列表, 查询参数: {}", req);
        Page<BankQuestionsEntity> page = new Page<>(req.getPageNo(), req.getPageSize());
        LambdaQueryWrapper<BankQuestionsEntity> queryWrapper = new LambdaQueryWrapper<>();

        // 根据年级和科目查询知识点
        if (Objects.nonNull(req.getGradeId()) || Objects.nonNull(req.getSubjectId()) || Objects.nonNull(req.getVersionId())|| Objects.nonNull(req.getKnowName())  || Objects.nonNull(req.getKnowId()) || Objects.nonNull(req.getGradeType())) {
            Collection<Integer> knowIdList = knowledgePointQueryService.getKnowIdsByConditions(bankQuestionsConvert.req2KnowledgePointSearchParam(req));
            if (knowIdList.isEmpty()) {
                log.info("根据年级和学科筛选后无匹配的知识点，返回空结果");
                return new Page<>(req.getPageNo(), req.getPageSize());
            }
            queryWrapper.in(BankQuestionsEntity::getKnowId, knowIdList);
        }
        if (req.getKnowId() != null) {
            queryWrapper.eq(BankQuestionsEntity::getKnowId, req.getKnowId());
        }
        if (Objects.nonNull(req.getQuestionId())) {
            queryWrapper.eq(BankQuestionsEntity::getId, req.getQuestionId());
        }
        if (Objects.nonNull(req.getIsChecked())) {
            queryWrapper.eq(BankQuestionsEntity::getIsChecked, req.getIsChecked());
        }
        if (req.getType() != null) {
            queryWrapper.eq(BankQuestionsEntity::getType, req.getType());
        }
        if (Objects.nonNull(req.getStatus())) {
            queryWrapper.eq(BankQuestionsEntity::getStatus, req.getStatus());
        }
        if (req.getTitle() != null && !req.getTitle().isEmpty()) {
            queryWrapper.like(BankQuestionsEntity::getTitle, req.getTitle());
        }
        queryWrapper.orderByAsc(BankQuestionsEntity::getIsChecked).orderByDesc(BankQuestionsEntity::getCreateTime);
        IPage<BankQuestionsEntity> entityPage = bankQuestionsService.page(page, queryWrapper);
        log.info("分页查询题库列表成功, 查询到 {} 条记录", entityPage.getRecords().size());

        IPage<BankQuestionsResp> respPage = bankQuestionsConvert.toRespPage(entityPage);
        if (CollectionUtil.isEmpty(respPage.getRecords())) {
            return respPage;
        }
        List<BankQuestionsResp> respList = respPage.getRecords();
        Set<Integer> knowIds = respList.stream().map(BankQuestionsResp::getKnowId).collect(Collectors.toSet());
        if (CollectionUtil.isEmpty(knowIds)) {
            return respPage;
        }
        // 将知识点查询移至knowledgePointQueryService中
        List<KnowledgePointEntity> knowList = knowledgePointQueryService.getKnowledgePointListByKnowIds(knowIds).stream().collect(Collectors.toList());
        List<KnowledgePointsResp> knowledgePointsResps = KnowledgePointsConvert.INSTANCE.converEntity2RespList(knowList);
        Map<Integer, KnowledgePointsResp> knowMap = knowledgePointsResps.stream().collect(Collectors.toMap(KnowledgePointsResp::getId, Function.identity(), (k1, k2) -> k2));
        respList.forEach(resp -> {
            KnowledgePointsResp know = knowMap.get(resp.getKnowId());
            if (know != null) {
                resp.setKnow(know);
            }
        });
        return respPage;
    }

    @Override
    public BankQuestionsResp getBankQuestionById(Integer id) {
        log.info("根据ID查询题库详情, ID: {}", id);
        BankQuestionsEntity entity = bankQuestionsService.getById(id);
        if (Objects.nonNull(entity)) {
            return null;
        }
        BankQuestionsResp resp = bankQuestionsConvert.toResp(entity);
        // 如果是选择题类型，则获取选项列表
        if (isChoiceQuestion(entity.getType())) {
            List<BankOptionsEntity> options = bankOptionsService.list(new LambdaQueryWrapper<BankOptionsEntity>().eq(BankOptionsEntity::getQuestionId, id).orderByAsc(BankOptionsEntity::getSort));

            // 转换选项列表
            List<BankOptionsResp> optionsResps = options.stream().map(option -> {
                BankOptionsResp optionResp = new BankOptionsResp();
                optionResp.setId(option.getId());
                optionResp.setQuestionId(option.getQuestionId());
                optionResp.setSort(option.getSort());
                optionResp.setContent(option.getContent());
                return optionResp;
            }).collect(Collectors.toList());

            resp.setOptions(optionsResps);

        }
        KnowledgePointEntity knowledgePoints = knowledgePointQueryService.getKnowledgePointByKnowId(entity.getKnowId());
        resp.setKnow(KnowledgePointsConvert.INSTANCE.toResp(knowledgePoints));
        log.info("查询题库详情成功, ID: {}", id);
        return resp;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean addBankQuestion(BankQuestionsReq req) {
        log.info("新增题库, 请求参数: {}", req);
        BankQuestionsEntity entity = bankQuestionsConvert.toEntity(req);
        boolean result = bankQuestionsService.save(entity);
        log.info("新增题库结果: {}, 题库ID: {}", result, entity.getId());
        if(result && CollectionUtil.isNotEmpty(req.getOptions())){
            List<BankOptionsEntity> options = new ArrayList<>();
            req.getOptions().forEach(option -> {
                BankOptionsEntity optionEntity = new BankOptionsEntity();
                optionEntity.setQuestionId(entity.getId());
                optionEntity.setSort(option.getSort());
                optionEntity.setContent(option.getContent());
                options.add(optionEntity);

            });
            boolean batchUpdated = bankOptionsService.saveBatch(options);
            log.info("新增选项结果: {}", batchUpdated);
        }
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateBankQuestion(Integer id, BankQuestionsReq req) {
        log.info("更新题库信息, ID: {}, 请求参数: {}", id, req);
        BankQuestionsResp beforeData = getBankQuestionById(id);
        BankQuestionsEntity entity = bankQuestionsConvert.toEntity(req);
        entity.setId(id);
        boolean result = bankQuestionsService.updateById(entity);
        if(result ){
            if(CollectionUtil.isNotEmpty(req.getOptions())){
                List<BankOptionsEntity> options = new ArrayList<>();
                req.getOptions().forEach(option -> {
                    BankOptionsEntity optionEntity = new BankOptionsEntity();
                    optionEntity.setId(option.getId());
                    optionEntity.setQuestionId(id);
                    optionEntity.setSort(option.getSort());
                    optionEntity.setContent(option.getContent());
                    options.add(optionEntity);

                });
                boolean batchUpdated = bankOptionsService.updateBatchById(options);
                log.info("更新选项结果: {}", batchUpdated);
            }
            BankQuestionsResp afterData = getBankQuestionById(id);
            ModificationLogUtils.logModification(ModificationLogEntity.TARGET_TYPE_QUESTION, id,
                    entity.getTitle(), ModificationLogEntity.OPERATION_TYPE_UPDATE,
                    beforeData, afterData, StpUtil.getLoginIdAsInt());
        }
        log.info("更新题库信息结果: {}", result);
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateBankQuestionCheckAndScore(Integer id, CheckAndScoreReq req) {
        log.info("更新题库检查状态和评分, ID: {}, 请求参数: {}", id, req);
        BankQuestionsEntity entity = new BankQuestionsEntity();
        entity.setId(id);
        entity.setIsChecked(req.getIsChecked());
        entity.setScore(req.getScore());
        boolean result = bankQuestionsService.updateById(entity);
        log.info("更新题库检查状态和评分结果: {}", result);
        ModificationLogUtils.logModification(ModificationLogEntity.TARGET_TYPE_QUESTION, id,
                entity.getTitle(), ModificationLogEntity.OPERATION_TYPE_UPDATE, StpUtil.getLoginIdAsInt(),"更新检查状态和评分");
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteBankQuestion(Integer id) {
        BankQuestionsEntity entity = bankQuestionsService.getById(id);
        log.info("删除题库, ID: {}", id);
        boolean result = bankQuestionsService.removeById(id);
        log.info("删除题库结果: {}", result);
        ModificationLogUtils.logModification(ModificationLogEntity.TARGET_TYPE_QUESTION, id,
                entity.getTitle(), ModificationLogEntity.OPERATION_TYPE_DELETE, StpUtil.getLoginIdAsInt(),"删除题目");
        return result;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchSaveGeneratedBankQuestions(BankQuestionsBatchSaveReq req) {
        log.info("批量保存生成的题目开始");
        KnowledgePointEntity knowledgePoints = knowledgePointQueryService.getKnowledgePointByKnowId(req.getKnowId());
        AssertUtils.notNull(knowledgePoints, ResultCodeEnum.KNOW_NOT_EXIST);
        log.info("批量保存生成的题目, 请求参数: {}", req);
        if (CollectionUtil.isEmpty(req.getQuestions())) {
            log.warn("批量保存生成的题目请求参数为空");
            return false;
        }
        // 转换题目实体
        List<BankQuestionsEntity> entities = BankQuestionsConvert.INSTANCE.req2EntityList(req.getQuestions());
        entities.forEach(entity -> {
            entity.setKnowId(req.getKnowId());
        });
        // 批量保存题目
        boolean result = bankQuestionsService.saveBatch(entities);
        if (!result) {
            log.error("批量保存题目失败");
            return false;
        }
        // 收集所有选择题及其选项，准备批量保存
        List<BankOptionsEntity> allOptionEntities = new ArrayList<>();

        for (int i = 0; i < entities.size(); i++) {
            BankQuestionsEntity entity = entities.get(i);
            BankQuestionsBatchSaveReq.BankQuestionItem questionItem = req.getQuestions().get(i);

            // 判断是否为选择题（单选或多选）并且有选项数据
            if (isChoiceQuestion(entity.getType()) && CollectionUtil.isNotEmpty(questionItem.getOptions())) {
                // 构造选项实体
                List<BankOptionsEntity> optionEntities = questionItem.getOptions().stream().map(option -> {
                    BankOptionsEntity optionEntity = new BankOptionsEntity();
                    optionEntity.setQuestionId(entity.getId());
                    optionEntity.setSort(option.getSort());
                    optionEntity.setContent(option.getContent());
                    return optionEntity;
                }).collect(Collectors.toList());

                allOptionEntities.addAll(optionEntities);
            }
        }
        // 批量保存所有选项
        if (CollectionUtil.isNotEmpty(allOptionEntities)) {
            result = bankOptionsService.saveBatch(allOptionEntities);
            if (!result) {
                log.error("批量保存选项失败");
                return false;
            }
        }
        log.info("批量保存生成的题目结果: {}", result);
        return result;
    }

    /**
     * 判断是否为选择题
     *
     * @param type 题目类型
     * @return 是否为选择题
     */
    private boolean isChoiceQuestion(Integer type) {
        return type != null && (type.equals(QuestionTypesEnums.SINGLE_CHOICE_QUESTIONS.getCode()) || type.equals(QuestionTypesEnums.MULTIPLE_CHOICE_QUESTIONS.getCode()));
    }
}