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

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.seer.teach.common.utils.GradeUtils;
import com.seer.teach.common.utils.SubjectUtils;
import com.seer.teach.teacher.module.entity.*;
import com.seer.teach.teacher.module.mapper.KnowledgePointsMapper;
import com.seer.teach.teacher.module.mapper.UnitsMapper;
import com.seer.teach.teacher.module.param.KnowledgePointSearchParam;
import com.seer.teach.teacher.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

/**
 * <p>
 * 知识点表查询服务实现类
 * </p>
 *
 * @author Wang
 * @since 2025-10-09 15:20:36
 */
@Service
@Slf4j
public class KnowledgePointServiceQueryImpl implements KnowledgePointQueryService {

    @Autowired
    private UnitKnowMappingService unitKnowMappingService;

    @Autowired
    private UnitsMapper unitsMapper;

    @Autowired
    private MaterialService materialService;

    @Autowired
    private VersionsService versionsService;

    @Autowired
    private KnowledgePointsMapper knowledgePointsMapper;

    @Autowired
    private KnowSummaryService knowSummaryService;

    @Override
    public Collection<Integer> getUnitIdsByGradeIds(Set<Integer> gradeIds) {
        if(CollUtil.isEmpty(gradeIds)){
            return Collections.emptyList();
        }
        List<MaterialEntity> materials = materialService.list(new LambdaQueryWrapper<>(MaterialEntity.class).in(MaterialEntity::getGradeId, gradeIds));
        if (CollectionUtil.isEmpty(materials)) {
            return Collections.emptyList();
        }
        Set<Integer> materialIds = materials.stream().map(MaterialEntity::getId).collect(Collectors.toSet());
        // 根据教材ID查询单元
        List<UnitsEntity> units = unitsMapper.selectList(new LambdaQueryWrapper<UnitsEntity>()
                .in(UnitsEntity::getMaterialId, materialIds));
        if (CollectionUtil.isEmpty(units)) {
            return Collections.emptyList();
        }
        // 提取单元ID
        Set<Integer> unitIds = units.stream().map(UnitsEntity::getId).collect(Collectors.toSet());
        log.debug("找到 {} 个符合条件的单元", units.size());
        return unitIds;
    }

    @Override
    public Collection<Integer> getUnitIdsByGradeIdsAndVersionIdsAndSubjetIds(Set<Integer> gradeIds, Set<Integer> versionIds, Set<Integer> subjectIds) {
        // 构建查询教材的条件
        LambdaQueryWrapper<MaterialEntity> materialQueryWrapper = new LambdaQueryWrapper<>();
        if (CollUtil.isNotEmpty(gradeIds)) {
            materialQueryWrapper.in(MaterialEntity::getGradeId, gradeIds);
        }
        List<VersionsEntity> versionsEntities = versionsService.list(new LambdaQueryWrapper<>(VersionsEntity.class)
                .in(CollUtil.isNotEmpty(versionIds),VersionsEntity::getId, versionIds)
                .in(CollUtil.isNotEmpty(subjectIds),VersionsEntity::getSubjectId, subjectIds));
        if(CollectionUtil.isNotEmpty(versionsEntities)){
            Set<Integer> versionIdList = versionsEntities.stream().map(VersionsEntity::getId).collect(Collectors.toSet());
            materialQueryWrapper.in(MaterialEntity::getVersionId, versionIdList);
        }
        // 查询符合条件的教材
        List<MaterialEntity> materials = materialService.list(materialQueryWrapper);
        if (CollectionUtil.isEmpty(materials)) {
            log.debug("未找到符合条件的教材");
            return Collections.emptySet();
        }
        Set<Integer> materialIds = materials.stream().map(MaterialEntity::getId).collect(Collectors.toSet());
        log.debug("找到 {} 个符合条件的教材，教材ID集合：{}", materials.size(), materialIds);
        // 根据教材ID查询单元
        List<UnitsEntity> units = unitsMapper.selectList(new LambdaQueryWrapper<UnitsEntity>()
                .in(UnitsEntity::getMaterialId, materialIds));
        if (CollectionUtil.isEmpty(units)) {
            log.debug("未找到符合条件的单元");
            return Collections.emptySet();
        }
        // 提取单元ID
        Set<Integer> unitIds = units.stream().map(UnitsEntity::getId).collect(Collectors.toSet());
        log.debug("找到 {} 个符合条件的单元，单元ID集合：{}", units.size(), unitIds);
        return unitIds;
    }

