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

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.seer.teach.admin.convert.AdminUnitsConvert;
import com.seer.teach.admin.convert.MaterialConvert;
import com.seer.teach.admin.request.CheckAndScoreReq;
import com.seer.teach.admin.request.UnitMappingQueryReq;
import com.seer.teach.admin.request.UnitsQueryReq;
import com.seer.teach.admin.request.UnitsReq;
import com.seer.teach.admin.response.AdminUnitsResp;
import com.seer.teach.admin.response.UnitGradeSubjectResp;
import com.seer.teach.admin.response.UnitMaterialInfoResp;
import com.seer.teach.admin.service.AdminExampleQuestionsService;
import com.seer.teach.admin.service.AdminUnitsService;
import com.seer.teach.common.PageListBean;
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.PageConverterUtils;
import com.seer.teach.common.utils.SubjectUtils;
import com.seer.teach.teacher.module.entity.MaterialEntity;
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.IRichTextTemplateService;
import com.seer.teach.teacher.service.KnowledgePointService;
import com.seer.teach.teacher.service.MaterialService;
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.teacher.util.ModificationLogUtils;
import com.seer.teach.teacher.module.entity.ModificationLogEntity;
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.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.Collection;
import java.util.Collections;
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;

@Slf4j
@RequiredArgsConstructor
@Service
public class AdminUnitsServiceImpl implements AdminUnitsService {

    private final UnitsService unitsService;

    private final MaterialService materialService;

    private final KnowledgePointService knowledgePointService;

    private final AdminExampleQuestionsService adminExampleQuestionsService;

    private final IRichTextTemplateService richTextTemplateService;

    private final UnitKnowMappingService unitKnowMappingService;
    
    private final VersionsService versionsService;
    
    private final UserInfoServiceApi userInfoServiceApi;

    @Override
    public PageListBean<AdminUnitsResp> getPageList(UnitsQueryReq req) {
        // 自己实现分页逻辑
        Page<UnitsEntity> page = new Page<>(req.getPageNo(), req.getPageSize());
        LambdaQueryWrapper<UnitsEntity> queryWrapper = new LambdaQueryWrapper<>();
        
        // 根据查询条件构造查询条件
        if (req.getMaterialId() != null) {
            queryWrapper.eq(UnitsEntity::getMaterialId, req.getMaterialId());
        }
        if (StringUtils.hasText(req.getUnitName())) {
            queryWrapper.like(UnitsEntity::getUnitName, req.getUnitName());
        }
        if(Objects.nonNull(req.getIsChecked())){
            queryWrapper.eq(UnitsEntity::getIsChecked, req.getIsChecked());
        }
        if(CollUtil.isNotEmpty(req.getUpdateBy())){
            queryWrapper.in(UnitsEntity::getUpdateBy, req.getUpdateBy());
        }
        queryWrapper.orderByAsc(UnitsEntity::getSort);
        
        // 执行分页查询
        Page<UnitsEntity> resultPage = unitsService.page(page, queryWrapper);

        if(CollectionUtil.isEmpty(resultPage.getRecords())){
            return new PageListBean<>();
        }
        PageListBean<AdminUnitsResp> result = PageConverterUtils.convertPageListBean(resultPage, AdminUnitsConvert.INSTANCE::convertEntity2RespList);

        Set<Integer> materialIds = result.getList().stream().map(AdminUnitsResp::getMaterialId).collect(Collectors.toSet());

        List<MaterialEntity> materials = materialService.list(new LambdaQueryWrapper<>(MaterialEntity.class).in(com.seer.teach.teacher.module.entity.MaterialEntity::getId, materialIds));

        Map<Integer, MaterialEntity> mapping = materials.stream().collect(Collectors.toMap(MaterialEntity::getId, material -> material));

        // 收集所有需要查询的用户ID
        Set<Integer> updateUserIds = result.getList().stream()
                .map(AdminUnitsResp::getUpdateBy)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());

