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

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.seer.teach.admin.convert.KnowledgePointsConvert;
import com.seer.teach.admin.request.GenerateTaskReq;
import com.seer.teach.admin.response.TeachTextsResp;
import com.seer.teach.admin.service.VideoScriptGenerationService;
import com.seer.teach.admin.util.PromptBuilder;
import com.seer.teach.common.enums.AiScenarioCodeEnum;
import com.seer.teach.admin.util.PythonScriptExecutor;
import com.seer.teach.teacher.module.entity.TeachGoalsEntity;
import com.seer.teach.teacher.module.entity.TeachTextsEntity;
import com.seer.teach.teacher.module.param.KnowledgePointSearchParam;
import com.seer.teach.teacher.service.KnowledgePointQueryService;
import com.seer.teach.teacher.service.TeachGoalsService;
import com.seer.teach.teacher.service.TeachTextsService;
import com.seer.teach.teacher.service.platform.LlmResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * <p>
 * 视频脚本生成服务实现类
 * </p>
 *
 * @author Lingma
 * @since 2025-12-17
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class VideoScriptGenerationServiceImpl extends AbstractGenerationService<TeachTextsResp, GenerateTaskReq, TeachTextsEntity> implements VideoScriptGenerationService {

    private final KnowledgePointQueryService knowledgePointQueryService;
    private final TeachGoalsService teachGoalsService;
    private final TeachTextsService teachTextsService;

    @Override
    public List<TeachTextsResp> generateVideoScripts(GenerateTaskReq req) {
        log.info("根据讲课稿生成视频脚本, 请求参数: {}", req);

        // 1. 根据讲课稿ID查询对应的讲课稿
        Integer textId = req.getTextId();
        TeachTextsEntity teachText = teachTextsService.getById(textId);
        if (Objects.isNull(teachText)) {
            log.warn("未找到讲课稿，ID: {}", textId);
            return Collections.emptyList();
        }

        // 2. 调用大模型生成视频脚本
        List<TeachTextsResp> generatedScripts = callLLMToGenerateVideoScript(teachText, req);

        // 3. 执行Python脚本并保存视频
        executePythonScriptsAndSaveVideos(generatedScripts);

        log.info("生成视频脚本完成，共生成 {} 个视频脚本", generatedScripts.size());
        return generatedScripts;
    }

    @Override
    public Integer generateAndSaveAllVideoScripts(GenerateTaskReq req) {
        // 1. 查询所有知识点
        KnowledgePointSearchParam params = KnowledgePointsConvert.INSTANCE.generateReq2KnowledgePointSearchParam(req);
        Collection<Integer> knowIds = knowledgePointQueryService.getKnowIdsByConditions(params);
        if (CollectionUtil.isEmpty(knowIds)) {
            log.warn("未找到对应的知识点");
            return 0;
        }

        Collection<TeachGoalsEntity> teachGoals = teachGoalsService.list(new LambdaQueryWrapper<TeachGoalsEntity>().in(TeachGoalsEntity::getKnowId, knowIds));
        if (CollectionUtil.isEmpty(teachGoals)) {
            log.warn("未找到对应的教学目标");
            return 0;
        }

        log.info("查询到的教学目标数量: {}", teachGoals.size());
        int totalCount = 0;

        // 2. 遍历知识点，查找对应的教学目标
        for (TeachGoalsEntity teachGoal : teachGoals) {
            // 检查任务是否被取消
            String taskId = getTaskIdFromRequest(req);
            if (isThreadInterrupted() || isTaskCancelled(taskId)) {
                log.info("任务被中断或取消，停止执行");
                return totalCount;
            }

            // 检查任务是否被取消
            if (isThreadInterrupted() || isTaskCancelled(taskId)) {
                log.info("任务被中断或取消，停止执行");
                return totalCount;
            }

            // 查询该教学目标下的所有讲课稿
            List<TeachTextsEntity> teachTexts = teachTextsService.list(
                    new LambdaQueryWrapper<TeachTextsEntity>()
                            .eq(TeachTextsEntity::getGoalId, teachGoal.getId())
                            .isNull(TeachTextsEntity::getPythonScript)
            );

            if (CollectionUtil.isEmpty(teachTexts)) {
                log.info("教学目标: {} 下未找到视频脚本为空的讲课稿，跳过", teachGoal.getId());
                continue;
            }
            log.info("教学目标: {} 下找到 {} 个到视频脚本为空的讲课稿", teachGoal.getId(), teachTexts.size());
            // 4. 遍历讲课稿，生成视频脚本
            for (TeachTextsEntity teachText : teachTexts) {
                log.info("讲课稿: {} 开始生成视频脚本", teachText.getId());
                req.setTextId(teachText.getId());
                totalCount += executeBatchProcess(
                        req,
                        this::generateVideoScripts,
                        this::saveGeneratedVideoScripts
                );
            }
        }
        log.info("生成视频脚本任务完成，总共处理 {} 个讲课稿", totalCount);
        return totalCount;
    }

    /**
     * 执行Python脚本并保存生成的视频
     *
     * @param scripts 生成的视频脚本列表
     */
    public void executePythonScriptsAndSaveVideos(List<TeachTextsResp> scripts) {
        for (TeachTextsResp script : scripts) {
            String pythonScript = script.getPythonScript();
            if (pythonScript == null || pythonScript.trim().isEmpty()) {
                log.warn("Python脚本为空，跳过执行");
                continue;
            }

            try {
                // 使用工具类执行Python脚本
                String videoFilePath = PythonScriptExecutor.executePythonScript(pythonScript, script.getId());
                
                // 设置视频URL
                if (videoFilePath != null) {
                    script.setVideoUrl(videoFilePath);
                    log.info("视频已保存至: {}", videoFilePath);
                }
            } catch (Exception e) {
                log.error("执行Python脚本时发生异常", e);
            }finally {
                TeachTextsEntity text = new TeachTextsEntity();
                text.setId(script.getId());
                text.setPythonScript(script.getPythonScript());
                teachTextsService.updateById(text);
            }
        }
    }

    /**
     * 保存生成的视频脚本
     *
     * @param scripts 生成的视频脚本列表
     */
    private void saveGeneratedVideoScripts(List<TeachTextsResp> scripts) {
        if (scripts.isEmpty()) {
            return;
        }
        List<TeachTextsEntity> scriptItems = new ArrayList<>();
        for (TeachTextsResp script : scripts) {
            TeachTextsEntity item = new TeachTextsEntity();
            item.setId(script.getId());
            item.setVideoContent(script.getVideoContent());
            item.setPythonScript(script.getPythonScript());
            item.setVideoUrl(script.getVideoUrl()); // 保存视频URL
            scriptItems.add(item);
        }
        boolean result = teachTextsService.updateBatchById(scriptItems);
        log.info("批量保存视频脚本结果: {}", result);
    }

    /**
     * 调用大模型生成视频脚本
     *
     * @param teachText 讲课稿
     * @param req       生成视频脚本参数
     * @return 生成的视频脚本列表
     */
    private List<TeachTextsResp> callLLMToGenerateVideoScript(TeachTextsEntity teachText, GenerateTaskReq req) {
        log.info("调用大模型生成视频脚本，讲课稿: {}", teachText.getId());

        // 构建提示词
        String prompt = PromptBuilder.buildPromptForTeachTextVideoScriptGeneration(teachText);

        log.info("调用大模型生成视频脚本，提示词: {}", prompt);

        // 调用大模型API生成视频脚本
        Map<String, Object> params = new HashMap<>();
        if (Objects.nonNull(req.getTaskId())) {
            params.putIfAbsent("taskId", req.getTaskId());
        }
        LlmResponse result = callLLM(
                AiScenarioCodeEnum.GENERATE_VIDEO_SCRIPT_FROM_TEACH_TEXTS.getCode(),
                prompt,
                params,
                req.getUserId());

        if (Objects.isNull(result)) {
            log.warn("调用大模型生成视频脚本失败，返回结果为空");
            return Collections.emptyList();
        }

        // 使用新的泛型方法解析响应
        List<TeachTextsResp> scripts = new ArrayList<>();
        for (LlmResponse.Choice choice : result.getChoices()) {
            LlmResponse.Message message = choice.getMessage();
            if (Objects.isNull(message)) {
                log.warn("调用大模型生成视频脚本失败，返回结果中 'message' 为空");
                continue;
            }
            String content = message.getContent();
            List<TeachTextsResp> resultList = parseLLMResponse(content, textNode -> {
                TeachTextsResp scriptResp = new TeachTextsResp();
                // 解析基本字段
                scriptResp.setId(teachText.getId());
                scriptResp.setPythonScript(getStringValue(textNode, "pythonScript"));
                return scriptResp;
            });
            scripts.addAll(resultList);
        }
        return scripts;
    }



    @Override
    protected String getTaskIdFromRequest(GenerateTaskReq request) {
        return request.getTaskId();
    }
}