    @Override
    public Collection<Integer> getUnitIdsByGradeIdsAndVersionIds(Set<Integer> gradeIds, Set<Integer> versionIds) {
        return getUnitIdsByGradeIdsAndVersionIdsAndSubjetIds(gradeIds, versionIds, null);
    }

    @Override
    public Collection<Integer> getKnowIdsByConditions(KnowledgePointSearchParam param) {
        return knowledgePointsMapper.getKnowIdsByConditions(param);
    }

    @Override
    public Collection<KnowledgePointEntity> getKnowListByGradeIdsAndSubjectIdsOrElseEmpty(Set<Integer> gradeIds, Set<Integer> subjectIds) {
        if (CollectionUtil.isEmpty(gradeIds) || CollectionUtil.isEmpty(subjectIds)){
            return Collections.emptyList();
        }
        List<MaterialEntity> materialEntities = materialService.list(new LambdaQueryWrapper<>(MaterialEntity.class).in(MaterialEntity::getGradeId, gradeIds));
        if(CollectionUtil.isEmpty(materialEntities)){
            return Collections.emptyList();
        }
        Set<Integer> materialIds = materialEntities.stream().map(MaterialEntity::getId).collect(Collectors.toSet());
        List<UnitsEntity> units = unitsMapper.selectList(new LambdaQueryWrapper<>(UnitsEntity.class).in(UnitsEntity::getMaterialId, materialIds));
        if(CollectionUtil.isEmpty(units)){
            return Collections.emptyList();
        }
        Set<Integer> unitIds = units.stream().map(UnitsEntity::getId).collect(Collectors.toSet());
        Collection<Integer> knowIds = getKnowIdListByUnitIds(unitIds);
        if(CollectionUtil.isEmpty(knowIds)){
            return Collections.emptyList();
        }
        return knowledgePointsMapper.selectList(new LambdaQueryWrapper<>(KnowledgePointEntity.class)
                .in(KnowledgePointEntity::getId, knowIds)
                .in(KnowledgePointEntity::getSubjectId, subjectIds));
    }

    @Override
    public Collection<Integer> getKnowIdsByGradeIdsAndVersionIds(Set<Integer> gradeIds, Set<Integer> versionIds) {
        Collection<Integer> unitIds = getUnitIdsByGradeIdsAndVersionIds(gradeIds, versionIds);
        if (CollectionUtil.isEmpty(unitIds)) {
            return Collections.emptySet();
        }
        return getKnowIdListByUnitIds(unitIds);
    }


    @Override
    public Collection<UnitKnowMappingEntity> getUnitKnowMappingListByUnitIds(Collection<Integer> unitIds) {
        if (CollectionUtil.isEmpty(unitIds)) {
            return Collections.emptyList();
        }
        return unitKnowMappingService.list(new LambdaQueryWrapper<>(UnitKnowMappingEntity.class).in(UnitKnowMappingEntity::getUnitId, unitIds));
    }

    @Override
    public Collection<UnitKnowMappingEntity> getUnitKnowMappingListByKnowIds(Collection<Integer> knowIds) {
        if (CollectionUtil.isEmpty(knowIds)) {
            return Collections.emptyList();
        }
        return unitKnowMappingService.list(new LambdaQueryWrapper<>(UnitKnowMappingEntity.class).in(UnitKnowMappingEntity::getKnowledgePointId, knowIds));
    }

    @Override
    public Collection<UnitKnowMappingEntity> getUnitKnowMappingListByKnowId(Integer knowId) {
        return unitKnowMappingService.list(new LambdaQueryWrapper<>(UnitKnowMappingEntity.class).eq(UnitKnowMappingEntity::getKnowledgePointId, knowId));
    }

    @Override
    public UnitKnowMappingEntity getUnitKnowMappingByUnitIdAndKnowId(Integer unitId, Integer knowId) {
        return unitKnowMappingService.getOne(new LambdaQueryWrapper<>(UnitKnowMappingEntity.class).eq(UnitKnowMappingEntity::getUnitId,unitId)
                .eq(UnitKnowMappingEntity::getKnowledgePointId,knowId));
    }

    @Override
    public Collection<KnowledgePointEntity> getKnowledgePointListByKnowIds(Collection<Integer> knowIds) {
        if (CollectionUtil.isEmpty(knowIds)) {
            return Collections.emptyList();
        }
        return knowledgePointsMapper.selectList(new LambdaQueryWrapper<>(KnowledgePointEntity.class).in(KnowledgePointEntity::getId, knowIds));
    }

