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

import cn.hutool.core.collection.CollUtil;
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.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.seer.teach.admin.convert.MaterialDocConvert;
import com.seer.teach.admin.request.CheckAndScoreReq;
import com.seer.teach.admin.request.MaterialDocQueryReq;
import com.seer.teach.admin.request.MaterialDocReq;
import com.seer.teach.admin.request.MaterialDocSaveReq;
import com.seer.teach.admin.response.MaterialDocResp;
import com.seer.teach.admin.service.AdminMaterialDocService;
import com.seer.teach.admin.service.MaterialUploadService;
import com.seer.teach.common.enums.ExampleQuestionTypesEnum;
import com.seer.teach.common.enums.ResultCodeEnum;
import com.seer.teach.common.exception.CommonException;
import com.seer.teach.common.minio.config.MinioConfig;
import com.seer.teach.common.service.CommonFileService;
import com.seer.teach.common.utils.AssertUtils;
import com.seer.teach.common.utils.GradeUtils;
import com.seer.teach.common.utils.SubjectUtils;
import com.seer.teach.common.utils.VolumeUtils;
import com.seer.teach.teacher.module.entity.ExampleQuestionsEntity;
import com.seer.teach.teacher.module.entity.KnowSummaryEntity;
import com.seer.teach.teacher.module.entity.KnowledgePointEntity;
import com.seer.teach.teacher.module.entity.MaterialDocDataParseLog;
import com.seer.teach.teacher.module.entity.MaterialDocEntity;
import com.seer.teach.teacher.module.entity.MaterialEntity;
import com.seer.teach.teacher.module.entity.QuestionOptionsEntity;
import com.seer.teach.teacher.module.entity.UnitKnowMappingEntity;
import com.seer.teach.teacher.module.entity.UnitsEntity;
import com.seer.teach.teacher.module.entity.VersionsEntity;
import com.seer.teach.teacher.service.ExampleQuestionsService;
import com.seer.teach.teacher.service.KnowSummaryService;
import com.seer.teach.teacher.service.KnowledgePointService;
import com.seer.teach.teacher.service.MaterialDocDataParseLogService;
import com.seer.teach.teacher.service.MaterialDocService;
import com.seer.teach.teacher.service.MaterialService;
import com.seer.teach.teacher.service.QuestionOptionsService;
import com.seer.teach.teacher.service.UnitKnowMappingService;
import com.seer.teach.teacher.service.UnitsService;
import com.seer.teach.teacher.service.VersionsService;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.StringUtils;

import jakarta.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.TreeMap;
import java.util.stream.Collectors;

