package com.seer.teach.teacher.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.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
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.PageConverterUtils;
import com.seer.teach.teacher.common.req.GetUnitsReq;
import com.seer.teach.teacher.common.resp.UnitKnowsResp;
import com.seer.teach.teacher.common.resp.UnitsResp;
import com.seer.teach.teacher.convert.KnowledgePointConvert;
import com.seer.teach.teacher.convert.UnitConvert;
import com.seer.teach.teacher.module.entity.KnowledgePointEntity;
import com.seer.teach.teacher.module.entity.MaterialEntity;
import com.seer.teach.teacher.module.entity.UnitKnowMappingEntity;
import com.seer.teach.teacher.module.entity.UnitsEntity;
import com.seer.teach.teacher.module.mapper.UnitsMapper;
import com.seer.teach.teacher.service.KnowledgePointQueryService;
import com.seer.teach.teacher.service.MaterialService;
import com.seer.teach.teacher.service.UnitsService;
import com.seer.teach.teacher.util.ModificationLogUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import jakarta.annotation.PostConstruct;
import java.io.Serializable;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author Wang
 * @since 2025-10-09 15:20:37
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class UnitsServiceImpl extends ServiceImpl<UnitsMapper, UnitsEntity> implements UnitsService {

    private final MaterialService materialService;

    private final KnowledgePointQueryService knowledgePointQueryService;

    private final Map<Integer, String> volumeMap = new HashMap<>();

    @PostConstruct
    public void init() {
        volumeMap.put(0, "上册");
        volumeMap.put(1, "下册");
        volumeMap.put(6, "第一册");
        volumeMap.put(7, "第二册");
        volumeMap.put(8, "第三册");
    }

    @Override
    public boolean save(UnitsEntity entity) {
        // 记录新增单元日志
        boolean result = super.save(entity);
        if (result) {
            ModificationLogUtils.logModification(
                    2, // 单元类型
                    entity.getId(),
                    entity.getUnitName(),
                    1, // 新增操作
                    null,
                    entity,
                    StpUtil.getLoginIdAsInt()
            );
        }
        return result;
    }

    @Override
    public boolean updateById(UnitsEntity entity) {
        // 获取修改前的数据
        UnitsEntity before = getById(entity.getId());
        
        // 更新数据
        boolean result = super.updateById(entity);
        
        // 记录修改日志
        if (result) {
            ModificationLogUtils.logModification(
                    2, // 单元类型
                    entity.getId(),
                    entity.getUnitName(),
                    2, // 修改操作
                    before,
                    entity,
                    StpUtil.getLoginIdAsInt()
            );
        }
        return result;
    }

    @Override
    public boolean removeById(Serializable id) {
        // 获取删除前的数据
        UnitsEntity before = getById(id);
        
        // 删除数据
        boolean result = super.removeById(id);
        
        // 记录删除日志
        if (result && before != null) {
            ModificationLogUtils.logModification(
                    2, // 单元类型
                    (Integer) id,
                    before.getUnitName(),
                    3, // 删除操作
                    before,
                    null,
                    StpUtil.getLoginIdAsInt()
            );
        }
        return result;
    }

    /**
     * 获取单元列表
     *
     * @param params 查询参数对象，包含学科ID、年级ID、页码和每页数量等信息
     * @return 分页的单元响应数据列表
     */
    @Override
    public PageListBean<UnitsResp> list( GetUnitsReq params) {
        if (params.getGradeId() >= 10) {
            params.setGradeId(10);
        }
        List<MaterialEntity> materials = materialService.list(new LambdaQueryWrapper<MaterialEntity>()
                .eq(MaterialEntity::getGradeId, params.getGradeId())
                .eq(MaterialEntity::getVolume, params.getVolume())
                .inSql(MaterialEntity::getVersionId,
                        "select id from teacher_versions where subject_id ="
                                + params.getSubjectId() +
                                " and (version_name like '%人教%' or version_name like '%统编%')"));
        log.info("教材列表：{}", materials);
        AssertUtils.notEmpty(materials, ResultCodeEnum.SUBJECT_IS_NOT_DATA);
        List<Integer> materialIds = materials.stream()
                .map(MaterialEntity::getId)
                .collect(Collectors.toList());

        Page<UnitsEntity> unitPage = new Page<>(params.getPage(), params.getLimits());
        Page<UnitsEntity> pageData = this.page(unitPage,
                new LambdaQueryWrapper<UnitsEntity>()
                        .in(UnitsEntity::getMaterialId, materialIds)
                        .orderByAsc(UnitsEntity::getMaterialId)
                        .orderByAsc(UnitsEntity::getSort)
        );

        List<UnitsEntity> unitList = pageData.getRecords();

        List<Integer> unitIds = unitList.stream()
                .map(UnitsEntity::getId)
                .collect(Collectors.toList());

        Collection<UnitKnowMappingEntity> knowMappingList = knowledgePointQueryService.getUnitKnowMappingListByUnitIds(unitIds);

        // 知识点和单元的映射
        Map<Integer, List<Integer>> knowUnitMapping = knowMappingList.stream().collect(Collectors.groupingBy(UnitKnowMappingEntity::getUnitId, Collectors.mapping(UnitKnowMappingEntity::getKnowledgePointId, Collectors.toList())));

        Set<Integer> knowIdList = knowMappingList.stream()
                .map(UnitKnowMappingEntity::getKnowledgePointId)
                .collect(Collectors.toSet());

        Collection<KnowledgePointEntity> knowList = knowledgePointQueryService.getKnowledgePointListByKnowIds(knowIdList);
        Map<Integer, KnowledgePointEntity> collect = knowList.stream().collect(Collectors.toMap(KnowledgePointEntity::getId, Function.identity()));

        Map<Integer, List<KnowledgePointEntity>> knowledgePointUnitMapping = new HashMap<>();
        for (UnitKnowMappingEntity knowMapping : knowMappingList) {
            Integer unitId = knowMapping.getUnitId();
            List<Integer> knowIds = knowUnitMapping.get(unitId);
            if (CollectionUtil.isEmpty(knowIds)) {
                continue;
            }
            List<KnowledgePointEntity> knowledgePointList = new ArrayList<>();
            for (Integer knowId : knowIds) {
                KnowledgePointEntity knowledgePointEntity = collect.get(knowId);
                knowledgePointList.add(knowledgePointEntity);
            }
            knowledgePointUnitMapping.put(unitId, knowledgePointList);
        }
        return PageConverterUtils.convertPageListBean(pageData, records -> records.stream().map(unit -> {
            UnitsResp resp = UnitConvert.INSTANCE.toUnitsResp(unit);
            List<UnitKnowsResp> knowRespList = knowledgePointUnitMapping.getOrDefault(unit.getId(), Collections.emptyList())
                    .stream()
                    .map(KnowledgePointConvert.INSTANCE::toUnitKnowsResp)
                    .collect(Collectors.toList());
            resp.setKnowPoints(knowRespList);
            return resp;
        }).collect(Collectors.toList()));
    }

}