    @Override
    public Collection<KnowledgePointEntity> getKnowledgePointListByKnowIdsOrName(Collection<Integer> knowIds, String knowName) {
        if (CollectionUtil.isEmpty(knowIds)) {
            return Collections.emptyList();
        }
        return knowledgePointsMapper.selectList(new LambdaQueryWrapper<>(KnowledgePointEntity.class)
                .in(KnowledgePointEntity::getId, knowIds)
                .like(StringUtils.isNotBlank(knowName), KnowledgePointEntity::getKnowledgePointName, knowName));
    }

    @Override
    public Collection<KnowledgePointEntity> getKnowledgePointListByIdsOrElseAll(Collection<Integer> knowIds) {
        return knowledgePointsMapper.selectList(new LambdaQueryWrapper<>(KnowledgePointEntity.class).in(CollUtil.isNotEmpty(knowIds), KnowledgePointEntity::getId, knowIds));
    }

    @Override
    public Collection<KnowledgePointEntity> getKnowledgePointListBySubjectId(Integer subjectId) {
        return knowledgePointsMapper.selectList(new LambdaQueryWrapper<>(KnowledgePointEntity.class).eq(KnowledgePointEntity::getSubjectId, subjectId));
    }

    @Override
    public KnowledgePointEntity getKnowledgePointByKnowId(Integer knowId) {
        if (knowId == null) {
            return null;
        }
        KnowledgePointEntity knowledgePointEntity = knowledgePointsMapper.selectById(knowId);
        if (knowledgePointEntity == null) {
            return null;
        }
        KnowSummaryEntity summary = knowSummaryService.getOneByKnowId(knowId);
        if (summary != null) {
            knowledgePointEntity.setSummary(summary.getSummary());
        }
        return knowledgePointEntity;
    }

    @Override
    public Collection<Integer> getUnitIdsByKnowId(Integer knowId) {
        List<UnitKnowMappingEntity> unitKnowMappingEntities = unitKnowMappingService.list(new LambdaQueryWrapper<>(UnitKnowMappingEntity.class).eq(UnitKnowMappingEntity::getKnowledgePointId, knowId));
        if (CollectionUtil.isEmpty(unitKnowMappingEntities)) {
            return Collections.emptyList();
        }
        return unitKnowMappingEntities.stream().map(UnitKnowMappingEntity::getUnitId).collect(Collectors.toSet());
    }

    @Override
    public UnitsEntity getUnitByUnitId(Integer unitId) {
        return unitsMapper.selectById(unitId);
    }

    @Override
    public Collection<Integer> getKnowIdListByUnitId(Integer unitId) {
        List<UnitKnowMappingEntity> unitKnowMappingEntities = unitKnowMappingService.list(new LambdaQueryWrapper<>(UnitKnowMappingEntity.class).eq(UnitKnowMappingEntity::getUnitId, unitId));
        if (CollectionUtil.isEmpty(unitKnowMappingEntities)) {
            return Collections.emptyList();
        }
        return unitKnowMappingEntities.stream().map(UnitKnowMappingEntity::getKnowledgePointId).collect(Collectors.toSet());
    }

    @Override
    public Collection<Integer> getKnowIdListByUnitIds(Collection<Integer> unitIds) {
        List<UnitKnowMappingEntity> unitKnowMappingEntities = unitKnowMappingService.list(new LambdaQueryWrapper<>(UnitKnowMappingEntity.class).in(UnitKnowMappingEntity::getUnitId, unitIds));
        if (CollectionUtil.isEmpty(unitKnowMappingEntities)) {
            return Collections.emptyList();
        }
        return unitKnowMappingEntities.stream().map(UnitKnowMappingEntity::getKnowledgePointId).collect(Collectors.toSet());
    }

    @Override
    public Integer getUnitIdByKnowId(Integer knowId) {
        UnitKnowMappingEntity one = unitKnowMappingService.getOne(new LambdaQueryWrapper<>(UnitKnowMappingEntity.class).eq(UnitKnowMappingEntity::getKnowledgePointId, knowId));
        if (one != null) {
            return one.getUnitId();
        }
        return null;
    }