/**
 * <p>
 * 教材文档管理服务实现类
 * </p>
 *
 * @author ZS
 * @since 2025-10-23
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class AdminMaterialDocServiceImpl implements AdminMaterialDocService {

    private final MaterialDocService materialDocService;
    private final CommonFileService commonFileService;
    private final MaterialDocDataParseLogService materialDocDataParseLogService;
    private final MaterialService materialService;
    private final UnitsService unitsService;
    private final KnowledgePointService knowledgePointService;
    private final KnowSummaryService knowSummaryService;
    private final ExampleQuestionsService exampleQuestionsService;
    private final QuestionOptionsService questionOptionsService;
    private final VersionsService versionsService;
    private final TransactionTemplate transactionTemplate;
    private final UnitKnowMappingService unitKnowMappingService;
    private final MaterialUploadService materialUploadService;

    @Override
    public IPage<MaterialDocResp> pageMaterialDocs(MaterialDocQueryReq req) {
        // 构造分页对象
        Page<MaterialDocEntity> page = new Page<>(req.getPageNo(), req.getPageSize());

        // 构造查询条件
        LambdaQueryWrapper<MaterialDocEntity> queryWrapper = new LambdaQueryWrapper<>();

        // 根据查询条件构造查询条件
        if (StringUtils.hasText(req.getTeacherMaterialDocName())) {
            queryWrapper.like(MaterialDocEntity::getTeacherMaterialDocName, req.getTeacherMaterialDocName());
        }
        // 根据查询条件构造查询条件
        if (Objects.nonNull(req.getTeacherMaterialDocId())) {
            queryWrapper.eq(MaterialDocEntity::getId, req.getTeacherMaterialDocId());
        }
        if (Objects.nonNull(req.getIsChecked())) {
            queryWrapper.eq(MaterialDocEntity::getIsChecked, req.getIsChecked());
        }
        if (StringUtils.hasText(req.getSubjectName())) {
            queryWrapper.eq(MaterialDocEntity::getSubjectName, req.getSubjectName());
        }

        if (StringUtils.hasText(req.getVersionName())) {
            queryWrapper.like(MaterialDocEntity::getVersionName, req.getVersionName());
        }

        if (StringUtils.hasText(req.getGradeName())) {
            queryWrapper.eq(MaterialDocEntity::getGradeName, req.getGradeName());
        }

        queryWrapper.last("ORDER BY version_name DESC,FIELD(grade_name, '一年级','二年级','三年级','四年级','五年级','六年级','七年级','八年级','九年级','高中') ,volume_name ASC");

        // 执行分页查询
        IPage<MaterialDocEntity> resultPage = materialDocService.page(page, queryWrapper);

        // 转换为响应对象
        return resultPage.convert(MaterialDocConvert.INSTANCE::convert);
    }

    @Override
    public MaterialDocResp getMaterialDocById(Long id) {
        MaterialDocEntity entity = materialDocService.getById(id);
        return entity != null ? MaterialDocConvert.INSTANCE.convert(entity) : null;
    }

    @Override
    public boolean addMaterialDoc(MaterialDocSaveReq req) {
        // 如果有文件上传，则使用文件上传服务
        if (req.getFile() != null && !req.getFile().isEmpty()) {
            try {
                String fileName = req.getFile().getOriginalFilename();
                List<VersionsEntity> versionList = versionsService.list();
                Integer subjectId = req.getSubjectId();
                AssertUtils.notNull(subjectId, ResultCodeEnum.SUBJECT_NOT_EXIST);
                VersionsEntity version = getVersionByName(req.getVersionName(), subjectId, versionList);
                // 获取版本ID
                Integer versionId = version.getId();
                // 创建临时文件
                File tempFile = File.createTempFile("material_", ".pdf");
                req.getFile().transferTo(tempFile);
                
                // 调用上传服务
                MaterialDocEntity entity = materialUploadService.uploadMaterial(fileName,
                    tempFile, 
                    req.getJsonContent(), 
                    req.getSubjectName(), 
                    req.getVersionName(), 
                    req.getVolumeName(),
                    req.getGradeName()
                );
                // 删除临时文件
                tempFile.delete();

                Integer volumeId = VolumeUtils.getVolumeIdByName(entity.getVolumeName());
                log.debug("获取到册别ID: {}，册别名称: {}", volumeId, entity.getVolumeName());
                MaterialEntity material = new MaterialEntity();
                material.setDocId(entity.getId());
                material.setVersionId(versionId);
                material.setSubjectId(subjectId);
                material.setGradeId(req.getGradeId());
                material.setVolume(volumeId);
                material.setBookName(fileName);
                material.setIsChecked(0);
                material.setScore(BigDecimal.ZERO);
                material.setCreateTime(LocalDateTime.now());
                materialService.save(material);
                log.info("教材保存成功");
                return true;
            } catch (Exception e) {
                log.error(e.getMessage(), e);
               throw new RuntimeException(e.getMessage(),e);
            }
        }
        return false;
    }

    @Override
    public boolean updateMaterialDoc(Long id, MaterialDocReq req) {
        MaterialDocEntity entity = MaterialDocConvert.INSTANCE.convert(req);
        entity.setId(id.intValue());
        entity.setUpdateTime(LocalDateTime.now());
        return materialDocService.updateById(entity);
    }

    @Transactional(rollbackFor = Exception.class,timeout = 300)
    @Override
    public boolean deleteMaterialDoc(Integer id) {
        log.info("开始删除教材文档，文档ID: {}", id);
        deleteExistingRecords(id);

        return materialDocService.removeById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean parseMaterialDoc(Long id) {
        log.info("开始解析教材文档，文档ID: {}", id);
        // 1. 根据ID查找文档
        MaterialDocEntity doc = materialDocService.getById(id);
        if (doc == null) {
            throw new RuntimeException("未找到ID为 " + id + " 的教材文档");
        }
        // 创建日志记录（在独立事务中保存）
        Integer logId = transactionTemplate.execute(status -> {
            try {
                MaterialDocDataParseLog parseLog = new MaterialDocDataParseLog();
                parseLog.setDocId(doc.getId());
                parseLog.setSubjectName(doc.getSubjectName());
                parseLog.setVersionName(doc.getVersionName());
                parseLog.setGradeName(doc.getGradeName());
                parseLog.setVolumeName(doc.getVolumeName());
                parseLog.setStatus(1);
                parseLog.setCreateTime(LocalDateTime.now());
                parseLog.setUpdateTime(LocalDateTime.now());
                materialDocDataParseLogService.save(parseLog);
                log.debug("成功创建解析日志记录，日志ID: {}", parseLog.getId());
                return parseLog.getId();
            } catch (Exception e) {
                log.error("创建日志记录失败，文档ID: {}", doc.getId(), e);
                status.setRollbackOnly();
                return null;
            }
        });

        if (logId == null) {
            log.error("无法创建日志记录，文档ID: {}", doc.getId());
            throw new RuntimeException("无法创建日志记录");
        }

        try {
            // 2. 解析JSON内容
            String jsonContent = doc.getJsonContent();
            if (!StringUtils.hasText(jsonContent)) {
                throw new RuntimeException("教材文档JSON内容为空");
            }

            ObjectMapper objectMapper = new ObjectMapper();
            List<UnitDTO> units = objectMapper.readValue(doc.getJsonContent(), new TypeReference<List<UnitDTO>>() {});
            log.info("版本{} 年纪：{}，科目：{}  文档[{}] [{}] JSON解析完成，共包含 {} 个单元", doc.getVersionName(), doc.getGradeName(), doc.getSubjectName(), doc.getId(), doc.getTeacherMaterialDocName(), units.size());

            if (CollUtil.isEmpty(units)) {
                throw new CommonException(ResultCodeEnum.PARSET_MATERIAL_DOC_ERROR);
            }
            // 3. 删除旧记录
            deleteExistingRecords(doc.getId());

            // 4. 插入新记录到相关表
            DataCount dataCount = saveParsedData(doc, units);
            log.info("文档[{}] [{}] 数据保存完成，统计信息 - 单元: {}, 知识点: {}, 总结: {}, 例题: {}, 选项: {}",
                    doc.getId(), doc.getTeacherMaterialDocName(), dataCount.getUnitCount(), dataCount.getKnowledgePointCount(),
                    dataCount.getKnowSummaryCount(), dataCount.getExampleQuestionCount(),
                    dataCount.getQuestionOptionCount());

            // 5. 更新解析日志
            // 更新日志记录为成功状态（在独立事务中更新）
            transactionTemplate.execute(status -> {
                try {
                    MaterialDocDataParseLog parseLog = new MaterialDocDataParseLog();
                    parseLog.setId(logId);
                    parseLog.setStatus(2); // 成功
                    parseLog.setKnowledgePointCount(dataCount.getKnowledgePointCount());
                    parseLog.setKnowSummaryCount(dataCount.getKnowSummaryCount());
                    parseLog.setExampleQuestionCount(dataCount.getExampleQuestionCount());
                    parseLog.setQuestionOptionCount(dataCount.getQuestionOptionCount());
                    parseLog.setUnitCount(dataCount.getUnitCount());
                    parseLog.setUpdateTime(LocalDateTime.now());
                    materialDocDataParseLogService.updateById(parseLog);
                } catch (Exception e) {
                    log.error("更新日志记录失败，日志ID: {}", logId, e);
                }
                return null;
            });
            return true;
        } catch (  Exception e) {
            log.error("解析教材文档失败，文档ID: {}", id, e);
            log.error("处理文档数据时发生异常，文档ID: {}", doc.getId(), e);
            // 更新日志记录为失败状态（在独立事务中更新）
            transactionTemplate.execute(status -> {
                try {
                    MaterialDocDataParseLog parseLog = new MaterialDocDataParseLog();
                    parseLog.setId(logId);
                    parseLog.setStatus(3); // 失败
                    parseLog.setErrorMsg(e.getMessage());
                    parseLog.setUpdateTime(LocalDateTime.now());
                    materialDocDataParseLogService.updateById(parseLog);
                    log.debug("成功更新解析日志记录为失败状态，日志ID: {}", logId);
                } catch (Exception ex) {
                    log.error("更新日志记录失败，日志ID: {}", logId, ex);
                }
                return null;
            });
            return false;
        }
    }

    @Override
    public boolean updateMaterialDocCheckAndScore(Integer id, CheckAndScoreReq req) {
        MaterialDocEntity entity = new MaterialDocEntity();
        entity.setId(id);
        entity.setIsChecked(req.getIsChecked());
        entity.setScore(req.getScore());
        return materialDocService.updateById(entity);
    }

    /**
     * 保存解析后的数据
     */
    private DataCount saveParsedData(MaterialDocEntity doc, List<UnitDTO> units){
        Integer subjectId = SubjectUtils.getSubjectIdBySubjectName(doc.getSubjectName());
        AssertUtils.notNull(subjectId, ResultCodeEnum.SUBJECT_NOT_EXIST);
        log.debug("获取到学科ID: {}，学科名称: {}", subjectId, doc.getSubjectName());

        List<VersionsEntity> versionList = versionsService.list();
        // 获取版本ID
        VersionsEntity version = getVersionByName(doc.getVersionName(), subjectId, versionList);
        Integer versionId = version.getId();
        log.debug("获取到版本ID: {}，版本名称: {}", versionId, doc.getVersionName());

        // 获取年级ID
        Integer gradeId = GradeUtils.getGradeIdByName(doc.getGradeName());
        log.debug("获取到年级ID: {}，年级名称: {}", gradeId, doc.getGradeName());

        // 获取册别ID (0-上册, 1-下册)
        Integer volumeId = VolumeUtils.getVolumeIdByName(doc.getVolumeName());
        log.debug("获取到册别ID: {}，册别名称: {}", volumeId, doc.getVolumeName());
        MaterialEntity materialEntity = new MaterialEntity();
        materialEntity.setVersionId(versionId);
        materialEntity.setGradeId(gradeId);
        materialEntity.setVolume(volumeId);
        materialEntity.setBookName(doc.getTeacherMaterialDocName());
        materialEntity.setDocId(doc.getId());
        materialService.save(materialEntity);

        // 初始化统计数据
        DataCount dataCount = new DataCount();
        for (UnitDTO unitDto : units) {
            // 保存单元及相关数据
            log.debug("开始处理 {} 个单元", units.size());
            // 保存单元信息
            UnitsEntity unit = new UnitsEntity();
            unit.setMaterialId(materialEntity.getId());
            unit.setUnitName(unitDto.getUnitTitle());
            unit.setSort(unitDto.getUnitOrder());
            unit.setCreateTime(LocalDateTime.now());
            unit.setUpdateTime(LocalDateTime.now());
            unitsService.save(unit);
            dataCount.unitCount++;
            log.debug("单元信息保存完成，单元ID: {},单元名称:{}", unit.getId(), unit.getUnitName());

            // 保存知识点
            if (unitDto.getKnowledgePoints() != null) {
                log.debug("单元ID: {} 包含 {} 个知识点", unit.getId(), unitDto.getKnowledgePoints().size());
                for (int j = 0; j < unitDto.getKnowledgePoints().size(); j++) {
                    KnowledgePointDTO knowledgePointDto = unitDto.getKnowledgePoints().get(j);
                    log.debug("处理第 {} 个知识点: {}", j + 1, knowledgePointDto.getPointTitle());
                    // 保存知识点
                    KnowledgePointEntity knowledgePoint = new KnowledgePointEntity();
                    knowledgePoint.setKnowledgePointName(knowledgePointDto.getPointTitle());
                    knowledgePoint.setVideoScript(knowledgePointDto.getDetailedTeaching());
                    knowledgePoint.setCreateTime(LocalDateTime.now());
                    knowledgePoint.setGradeType(getGradeTypeByGradeId(gradeId));
                    knowledgePoint.setSubjectId(subjectId);
                    knowledgePointService.save(knowledgePoint);
                    dataCount.knowledgePointCount++;
                    log.debug("知识点保存完成，知识点ID: {},知识点名称:{}", knowledgePoint.getId(), knowledgePoint.getKnowledgePointName());

                    // 保存知识点总结
                    KnowSummaryEntity knowSummary = new KnowSummaryEntity();
                    knowSummary.setKnowId(knowledgePoint.getId());
                    knowSummary.setSummary(knowledgePointDto.getSummary());
                    knowSummary.setCreateTime(LocalDateTime.now());
                    knowSummary.setUpdateTime(LocalDateTime.now());
                    knowSummaryService.save(knowSummary);

                    UnitKnowMappingEntity unitKnowMapping = new UnitKnowMappingEntity();
                    unitKnowMapping.setUnitId(unit.getId());
                    unitKnowMapping.setKnowledgePointId(knowledgePoint.getId());
                    unitKnowMapping.setSort(knowledgePointDto.getOrder());
                    unitKnowMapping.setScore(BigDecimal.ZERO);
                    unitKnowMapping.setIsChecked(0);
                    unitKnowMapping.setIsStandardVersion(version.getIsStandardVersion());
                    knowledgePoint.setCreateTime(LocalDateTime.now());
                    unitKnowMappingService.save(unitKnowMapping);
                    dataCount.knowSummaryCount++;
                    log.debug("知识点总结保存完成，总结ID: {}", knowSummary.getId());

                    // 保存例题
                    if (knowledgePointDto.getExampleQuestions() != null) {
                        log.debug("知识点ID: {} 包含 {} 道例题", knowledgePoint.getId(), knowledgePointDto.getExampleQuestions().size());
                        for (int k = 0; k < knowledgePointDto.getExampleQuestions().size(); k++) {
                            ExampleQuestionDTO exampleQuestionDto = knowledgePointDto.getExampleQuestions().get(k);
                            log.debug("处理第 {} 道例题，题型: {}", k + 1, exampleQuestionDto.getType());

                            ExampleQuestionsEntity exampleQuestion = new ExampleQuestionsEntity();
                            exampleQuestion.setKnowId(knowledgePoint.getId());
                            exampleQuestion.setQuestion(exampleQuestionDto.getQuestion());
                            exampleQuestion.setAnswer(exampleQuestionDto.getAnswer());
                            exampleQuestion.setSolution(exampleQuestionDto.getExplanation());
                            exampleQuestion.setType(getQuestionType(exampleQuestionDto.getType()));
                            exampleQuestion.setCreateTime(LocalDateTime.now());
                            exampleQuestion.setUpdateTime(LocalDateTime.now());
                            exampleQuestionsService.save(exampleQuestion);
                            dataCount.exampleQuestionCount++;
                            log.debug("例题保存完成，例题ID: {},例题名称:{}", exampleQuestion.getId(), exampleQuestion.getQuestion());

                            // 保存选择题选项
                            if ("选择题".equals(exampleQuestionDto.getType()) && exampleQuestionDto.getOptions() != null) {
                                log.debug("例题ID: {} 包含 {} 个选项", exampleQuestion.getId(), exampleQuestionDto.getOptions().size());
                                for (int l = 0; l < exampleQuestionDto.getOptions().size(); l++) {
                                    QuestionOptionsEntity option = new QuestionOptionsEntity();
                                    option.setQuestionId(exampleQuestion.getId());
                                    option.setContent(exampleQuestionDto.getOptions().get(l));
                                    option.setSort(l + 1);
                                    option.setCreateTime(LocalDateTime.now());
                                    option.setUpdateTime(LocalDateTime.now());
                                    questionOptionsService.save(option);
                                    dataCount.questionOptionCount++;
                                    log.debug("选项保存完成，选项ID: {},选项：{}", option.getId(), option.getContent());
                                }
                            }
                        }
                    }
                }
            }

        }
        return dataCount;
    }

    private Integer getGradeTypeByGradeId(Integer gradeId) {
        log.debug("获取年级类型，年级ID: {}", gradeId);
        switch (gradeId) {
            case 1:
            case 2:
            case 3:
            case 4:
            case 5:
            case 6:
                return 1;
            case 7:
            case 8:
            case 9:
                return 2;
            case 10:
                return 3;
        }
        throw new RuntimeException("未找到年级类型");
    }

    /**
     * 根据题型名称获取题型ID
     */
    private Integer getQuestionType(String typeStr) {
        log.debug("获取题型ID，题型名称: {}", typeStr);
        return ExampleQuestionTypesEnum.fromMessage(typeStr).getCode();
    }

    /**
     * 根据版本名称和学科ID获取版本ID（带缓存）
     */
    private VersionsEntity getVersionByName(String versionName, Integer subjectId, List<VersionsEntity> versionList) {
        for (VersionsEntity version : versionList) {
            if (version.getVersionName().equals(versionName) && version.getSubjectId().equals(subjectId)) {
                return version;
            }
        }
        VersionsEntity version = new VersionsEntity();
        version.setSubjectId(subjectId);
        version.setVersionName(versionName);
        version.setIsStandardVersion(1);
        version.setCreateTime(LocalDateTime.now());
        version.setUpdateTime(LocalDateTime.now());
        boolean saved = versionsService.save(version);
        if (!saved) {
            log.warn("保存版本失败，版本名称: {}, 学科ID: {}", versionName, subjectId);
            throw new RuntimeException("保存版本失败");
        }
        log.warn("未找到版本名称对应的ID: {}, 学科ID: {}", versionName, subjectId);
        return version;
    }

    /**
     * 删除已存在的相关记录
     *
     * @param docId 教材文档ID
     */
    private void deleteExistingRecords(Integer docId) {
        log.info("开始删除教材文档相关旧记录，文档ID: {}", docId);

        // 查找对应的教材记录
        MaterialEntity materialEntity = materialService.getOne(new LambdaQueryWrapper<MaterialEntity>().eq(MaterialEntity::getDocId, docId));
        if (Objects.isNull(materialEntity)) {
            log.info("教材记录不存在，文档ID: {}", docId);
            return;
        }

        List<UnitsEntity> unitsList = unitsService.list(new LambdaQueryWrapper<UnitsEntity>().eq(UnitsEntity::getMaterialId, materialEntity.getId()));
        if (CollUtil.isEmpty(unitsList)) {
            log.info("单元记录不存在，文档ID: {}", docId);
            return;
        }
        List<Integer> unitsIds = unitsList.stream().map(UnitsEntity::getId).collect(Collectors.toList());
        Collection<UnitKnowMappingEntity> unitKnowMappingList = unitKnowMappingService.getListByUnitIds(unitsIds);
        if (CollUtil.isEmpty(unitKnowMappingList)) {
            log.info("知识点映射记录不存在，文档ID: {}", docId);
            return;
        }
        List<Integer> knowledgePointIds = unitKnowMappingList.stream().map(UnitKnowMappingEntity::getKnowledgePointId).collect(Collectors.toList());
        for (UnitKnowMappingEntity unitKnowMapping : unitKnowMappingList) {
            Integer knowledgePointId = unitKnowMapping.getKnowledgePointId();
            List<UnitKnowMappingEntity> unitKnowMappingEntities = unitKnowMappingService.list(new LambdaQueryWrapper<UnitKnowMappingEntity>().eq(UnitKnowMappingEntity::getKnowledgePointId, knowledgePointId));
            if(unitKnowMappingEntities.size() == 1 &&  unitKnowMappingEntities.get(0).getId().equals(unitKnowMapping.getId())){
                List<ExampleQuestionsEntity> questionList = exampleQuestionsService.getQuestionsByKnowleIds(knowledgePointIds);
                if (CollUtil.isNotEmpty(questionList)) {
                    Set<Integer> questionIdList = questionList.stream().map(ExampleQuestionsEntity::getId).collect(Collectors.toSet());
                    boolean deletedOptions = questionOptionsService.remove(new LambdaQueryWrapper<QuestionOptionsEntity>().in(QuestionOptionsEntity::getQuestionId, questionIdList));
                    log.info("删除题目选项完成, 结果: {}", deletedOptions);

                    boolean removed = exampleQuestionsService.remove(new LambdaQueryWrapper<ExampleQuestionsEntity>().in(ExampleQuestionsEntity::getKnowId, knowledgePointIds));
                    log.info("删除题目完成, 结果: {}", removed);
                }
                // 删除知识点总结
                boolean removedKnowSummaries = knowSummaryService.remove(new LambdaQueryWrapper<KnowSummaryEntity>().in(KnowSummaryEntity::getKnowId, knowledgePointIds));
                log.info("删除知识点总结完成, 结果: {}", removedKnowSummaries);

                // 删除知识点
                boolean removeKnowledgePoint = knowledgePointService.remove(new LambdaQueryWrapper<KnowledgePointEntity>().eq(KnowledgePointEntity::getId, knowledgePointId));
                log.info("删除知识点完成, 结果: {}", removeKnowledgePoint);

                // 删除知识点映射
                boolean removedUnitKnowMapping = unitKnowMappingService.remove(new LambdaQueryWrapper<UnitKnowMappingEntity>().in(UnitKnowMappingEntity::getUnitId, unitsIds));
                log.info("删除知识点映射完成, 结果: {}", removedUnitKnowMapping);
            }else{
                log.info("单元映射关系存在多个,只能删除自己的");
                // 删除知识点映射
                boolean removedUnitKnowMapping = unitKnowMappingService.removeById(unitKnowMapping);
                log.info("多映射关系删除知识点映射完成, 结果: {}", removedUnitKnowMapping);
            }
        }
        // 删除单元
        boolean removeUnits = unitsService.remove(new LambdaQueryWrapper<UnitsEntity>().eq(UnitsEntity::getMaterialId, materialEntity.getId()));
        log.info("删除单元完成, 结果: {}", removeUnits);
        // 删除教材
        boolean removed = materialService.removeById(materialEntity.getId());
        log.info("删除教材完成, 结果: {}", removed);
        log.info("删除教材文档相关旧记录完成，文档ID: {}", docId);
    }

    @Override
    public void downloadMaterialDoc(Long id, HttpServletResponse response) throws IOException {
        // 获取教材文档信息
        MaterialDocEntity entity = materialDocService.getById(id);
        if (entity == null) {
            throw new RuntimeException("教材文档不存在");
        }

        // 获取文件URL
        String fileUrl = entity.getTeacherMaterialUrl();
        if (!StringUtils.hasText(fileUrl)) {
            throw new RuntimeException("教材文档URL为空");
        }
        log.info("下载教材文档，文档ID: {}，URL: {}", id, fileUrl);
        try {
            // 从MinIO下载文件
            String bucketName = MinioConfig.TEXT_BOOK;
            String objectName = extractObjectNameFromUrl(fileUrl, bucketName);
            log.info("解析出的MinIO对象名称: {}", objectName);
            InputStream inputStream = commonFileService.downloadFile(bucketName, objectName);

            // 设置响应头
            String fileName = entity.getTeacherMaterialDocName();
            if (!StringUtils.hasText(fileName)) {
                fileName = "document_" + id;
            }

            // 编码文件名以支持中文
            String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.toString()).replace("+", "%20");

            response.setContentType(entity.getTeacherMaterialMime() != null ? entity.getTeacherMaterialMime() : "application/octet-stream");
            response.setHeader("Content-Disposition", "attachment; filename=\"" + encodedFileName + "\"");

            // 写入响应流
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                response.getOutputStream().write(buffer, 0, bytesRead);
            }
            response.getOutputStream().flush();

            inputStream.close();
        } catch (Exception e) {
            log.error("下载教材文档失败，文档ID: {}，URL: {}", id, fileUrl, e);
            throw new IOException("下载教材文档失败: " + e.getMessage());
        }
    }

    /**
     * 从完整的URL中提取MinIO对象名称
     *
     * @param fileUrl    完整的文件URL
     * @param bucketName 存储桶名称
     * @return 对象名称
     */
    private String extractObjectNameFromUrl(String fileUrl, String bucketName) {
        try {
            String urlWithoutProtocol = fileUrl.replaceFirst("^https?://", "");

            // 找到第一个斜杠，即服务器地址和路径的分界
            int firstSlashIndex = urlWithoutProtocol.indexOf("/");
            if (firstSlashIndex != -1) {
                // 获取路径部分
                String path = urlWithoutProtocol.substring(firstSlashIndex + 1);
                log.debug("解析URL路径部分: {}", path);

                // 查找BUCKET名称在路径中的位置
                int bucketIndex = path.indexOf(bucketName);
                if (bucketIndex != -1) {
                    // 找到BUCKET后，提取对象名称部分
                    String objectPath = path.substring(bucketIndex + bucketName.length());
                    if (objectPath.startsWith("/")) {
                        objectPath = objectPath.substring(1);
                    }
                    log.debug("通过BUCKET解析出对象路径: {}", objectPath);
                    return objectPath;
                }

                // 如果没有找到BUCKET，尝试直接去掉第一个路径段
                int secondSlashIndex = path.indexOf("/");
                if (secondSlashIndex != -1) {
                    String objectPath = path.substring(secondSlashIndex + 1);
                    log.debug("通过移除第一段路径解析出对象路径: {}", objectPath);
                    return objectPath;
                }
            }
        } catch (Exception e) {
            log.error("解析URL时发生异常: {}", fileUrl, e);
        }

        log.warn("URL格式不符合预期，直接使用原始URL作为对象名称: {}", fileUrl);
        // 如果解析失败，尝试直接使用URL的最后一部分作为对象名称
        String[] parts = fileUrl.split("/");
        if (parts.length > 0) {
            return parts[parts.length - 1];
        }

        throw new IllegalArgumentException("无效的MinIO URL格式: " + fileUrl);
    }

    @Setter
    @Getter
    @NoArgsConstructor
    static class UnitDTO {
        private Integer unitOrder;
        private String unitTitle;
        private List<KnowledgePointDTO> knowledgePoints;
    }

    @Setter
    @Getter
    @NoArgsConstructor
    static class KnowledgePointDTO {
        private Integer order;
        private String pointTitle;
        private String summary;
        private String detailedTeaching;
        private List<ExampleQuestionDTO> exampleQuestions;
    }

    @Setter
    @Getter
    @NoArgsConstructor
    static class ExampleQuestionDTO {
        private String type;
        private String question;
        private List<String> options;
        private String answer;
        private String explanation;
    }

    @Data
    class DataCount {
        private int unitCount = 0;
        private int knowledgePointCount = 0;
        private int knowSummaryCount = 0;
        private int exampleQuestionCount = 0;
        private int questionOptionCount = 0;
    }
}