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

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.seer.teach.admin.request.BatchSaveSplitKnowledgePointsReq;
import com.seer.teach.admin.request.KnowledgePointSplitReq;
import com.seer.teach.admin.response.KnowledgePointSplitResp;
import com.seer.teach.admin.response.QuestionOptionsResp;
import com.seer.teach.teacher.service.AiModelCallService;
import com.seer.teach.admin.service.KnowledgePointSplitService;
import com.seer.teach.teacher.service.platform.LlmResponse;
import com.seer.teach.admin.util.PromptBuilder;
import com.seer.teach.common.enums.AiScenarioCodeEnum;
import com.seer.teach.common.enums.ResultCodeEnum;
import com.seer.teach.common.utils.AssertUtils;
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.MaterialEntity;
import com.seer.teach.teacher.module.entity.QuestionOptionsEntity;
import com.seer.teach.teacher.module.entity.UnitKnowMappingEntity;
import com.seer.teach.teacher.service.ExampleQuestionsService;
import com.seer.teach.teacher.service.KnowSummaryService;
import com.seer.teach.teacher.service.KnowledgePointQueryService;
import com.seer.teach.teacher.service.KnowledgePointService;
import com.seer.teach.teacher.service.QuestionOptionsService;
import com.seer.teach.teacher.service.UnitKnowMappingService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 知识点拆分服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class KnowledgePointSplitServiceImpl implements KnowledgePointSplitService {

    private final KnowledgePointQueryService knowledgePointQueryService;

    private final KnowledgePointService knowledgePointService;

    private final UnitKnowMappingService unitKnowMappingService;

    private final KnowSummaryService knowSummaryService;

    private final AiModelCallService aiModelCallService;

    private final ExampleQuestionsService exampleQuestionsService;

    private final QuestionOptionsService questionOptionsService;

    /**
     * 拆分知识点
     *
     * @param req 知识点拆分请求
     * @return 拆分后的知识点列表
     */
    @Override
    public List<KnowledgePointSplitResp> splitKnowledgePoint(KnowledgePointSplitReq req) {
        log.info("开始拆分知识点，请求参数: {}", req);

        // 1. 查询知识点信息
        Integer knowId = req.getKnowledgePointId();
        KnowledgePointEntity knowledgePoint = knowledgePointQueryService.getKnowledgePointByKnowId(knowId);
        if (Objects.isNull(knowledgePoint)) {
            log.warn("未找到知识点，ID: {}", req.getKnowledgePointId());
            return new ArrayList<>();
        }
        KnowSummaryEntity summary = knowSummaryService.getOneByKnowId(knowId);

        Collection<MaterialEntity> materials = knowledgePointQueryService.getMaterialListByKnowId(knowId);
        if (CollectionUtil.isEmpty(materials)) {
            log.warn("知识点下没有教材，请先添加教材");
            return Collections.emptyList();
        }
        req.setGradeIds(materials.stream().map(MaterialEntity::getGradeId).collect(Collectors.toSet()));
        // 2. 构建提示词
        String prompt = PromptBuilder.buildSplitPrompt(knowledgePoint, summary, req);
        log.info("构建提示词: {}", prompt);
        // 3. 调用大模型进行知识点拆分
        LlmResponse result = aiModelCallService.callModel(AiScenarioCodeEnum.KNOWLEDGE_POINT_SPLIT.getCode(), prompt, new HashMap<>(), req.getUserId());

        if (Objects.isNull(result)) {
            log.warn("调用大模型拆分知识点失败，返回结果为空");
            return new ArrayList<>();
        }

        // 4. 解析大模型返回结果
        return parseLLMResponse(result);
    }


    /**
     * 解析大模型响应（用于知识点拆分场景）
     *
     * @param result 大模型响应结果
     * @return 拆分后的知识点列表
     */
    private List<KnowledgePointSplitResp> parseLLMResponse(LlmResponse result) {
        List<KnowledgePointSplitResp> respList = new ArrayList<>();

        try {
            for (LlmResponse.Choice choice : result.getChoices()) {
                LlmResponse.Message message = choice.getMessage();
                if (Objects.isNull(message)) {
                    log.warn("大模型响应中 'message' 为空");
                    continue;
                }

                String content = message.getContent();
                log.info("大模型响应内容: {}", content);

                // 尝试解析内容中的JSON数组
                content = content.trim();
                if (content.startsWith("```json")) {
                    content = content.substring(7, content.length() - 3).trim();
                } else if (content.startsWith("```")) {
                    content = content.substring(3, content.length() - 3).trim();
                }

                ObjectMapper objectMapper = new ObjectMapper();
                JsonNode jsonArray = objectMapper.readTree(content);

                if (jsonArray.isArray()) {
                    for (JsonNode jsonNode : jsonArray) {
                        KnowledgePointSplitResp resp = new KnowledgePointSplitResp();

                        resp.setKnowledgePointName(
                                jsonNode.has("knowledgePointName") ? jsonNode.get("knowledgePointName").asText() : "");
                        resp.setSummary(
                                jsonNode.has("summary") ? jsonNode.get("summary").asText() : "");
                        resp.setVideoScript(
                                jsonNode.has("videoScript") ? jsonNode.get("videoScript").asText() : "");

                        // 解析示例题目
                        if (jsonNode.has("exampleQuestions") && jsonNode.get("exampleQuestions").isArray()) {
                            List<KnowledgePointSplitResp.ExampleQuestion> exampleQuestions = new ArrayList<>();
                            JsonNode questionsArray = jsonNode.get("exampleQuestions");

                            for (JsonNode questionNode : questionsArray) {
                                KnowledgePointSplitResp.ExampleQuestion exampleQuestion = new KnowledgePointSplitResp.ExampleQuestion();
                                if (!questionNode.has("type")) {
                                    log.warn("示例题目类型为空");
                                    continue;
                                }
                                exampleQuestion.setType(questionNode.get("type").asInt());
                                exampleQuestion.setQuestion(
                                        questionNode.has("question") ? questionNode.get("question").asText() : "");
                                exampleQuestion.setAnswer(
                                        questionNode.has("answer") ? questionNode.get("answer").asText() : "");
                                exampleQuestion.setExplanation(
                                        questionNode.has("explanation") ? questionNode.get("explanation").asText() : "");

                                if (questionNode.has("options") && questionNode.get("options").isArray()) {
                                    List<QuestionOptionsResp> optionsResp = new ArrayList<>();
                                    JsonNode optionsArray = questionNode.get("options");

                                    for (JsonNode optionNode : optionsArray) {
                                        QuestionOptionsResp optionResp = new QuestionOptionsResp();
                                        optionResp.setContent(optionNode.has("content") ? optionNode.get("content").asText() : "");
                                        optionResp.setSort(optionNode.has("sort") ? optionNode.get("sort").asInt() : 0);
                                        optionsResp.add(optionResp);
                                    }
                                    exampleQuestion.setOptions(optionsResp);
                                }
                                exampleQuestions.add(exampleQuestion);
                            }
                            resp.setExampleQuestions(exampleQuestions);
                        }

                        respList.add(resp);
                    }
                }
            }
        } catch (Exception e) {
            log.error("解析大模型响应时发生异常", e);
        }

        log.info("知识点拆分完成，共拆分出 {} 个知识点", respList.size());
        return respList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchSaveSplitKnowledgePoints(BatchSaveSplitKnowledgePointsReq req) {
        log.info("开始批量保存拆分知识点，原始知识点ID：{}", req.getOldKnowId());
        if (CollectionUtil.isEmpty(req.getKnowledgePoints())) {
            return false;
        }
        // 1. 先根据oldKnowId查询对应的unitId
        KnowledgePointEntity oldKnowledgePoint = knowledgePointQueryService.getKnowledgePointByKnowId(req.getOldKnowId());
        AssertUtils.notNull(oldKnowledgePoint, ResultCodeEnum.KNOW_NOT_EXIST);
        UnitKnowMappingEntity oldMapping = knowledgePointQueryService.getUnitKnowMappingByUnitIdAndKnowId(req.getUnitId(), req.getOldKnowId());
        if (Objects.isNull(oldMapping)) {
            log.warn("未找到知识点ID为{}对应的单元ID", req.getOldKnowId());
            return false;
        }

        // 2. 保存新的知识点
        for (KnowledgePointSplitResp kp : req.getKnowledgePoints()) {
            KnowledgePointEntity entity = new KnowledgePointEntity();
            entity.setKnowledgePointName(kp.getKnowledgePointName());
            entity.setVideoScript(kp.getVideoScript());
            entity.setSort(0);
            entity.setIsChecked(0);
            entity.setGradeType(oldKnowledgePoint.getGradeType());
            entity.setSubjectId(oldKnowledgePoint.getSubjectId());

            knowledgePointService.save(entity);

            log.info("保存新的知识点：{}", entity);

            UnitKnowMappingEntity mapping = new UnitKnowMappingEntity();
            mapping.setUnitId(oldMapping.getUnitId());
            mapping.setKnowledgePointId(entity.getId());
            mapping.setIsStandardVersion(oldMapping.getIsStandardVersion());
            mapping.setSort(0);
            mapping.setCreateTime(LocalDateTime.now());

            boolean mappingResult = unitKnowMappingService.save(mapping);
            if (!mappingResult) {
                log.error("保存单元知识点映射关系失败");
                throw new RuntimeException("保存单元知识点映射关系失败");
            }

            // 保存摘要
            KnowSummaryEntity summary = new KnowSummaryEntity();
            summary.setKnowId(entity.getId());
            summary.setSummary(kp.getSummary());
            knowSummaryService.save(summary);
            log.info("保存知识点摘要：{}", summary);

            // 保存示例题目
            if (kp.getExampleQuestions() != null && !kp.getExampleQuestions().isEmpty()) {
                for (KnowledgePointSplitResp.ExampleQuestion exampleQuestion : kp.getExampleQuestions()) {
                    ExampleQuestionsEntity question = new ExampleQuestionsEntity();
                    question.setKnowId(entity.getId());
                    question.setType(exampleQuestion.getType());
                    question.setQuestion(exampleQuestion.getQuestion());
                    question.setAnswer(exampleQuestion.getAnswer());
                    question.setSolution(exampleQuestion.getExplanation());
                    exampleQuestionsService.save(question);
                    log.info("保存示例题目：{}", question);
                    if (CollUtil.isNotEmpty(exampleQuestion.getOptions())) {
                        for (QuestionOptionsResp optionsResp : exampleQuestion.getOptions()) {
                            QuestionOptionsEntity option = new QuestionOptionsEntity();
                            option.setQuestionId(question.getId());
                            option.setContent(optionsResp.getContent());
                            option.setSort(optionsResp.getSort());
                            questionOptionsService.save(option);
                        }
                    }
                }
            }
        }
        log.info("批量保存拆分知识点完成");
        return true;
    }
}