    @Override
    public List<UnitsEntity> getUnitListByMaterialIds(Collection<Integer> materialIds) {
        if (CollectionUtil.isEmpty(materialIds)) {
            return Collections.emptyList();
        }
        return unitsMapper.selectList(new LambdaQueryWrapper<>(UnitsEntity.class).in(UnitsEntity::getMaterialId, materialIds));
    }

    @Override
    public List<UnitsEntity> getUnitListByUnitIds(Collection<Integer> unitIds) {
        if (CollectionUtil.isEmpty(unitIds)) {
            return Collections.emptyList();
        }
        return unitsMapper.selectByIds(unitIds);
    }

    @Override
    public List<VersionsEntity> getVersionListBySubjectIds(Collection<Integer> subjectIds) {
        if (CollectionUtil.isEmpty(subjectIds)) {
            return Collections.emptyList();
        }
        return versionsService.list(new LambdaQueryWrapper<>(VersionsEntity.class).in(VersionsEntity::getSubjectId, subjectIds));
    }

    @Override
    public Collection<MaterialEntity> getMaterialListByKnowId(Integer knowId) {
        List<UnitKnowMappingEntity> unitKnowMappingEntities = unitKnowMappingService.list(new LambdaQueryWrapper<>(UnitKnowMappingEntity.class).eq(UnitKnowMappingEntity::getKnowledgePointId, knowId));
        if (CollectionUtil.isEmpty(unitKnowMappingEntities)) {
            return Collections.emptyList();
        }
        List<Integer> unitIds = unitKnowMappingEntities.stream().map(UnitKnowMappingEntity::getUnitId).collect(Collectors.toList());
        List<UnitsEntity> unitsEntities = unitsMapper.selectList(new LambdaQueryWrapper<>(UnitsEntity.class).in(UnitsEntity::getId, unitIds));
        if (CollectionUtil.isEmpty(unitsEntities)) {
            return Collections.emptyList();
        }
        List<Integer> materialIds = unitsEntities.stream().map(UnitsEntity::getMaterialId).collect(Collectors.toList());
        return materialService.list(new LambdaQueryWrapper<>(MaterialEntity.class).in(MaterialEntity::getId, materialIds));
    }

    @Override
    public Collection<MaterialEntity> getMaterialListByMaterialIds(Collection<Integer> materialIds) {
        if (CollectionUtil.isEmpty(materialIds)) {
            return Collections.emptyList();
        }
        return materialService.listByIds(materialIds);
    }

    @Override
    public MaterialEntity getMaterialByMaterialId(Integer materialId) {
        return materialService.getById(materialId);
    }

    @Override
    public Collection<MaterialEntity> getMaterialListByKnowIds(Collection<Integer> knowIds) {
        List<UnitKnowMappingEntity> unitKnowMappingEntities = unitKnowMappingService.list(new LambdaQueryWrapper<>(UnitKnowMappingEntity.class).in(UnitKnowMappingEntity::getKnowledgePointId, knowIds));
        if (CollectionUtil.isEmpty(unitKnowMappingEntities)) {
            return Collections.emptyList();
        }
        List<Integer> unitIds = unitKnowMappingEntities.stream().map(UnitKnowMappingEntity::getUnitId).collect(Collectors.toList());
        List<UnitsEntity> unitsEntities = unitsMapper.selectList(new LambdaQueryWrapper<>(UnitsEntity.class).in(UnitsEntity::getId, unitIds));
        if (CollectionUtil.isEmpty(unitsEntities)) {
            return Collections.emptyList();
        }
        List<Integer> materialIds = unitsEntities.stream().map(UnitsEntity::getMaterialId).collect(Collectors.toList());
        return materialService.list(new LambdaQueryWrapper<>(MaterialEntity.class).in(MaterialEntity::getId, materialIds));
    }

