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

import cn.hutool.core.collection.CollUtil;
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.MaterialConvert;
import com.seer.teach.admin.request.CheckAndScoreReq;
import com.seer.teach.admin.request.MaterialQueryReq;
import com.seer.teach.admin.request.MaterialReq;
import com.seer.teach.admin.response.MaterialResp;
import com.seer.teach.admin.response.MaterialWithUnitResp;
import com.seer.teach.admin.service.AdminExampleQuestionsService;
import com.seer.teach.admin.service.AdminsMaterialService;
import com.seer.teach.common.enums.ResultCodeEnum;
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.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.MaterialDocEntity;
import com.seer.teach.teacher.module.entity.MaterialEntity;
import com.seer.teach.teacher.module.entity.QuestionOptionsEntity;
import com.seer.teach.teacher.module.entity.RichTextTemplateEntity;
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.IRichTextTemplateService;
import com.seer.teach.teacher.service.KnowSummaryService;
import com.seer.teach.teacher.service.KnowledgePointService;
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 com.seer.teach.common.utils.dto.GradeDTO;
import com.seer.teach.user.api.UserInfoServiceApi;
import com.seer.teach.user.api.dto.UserInfoDTO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 教材管理服务实现类
 * </p>
 *
 * @author ZS
 * @since 2025-10-22
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class AdminsMaterialServiceImpl implements AdminsMaterialService {

    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 MaterialDocService materialDocService;

    private final AdminExampleQuestionsService adminExampleQuestionsService;

    private final IRichTextTemplateService richTextTemplateService;

    private final UnitKnowMappingService unitKnowMappingService;

    private final UserInfoServiceApi userInfoServiceApi;

    @Override
    public IPage<MaterialResp> pageMaterials(MaterialQueryReq req) {
        LambdaQueryWrapper<MaterialEntity> queryWrapper = buildPageQueryWrapper(req);
        Page<MaterialEntity> page = new Page<>(req.getPageNo(), req.getPageSize());
        IPage<MaterialEntity> entityPage = materialService.page(page, queryWrapper);

        IPage<MaterialResp> respPage = entityPage.convert(MaterialConvert.INSTANCE::entityToResp);
        if (CollectionUtil.isEmpty(respPage.getRecords())) {
            return new Page<>();
        }
        List<Integer> versionIds = respPage.getRecords().stream().map(MaterialResp::getVersionId).collect(Collectors.toList());
        List<Integer> docIds = respPage.getRecords().stream().map(MaterialResp::getDocId).collect(Collectors.toList());
        Set<Integer> updateUserIds = respPage.getRecords().stream().filter(item -> Objects.nonNull(item.getUpdateBy())).map(item -> Integer.valueOf(item.getUpdateBy())).collect(Collectors.toSet());
        List<VersionsEntity> versionsEntities = versionsService.listByIds(versionIds);
        // 批量获取用户信息
        Map<Integer, String> updateUserNamesMap = new HashMap<>();
        if (CollUtil.isNotEmpty(updateUserIds)) {
            try {
                List<UserInfoDTO> userInfoList = userInfoServiceApi.getListByUserIds(updateUserIds);
                updateUserNamesMap = userInfoList.stream()
                        .filter(Objects::nonNull)
                        .filter(userInfo -> userInfo.getId() != null)
                        .filter(userInfo -> userInfo.getUserName() != null)
                        .collect(Collectors.toMap(UserInfoDTO::getId, UserInfoDTO::getUserName));
            } catch (Exception e) {
                log.warn("获取用户信息失败，错误信息：{}", e.getMessage());
            }
        }
        Map<Integer, VersionsEntity> versionsMaps = versionsEntities.stream().collect(Collectors.toMap(VersionsEntity::getId, Function.identity(), (k1, k2) -> k1));
        List<MaterialDocEntity> materialDocIdsByMaterialIds = materialDocService.getMaterialDocIdsByMaterialIds(docIds);
        Map<Integer, MaterialDocEntity> materialDocMap = materialDocIdsByMaterialIds.stream().collect(Collectors.toMap(MaterialDocEntity::getId, Function.identity(), (k1, k2) -> k1));
        for (MaterialResp resp : respPage.getRecords()) {
            String updateBy = resp.getUpdateBy();
            if (StringUtils.isNotEmpty(updateBy)) {
                resp.setUpdateByName(updateUserNamesMap.get(Integer.valueOf(updateBy)));
            }
            resp.setGradeName(GradeUtils.getNameById(resp.getGradeId()));
            VersionsEntity versionsEntity = versionsMaps.get(resp.getVersionId());
            if (Objects.nonNull(versionsEntity)) {
                resp.setVersionName(versionsEntity.getVersionName());
            }
            resp.setSubjectName(SubjectUtils.getSubjectNameBySubjectId(versionsEntity.getSubjectId()));
            MaterialDocEntity materialDocEntity = materialDocMap.get(resp.getDocId());
            if (materialDocEntity != null) {
                resp.setDocUrl(materialDocEntity.getTeacherMaterialUrl());
            }
        }
        return respPage;
    }

    private static LambdaQueryWrapper<MaterialEntity> buildPageQueryWrapper(MaterialQueryReq req) {
        LambdaQueryWrapper<MaterialEntity> queryWrapper = new LambdaQueryWrapper<>();
        if (CollectionUtil.isNotEmpty(req.getVersionIds())) {
            queryWrapper.in(MaterialEntity::getVersionId, req.getVersionIds());
        }else{
            if (Objects.nonNull(req.getVersionId())) {
                queryWrapper.eq(MaterialEntity::getVersionId, req.getVersionId());
            }
        }
        if (Objects.nonNull(req.getSubjectId())) {
            queryWrapper.eq(MaterialEntity::getSubjectId, req.getSubjectId());
        }
        if (Objects.nonNull(req.getGradeType()) && CollectionUtil.isNotEmpty(GradeUtils.getGradeIdsByType(req.getGradeType()))) {
            queryWrapper.in(MaterialEntity::getGradeId, GradeUtils.getGradeIdsByType(req.getGradeType()));
        }
        if (Objects.nonNull(req.getGradeId())) {
            queryWrapper.eq(MaterialEntity::getGradeId, req.getGradeId());
        }
        if (req.getVolume() != null) {
            queryWrapper.eq(MaterialEntity::getVolume, req.getVolume());
        }
        if (req.getBookName() != null && !req.getBookName().isEmpty()) {
            queryWrapper.like(MaterialEntity::getBookName, req.getBookName());
        }
        if (Objects.nonNull(req.getIsChecked())) {
            queryWrapper.eq(MaterialEntity::getIsChecked, req.getIsChecked());
        }
        if (Objects.nonNull(req.getDocId())) {
            queryWrapper.eq(MaterialEntity::getDocId, req.getDocId());
        }
        if (Objects.nonNull(req.getMaterialId())) {
            queryWrapper.eq(MaterialEntity::getId, req.getMaterialId());
        }
        queryWrapper.orderByDesc(MaterialEntity::getVersionId).orderByAsc(MaterialEntity::getGradeId).orderByAsc(MaterialEntity::getId);
        return queryWrapper;
    }

    @Override
    public MaterialResp getMaterialById(Integer id) {
        MaterialEntity entity = materialService.getById(id);
        MaterialResp materialResp = MaterialConvert.INSTANCE.entityToResp(entity);
        String gradeName = GradeUtils.getNameById(entity.getGradeId());
        materialResp.setGradeName(gradeName);
        VersionsEntity versionsEntity = versionsService.getById(entity.getVersionId());
        materialResp.setVersionName(versionsEntity.getVersionName());
        return materialResp;
    }

    @Override
    public List<MaterialWithUnitResp> getMaterialsByKnowledgePointId(Integer knowledgePointId) {
        // 1. 通过知识点ID查询关联的单元知识点映射记录
        List<Integer> unitIds = unitKnowMappingService.list(
                        new LambdaQueryWrapper<UnitKnowMappingEntity>()
                                .eq(UnitKnowMappingEntity::getKnowledgePointId, knowledgePointId))
                .stream()
                .map(com.seer.teach.teacher.module.entity.UnitKnowMappingEntity::getUnitId)
                .collect(Collectors.toList());

        if (CollectionUtil.isEmpty(unitIds)) {
            return CollectionUtil.newArrayList();
        }

        // 2. 通过单元ID查询对应的教材ID
        List<UnitsEntity> units = unitsService.list(
                new LambdaQueryWrapper<UnitsEntity>()
                        .in(UnitsEntity::getId, unitIds));

        if (CollectionUtil.isEmpty(units)) {
            return CollectionUtil.newArrayList();
        }

        Set<Integer> materialIds = units.stream()
                .map(UnitsEntity::getMaterialId)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());

        if (CollectionUtil.isEmpty(materialIds)) {
            return CollectionUtil.newArrayList();
        }

        // 3. 查询教材信息
        List<MaterialEntity> materials = materialService.list(
                new LambdaQueryWrapper<MaterialEntity>()
                        .in(MaterialEntity::getId, materialIds));

        // 4. 转换为响应对象
        List<MaterialWithUnitResp> materialResps = MaterialConvert.INSTANCE.entitiesToWithUnitResps(materials);

        // 5. 填充额外信息
        fillMaterialExtraInfo(materialResps, units);

        return materialResps;
    }

    @Override
    public boolean addMaterial(MaterialReq req) {
        MaterialEntity entity = MaterialConvert.INSTANCE.reqToEntity(req);
        return materialService.save(entity);
    }

    @Override
    public boolean updateMaterial(Integer id, MaterialReq req) {
        MaterialEntity entity = MaterialConvert.INSTANCE.reqToEntity(req);
        entity.setId(id);
        return materialService.updateById(entity);
    }

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

    /**
     * 删除教材及其关联的所有数据（单元、知识点、知识点摘要、示例题目和选项）
     *
     * @param id 教材ID
     * @return 是否删除成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteMaterial(Integer id) {
        log.info("开始删除教材及其关联数据, 教材ID: {}", id);

        // 1. 查询该教材下的所有单元
        List<UnitsEntity> unitsList = unitsService.list(new LambdaQueryWrapper<UnitsEntity>()
                .eq(UnitsEntity::getMaterialId, id));
        log.info("查询到 {} 个单元需要删除", unitsList.size());

        if (CollectionUtil.isEmpty(unitsList)) {
            // 删除教材本身
            boolean result = materialService.removeById(id);
            log.info("教材删除完成, 结果: {}", result);
            return result;
        }
        List<Integer> unitIds = unitsList.stream().map(UnitsEntity::getId).collect(Collectors.toList());

        // 2. 查询这些单元下的所有知识点
        List<KnowledgePointEntity> knowledgePointsList = knowledgePointService.getKnows(unitIds);
        log.info("查询到 {} 个知识点需要删除", knowledgePointsList.size());

        if (CollectionUtil.isNotEmpty(knowledgePointsList)) {
            List<Integer> knowledgePointIds = knowledgePointsList.stream()
                    .map(KnowledgePointEntity::getId)
                    .collect(Collectors.toList());

            // 3. 删除知识点摘要
            boolean deletedSummaries = knowSummaryService.remove(
                    new LambdaQueryWrapper<KnowSummaryEntity>()
                            .in(KnowSummaryEntity::getKnowId, knowledgePointIds));
            log.info("删除了条知识点摘要结果：{}", deletedSummaries);

            // 4. 删除示例题目和选项
            List<ExampleQuestionsEntity> exampleQuestionsList = exampleQuestionsService.getQuestionsByKnowleIds(knowledgePointIds);
            log.info("查询到 {} 个示例题目需要删除", exampleQuestionsList.size());

            if (CollectionUtil.isNotEmpty(exampleQuestionsList)) {
                List<Integer> questionIds = exampleQuestionsList.stream()
                        .map(ExampleQuestionsEntity::getId)
                        .collect(Collectors.toList());

                // 删除题目选项
                boolean deletedOptions = questionOptionsService.remove(
                        new LambdaQueryWrapper<QuestionOptionsEntity>()
                                .in(QuestionOptionsEntity::getQuestionId, questionIds));
                log.info("删除了 {} 条题目选项", deletedOptions);

                // 删除题目
                boolean deletedQuestions = exampleQuestionsService.removeBatchByIds(questionIds);
                log.info("删除了 {} 条示例题目", deletedQuestions);
            }

            // 5. 删除知识点
            boolean deletedKnowledgePoints = knowledgePointService.removeBatchByIds(knowledgePointIds);
            log.info("删除了 {} 条知识点", deletedKnowledgePoints);
        }

        // 6. 删除单元
        boolean deletedUnits = unitsService.removeBatchByIds(unitIds);
        log.info("删除了 {} 个单元", deletedUnits);

        // 7. 删除教材本身
        boolean result = materialService.removeById(id);
        log.info("教材删除完成, 结果: {}", result);
        return result;
    }

    @Override
    public boolean updateExampleQuestionsHtml(Integer id, Integer templateId) {
        log.info("更新教材下所有单元、知识点的示例题目的富文本，教材ID: {}, 模板ID: {}", id, templateId);
        RichTextTemplateEntity richTextTemplate = richTextTemplateService.getById(templateId);
        AssertUtils.notNull(richTextTemplate, ResultCodeEnum.NOT_FOUND_TEMPLATE);
        // 1. 获取教材下的所有单元
        List<UnitsEntity> units = unitsService.list(
                new LambdaQueryWrapper<UnitsEntity>()
                        .eq(UnitsEntity::getMaterialId, id)
        );

        if (CollectionUtil.isEmpty(units)) {
            log.info("教材下没有单元，无需更新");
            return true;
        }

        // 2. 获取单元下的所有知识点
        List<Integer> unitIds = units.stream()
                .map(UnitsEntity::getId)
                .collect(Collectors.toList());

        // 3. 获取知识点下的所有例题
        Collection<Integer> knowledgePointIds = unitKnowMappingService.getKnowIdListByUnitIds(unitIds);

        if (CollectionUtil.isEmpty(knowledgePointIds)) {
            log.info("教材下没有知识点，无需更新");
            return true;
        }
        // 4. 调用例题服务更新富文本内容
        boolean result = adminExampleQuestionsService.updateExampleQuestionsHtmlByKnowledgePointIds(knowledgePointIds, richTextTemplate);

        log.info("更新教材下所有单元、知识点的示例题目的富文本完成，结果: {}", result);
        return result;
    }

    /**
     * 填充教材额外信息（年级名称、版本名称、文档URL等）
     *
     * @param materialResps 教材响应列表
     */
    private void fillMaterialExtraInfo(List<MaterialWithUnitResp> materialResps, List<UnitsEntity> units) {
        if (CollectionUtil.isEmpty(materialResps)) {
            return;
        }

        // 收集需要查询的ID
        List<Integer> gradeIds = materialResps.stream()
                .map(MaterialWithUnitResp::getGradeId)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

        List<Integer> versionIds = materialResps.stream()
                .map(MaterialWithUnitResp::getVersionId)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

        List<Integer> docIds = materialResps.stream()
                .map(MaterialWithUnitResp::getDocId)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

        // 批量查询相关信息
        Map<Integer, GradeDTO> gradeMap = CollectionUtil.isNotEmpty(gradeIds) ?
                GradeUtils.getGradesByIds(gradeIds).stream()
                        .collect(Collectors.toMap(GradeDTO::getId, Function.identity(), (k1, k2) -> k1)) :
                new HashMap<>();

        Map<Integer, VersionsEntity> versionMap = CollectionUtil.isNotEmpty(versionIds) ?
                versionsService.listByIds(versionIds).stream()
                        .collect(Collectors.toMap(VersionsEntity::getId, Function.identity(), (k1, k2) -> k1)) :
                new HashMap<>();

        Map<Integer, MaterialDocEntity> docMap = CollectionUtil.isNotEmpty(docIds) ?
                materialDocService.getMaterialDocIdsByMaterialIds(docIds).stream()
                        .collect(Collectors.toMap(MaterialDocEntity::getId, Function.identity(), (k1, k2) -> k1)) :
                new HashMap<>();

        Map<Integer, UnitsEntity> unitMap = CollectionUtil.isNotEmpty(units) ?
                units.stream()
                        .collect(Collectors.toMap(UnitsEntity::getMaterialId, Function.identity(), (k1, k2) -> k1)) :
                new HashMap<>();
        // 填充信息
        materialResps.forEach(resp -> {
            // 填充年级名称
            GradeDTO gradeDTO = gradeMap.get(resp.getGradeId());
            if (gradeDTO != null) {
                resp.setGradeName(gradeDTO.getGrade());
            }

            // 填充版本名称
            VersionsEntity versionEntity = versionMap.get(resp.getVersionId());
            if (versionEntity != null) {
                resp.setVersionName(versionEntity.getVersionName());
            }

            // 填充文档URL
            MaterialDocEntity docEntity = docMap.get(resp.getDocId());
            if (docEntity != null) {
                resp.setDocUrl(docEntity.getTeacherMaterialUrl());
            }
            UnitsEntity unitsEntity = unitMap.get(resp.getId());
            if (unitsEntity != null) {
                resp.setUnitId(unitsEntity.getId());
                resp.setUnitName(unitsEntity.getUnitName());
            }
        });
    }
}