        // 批量获取用户信息
        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.getUserName() != null)
                        .collect(Collectors.toMap(UserInfoDTO::getId, UserInfoDTO::getUserName));
            } catch (Exception e) {
                log.warn("获取用户信息失败，错误信息：{}", e.getMessage());
            }
        }

        for(AdminUnitsResp resp : result.getList()){
            MaterialEntity material = mapping.get(resp.getMaterialId());
            if(material != null){
                resp.setMaterial(MaterialConvert.INSTANCE.entityToResp(material));
            }
            // 设置更新人姓名
            Integer updateBy = resp.getUpdateBy();
            if (updateBy != null) {
                resp.setUpdateByName(updateUserNamesMap.get(updateBy));
            }
        }
        return result;
    }

    /**
     * 更新单元信息
     *
     * @param id  单元ID
     * @param req 更新请求参数
     * @return 是否更新成功
     */
    @Override
    public boolean updateUnits(Integer id, UnitsReq req) {
        // 获取修改前的数据
        UnitsEntity before = unitsService.getById(id);
        UnitsEntity entity = new UnitsEntity();
        entity.setId(id);
        entity.setMaterialId(req.getMaterialId());
        entity.setUnitName(req.getUnitName());
        entity.setSort(req.getSort());
        entity.setUpdateBy(StpUtil.getLoginIdAsString());
        entity.setUpdateTime(LocalDateTime.now());
        boolean result = unitsService.updateById(entity);
        
        // 记录修改日志
        if (result) {
            UnitsEntity after = unitsService.getById(id);
            ModificationLogUtils.logModification(
                    ModificationLogEntity.TARGET_TYPE_UNIT,
                    id,
                    "单元",
                    ModificationLogEntity.OPERATION_TYPE_UPDATE,
                    before,
                    after,
                    StpUtil.getLoginIdAsInt()
            );
        }
        return result;
    }

    /**
     * 更新单元检查状态和评分
     *
     * @param id  单元ID
     * @param req 检查状态和评分信息
     * @return 是否更新成功
     */
    @Override
    public boolean updateUnitsCheckAndScore(Integer id, CheckAndScoreReq req) {
        // 获取修改前的数据
        UnitsEntity before = unitsService.getById(id);
        UnitsEntity entity = new UnitsEntity();
        entity.setId(id);
        entity.setIsChecked(req.getIsChecked());
        entity.setScore(req.getScore());
        entity.setUpdateBy(StpUtil.getLoginIdAsString());
        entity.setUpdateTime(LocalDateTime.now());
        boolean result = unitsService.updateById(entity);
        
        // 记录修改日志
        if (result) {
            UnitsEntity after = unitsService.getById(id);
            ModificationLogUtils.logModification(
                    ModificationLogEntity.TARGET_TYPE_UNIT,
                    id,
                    "单元",
                    ModificationLogEntity.OPERATION_TYPE_UPDATE,
                    before,
                    after,
                    StpUtil.getLoginIdAsInt()
            );
        }
        return result;
    }

    /**
     * 批量更新单元检查状态
     *
     * @param ids ID列表
     * @param isChecked 检查状态
     * @return 是否更新成功
     */
    @Override
    public boolean batchUpdateUnitsCheck(List<Integer> ids, Integer isChecked) {
        // 获取修改前的数据
        List<UnitsEntity> beforeList = unitsService.listByIds(ids);
        Map<Integer, UnitsEntity> beforeMap = beforeList.stream()
                .collect(Collectors.toMap(UnitsEntity::getId, Function.identity()));
                
        List<UnitsEntity> entities = ids.stream().map(id -> {
            UnitsEntity entity = new UnitsEntity();
            entity.setId(id);
            entity.setIsChecked(isChecked);
            entity.setUpdateBy(StpUtil.getLoginIdAsString());
            entity.setUpdateTime(LocalDateTime.now());
            return entity;
        }).collect(Collectors.toList());
        
        boolean result = unitsService.updateBatchById(entities);
        
        // 记录修改日志
        if (result) {
            List<UnitsEntity> afterList = unitsService.listByIds(ids);
            for (UnitsEntity after : afterList) {
                UnitsEntity before = beforeMap.get(after.getId());
                if (before != null) {
                    ModificationLogUtils.logModification(
                            ModificationLogEntity.TARGET_TYPE_UNIT,
                            after.getId(),
                            "单元",
                            ModificationLogEntity.OPERATION_TYPE_UPDATE,
                            before,
                            after,
                            StpUtil.getLoginIdAsInt()
                    );
                }
            }
        }
        return result;
    }

    @Override
    public boolean createdUnits(UnitsReq req) {
        UnitsEntity entity = new UnitsEntity();
        entity.setMaterialId(req.getMaterialId());
        entity.setUnitName(req.getUnitName());
        entity.setIsChecked(req.getIsCheck());
        entity.setScore(req.getScore());
        entity.setSort(req.getSort());
        boolean result = unitsService.save(entity);
        
        // 记录新增日志
        if (result) {
            ModificationLogUtils.logModification(
                    ModificationLogEntity.TARGET_TYPE_UNIT,
                    entity.getId(),
                    "单元",
                    ModificationLogEntity.OPERATION_TYPE_ADD,
                    null,
                    entity,
                    StpUtil.getLoginIdAsInt()
            );
        }
        return result;
    }

    @Override
    public boolean deleteUnits(Integer id) {
        // 获取删除前的数据
        UnitsEntity before = unitsService.getById(id);
        boolean result = unitsService.removeById(id);
        
        // 记录删除日志
        if (result && before != null) {
            ModificationLogUtils.logModification(
                    ModificationLogEntity.TARGET_TYPE_UNIT,
                    id,
                    "单元",
                    ModificationLogEntity.OPERATION_TYPE_DELETE,
                    before,
                    null,
                    StpUtil.getLoginIdAsInt()
            );
        }
        return result;
    }

    /**
     * 根据ID获取单元详情
     *
     * @param id 单元ID
     * @return 单元详情
     */
    @Override
    public AdminUnitsResp getUnitDetailById(Integer id) {
        // 记录查看日志
        ModificationLogUtils.logModification(
                ModificationLogEntity.TARGET_TYPE_UNIT,
                id,
                "单元",
                ModificationLogEntity.OPERATION_TYPE_VIEW,
                StpUtil.getLoginIdAsInt(),
                "查看单元详情"
        );
        return AdminUnitsConvert.INSTANCE.convert(unitsService.getById(id));
    }

    @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<UnitKnowMappingEntity> mappings = unitKnowMappingService.list(
                new LambdaQueryWrapper<UnitKnowMappingEntity>()
                        .eq(UnitKnowMappingEntity::getUnitId, id)
        );

        if (CollectionUtil.isEmpty(mappings)) {
            log.info("单元下没有知识点，无需更新");
            return true;
        }

        // 2. 获取知识点下的所有例题
        List<Integer> knowledgePointIds = mappings.stream()
                .map(UnitKnowMappingEntity::getKnowledgePointId)
                .collect(Collectors.toList());

        // 3. 更新例题的富文本内容（这里需要具体的实现逻辑）

        boolean result = adminExampleQuestionsService.updateExampleQuestionsHtmlByKnowledgePointIds(knowledgePointIds, richTextTemplate);

        log.info("更新单元下所有知识点的示例题目的富文本完成，结果: {}", result);
        return result;
    }
    
    @Override
    public UnitGradeSubjectResp getUnitGradeAndSubject(Integer unitId) {
        // 1. 获取单元信息
        UnitsEntity unit = unitsService.getById(unitId);
        if (unit == null) {
            throw new RuntimeException("单元不存在");
        }
        
        // 2. 获取教材信息
        MaterialEntity material = materialService.getById(unit.getMaterialId());
        if (material == null) {
            throw new RuntimeException("教材不存在");
        }
        
        // 3. 获取版本信息（包含学科ID）
        VersionsEntity version =
            versionsService.getById(material.getVersionId());
        if (version == null) {
            throw new RuntimeException("版本不存在");
        }
        // 4. 构造返回结果
        UnitGradeSubjectResp resp = new UnitGradeSubjectResp();
        resp.setUnitId(unitId);
        resp.setGradeId(material.getGradeId());
        resp.setSubjectId(version.getSubjectId());
        return resp;
    }
    
    @Override
    public List<UnitMaterialInfoResp> getUnitMaterialInfo(UnitMappingQueryReq req) {
        List<UnitMaterialInfoResp> result = getMaterialInfo(req.getKnowledgePointId());
        if(CollectionUtil.isEmpty(result)){
            return Collections.emptyList();
        }
        return result.stream()
                .filter(item -> !item.getUnitId().equals(req.getUnitId()))
                .collect(Collectors.toList());
    }

    @Override
    public List<UnitMaterialInfoResp> getMaterialInfo(Integer id) {
        // 1. 根据知识点ID获取所有关联的单元映射信息，排除当前单元
        Collection<UnitKnowMappingEntity> mappings = unitKnowMappingService.getListByKnowIds(Collections.singletonList(id));

        if (CollectionUtil.isEmpty(mappings)) {
            return Collections.emptyList();
        }

        // 2. 过滤掉当前单元，并提取单元ID列表
        List<Integer> unitIds = mappings.stream()
                .map(UnitKnowMappingEntity::getUnitId)
                .collect(Collectors.toList());

        if (CollectionUtil.isEmpty(unitIds)) {
            return Collections.emptyList();
        }

        // 3. 获取单元信息
        List<UnitsEntity> units = unitsService.listByIds(unitIds);
        if (CollectionUtil.isEmpty(units)) {
            return Collections.emptyList();
        }

        // 4. 获取教材ID列表
        Set<Integer> materialIds = units.stream()
                .map(UnitsEntity::getMaterialId)
                .collect(Collectors.toSet());

        // 5. 获取教材信息
        List<MaterialEntity> materials = materialService.listByIds(materialIds);
        if (CollectionUtil.isEmpty(materials)) {
            return Collections.emptyList();
        }

        // 6. 获取版本ID列表
        Set<Integer> versionIds = materials.stream()
                .map(MaterialEntity::getVersionId)
                .collect(Collectors.toSet());

        // 7. 获取版本信息
        List<VersionsEntity> versions = versionsService.listByIds(versionIds);

        // 8. 构建映射关系
        Map<Integer, MaterialEntity> materialMap = materials.stream()
                .collect(Collectors.toMap(MaterialEntity::getId, Function.identity()));

        Map<Integer, VersionsEntity> versionMap = versions.stream()
                .collect(Collectors.toMap(VersionsEntity::getId, Function.identity()));

        // 9. 构造返回结果
        return units.stream().map(unit -> {
            UnitMaterialInfoResp resp = new UnitMaterialInfoResp();
            resp.setUnitId(unit.getId());
            resp.setUnitName(unit.getUnitName());

            MaterialEntity material = materialMap.get(unit.getMaterialId());
            if (material != null) {
                resp.setMaterialId(material.getId());
                resp.setMaterialName(material.getBookName());
                resp.setGradeId(material.getGradeId());
                resp.setGradeName(GradeUtils.getNameById(material.getGradeId()));
                resp.setDocId(material.getDocId());
                VersionsEntity version = versionMap.get(material.getVersionId());
                if (version != null) {
                    resp.setVersionId(version.getId());
                    resp.setVersionName(version.getVersionName());
                    resp.setSubjectId(version.getSubjectId());
                    resp.setSubjectName(SubjectUtils.getSubjectNameBySubjectId(version.getSubjectId()));
                }
            }
            return resp;
        }).collect(Collectors.toList());
    }
}