    @Override
    public Map<Integer, List<MaterialEntity>> getKnowIdMaterialRelationByKnowIds(Collection<Integer> knowIds) {
        Collection<UnitKnowMappingEntity> unitKnowMappingList = this.getUnitKnowMappingListByKnowIds(knowIds);

        if (unitKnowMappingList.isEmpty()) {
            return Collections.emptyMap();
        }
        List<Integer> unitList = unitKnowMappingList.stream()
                .map(UnitKnowMappingEntity::getUnitId)
                .distinct()
                .collect(Collectors.toList());
        if(CollectionUtil.isEmpty(unitList)){
            return Collections.emptyMap();
        }
        Map<Integer, UnitsEntity> unitMap = this.getUnitListByUnitIds(unitList)
                .stream()
                .collect(Collectors.toMap(UnitsEntity::getId, Function.identity(), (v1, v2) -> v1));
        if(CollectionUtil.isEmpty(unitMap)){
            return Collections.emptyMap();
        }
        Set<Integer> materialIds = unitMap.values().stream()
                .map(UnitsEntity::getMaterialId)
                .collect(Collectors.toSet());

        List<MaterialEntity> materialEntities = materialService.listByIds(materialIds);
        if(CollectionUtil.isEmpty(materialEntities)){
            return Collections.emptyMap();
        }
        Map<Integer, MaterialEntity> materialMap = materialEntities
                .stream()
                .collect(Collectors.toMap(MaterialEntity::getId, Function.identity()));

        Map<Integer, List<MaterialEntity>> knowIdToMaterials = new HashMap<>();

        for (UnitKnowMappingEntity mapping : unitKnowMappingList) {
            Integer knowId = mapping.getKnowledgePointId();
            Integer unitId = mapping.getUnitId();

            UnitsEntity unit = unitMap.get(unitId);
            if (unit == null) {
                continue;
            }
            MaterialEntity material = materialMap.get(unit.getMaterialId());
            if (material == null){
                continue;
            }
            knowIdToMaterials.computeIfAbsent(knowId, k -> new ArrayList<>()).add(material);
        }
        return knowIdToMaterials;
    }

    @Override
    public Map<Integer, List<UnitsEntity>> getKnowIdUnitRelationByKnowIds(Collection<Integer> knowIds) {
        if (CollectionUtil.isEmpty(knowIds)) {
            return Collections.emptyMap();
        }
        Collection<UnitKnowMappingEntity> unitKnowMappingList = this.getUnitKnowMappingListByKnowIds(knowIds);

        if (CollectionUtil.isEmpty(unitKnowMappingList)) {
            return Collections.emptyMap();
        }
        List<Integer> unitList = unitKnowMappingList.stream()
                .map(UnitKnowMappingEntity::getUnitId)
                .distinct()
                .collect(Collectors.toList());
        if(CollectionUtil.isEmpty(unitList)){
            return Collections.emptyMap();
        }
        Map<Integer, UnitsEntity> unitMap = this.getUnitListByUnitIds(unitList)
                .stream()
                .collect(Collectors.toMap(UnitsEntity::getId, Function.identity(), (v1, v2) -> v1));
        if(CollectionUtil.isEmpty(unitMap)){
            return Collections.emptyMap();
        }
        Map<Integer, List<UnitsEntity>> knowIdToUnits = new HashMap<>();

        for (UnitKnowMappingEntity mapping : unitKnowMappingList) {
            Integer knowId = mapping.getKnowledgePointId();
            Integer unitId = mapping.getUnitId();

            UnitsEntity unit = unitMap.get(unitId);
            if (unit == null) {
                continue;
            }
            knowIdToUnits.computeIfAbsent(knowId, k -> new ArrayList<>()).add(unit);
        }
        return knowIdToUnits;
    }

    @Override
    public Collection<VersionsEntity> getVersionListByVersionIds(Collection<Integer> versionIds) {
        if (versionIds.isEmpty()) {
            return Collections.emptyList();
        }
        return versionsService.listByIds(versionIds);
    }

    @Override
    public VersionsEntity getVersionByVersionId(Integer versionId) {
        return versionsService.getById(versionId);
    }
    
    @Override
    public String getSubjectNameByKnowId(Integer knowId) {
        KnowledgePointEntity knowledgePoint = getKnowledgePointByKnowId(knowId);
        if (knowledgePoint != null && knowledgePoint.getSubjectId() != null) {
            return SubjectUtils.getSubjectNameBySubjectId(knowledgePoint.getSubjectId());
        }
        return null;
    }
    
    @Override
    public List<String> getGradeNamesByKnowId(Integer knowId) {
        Collection<MaterialEntity> materials = getMaterialListByKnowId(knowId);
        if (CollectionUtil.isNotEmpty(materials)) {
            Set<Integer> gradeIds = materials.stream()
                    .map(MaterialEntity::getGradeId)
                    .filter(Objects::nonNull)
                    .collect(Collectors.toSet());
            
            return gradeIds.stream()
                    .map(GradeUtils::getNameById)
                    .collect(Collectors.toList());
        }
        return Collections.emptyList();
    }
}