package com.seer.teach.admin.util;

import lombok.extern.slf4j.Slf4j;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
public class PythonScriptExecutor {

    /**
     * 执行Python脚本并返回生成的视频文件路径
     *
     * @param pythonScript Python脚本内容
     * @param scriptId     脚本ID，用于生成文件名
     * @return 生成的视频文件路径，如果没有生成视频则返回null
     */
    public static String executePythonScript(String pythonScript, Integer scriptId) {
        if (pythonScript == null || pythonScript.trim().isEmpty()) {
            log.warn("Python脚本为空，跳过执行");
            return null;
        }

        try {
            // 创建临时目录用于执行Python脚本
            Path tempDir = Files.createTempDirectory("video_script_");
            Path scriptPath = tempDir.resolve("script.py");

            // 处理Python脚本内容，去除多余的转义字符
            String processedScript = processPythonScriptContent(pythonScript);

            // 将Python脚本写入文件
            Files.write(scriptPath, processedScript.getBytes());

            // 安装依赖包
            installDependencies(processedScript, tempDir);
            log.info("开始执行Python脚本...");
            long startTime = System.currentTimeMillis();
            // 执行Python脚本
            ProcessBuilder processBuilder = new ProcessBuilder("python", scriptPath.toString());
            processBuilder.directory(tempDir.toFile());
            Process process = processBuilder.start();
            // 等待脚本执行完成
            int exitCode = process.waitFor();
            log.info("脚本执行结束，耗时:{}", (System.currentTimeMillis() - startTime)/1000 + "秒");
            String videoFilePath = null;
            if (exitCode == 0) {
                log.info("Python脚本执行成功");

                // 查找生成的视频文件（假设是.mp4格式）
                File[] videoFiles = tempDir.toFile().listFiles((dir, name) -> name.endsWith(".mp4"));
                if (videoFiles != null && videoFiles.length > 0) {
                    // 选择第一个视频文件
                    File videoFile = videoFiles[0];

                    // 生成保存路径
                    String fileName = System.currentTimeMillis() + "_" + scriptId + ".mp4";
                    Path savePath = Paths.get("videos", fileName);

                    // 确保videos目录存在
                    Files.createDirectories(savePath.getParent());

                    // 移动视频文件到指定位置
                    Files.move(videoFile.toPath(), savePath);

                    videoFilePath = savePath.toString();
                    log.info("视频已保存至: {}", savePath);
                } else {
                    log.warn("未找到生成的视频文件");
                }
            } else {
                log.error("Python脚本执行失败，退出码: {}", exitCode);
                // 读取错误输出
                BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
                String errorLine;
                StringBuilder errorOutput = new StringBuilder();
                while ((errorLine = errorReader.readLine()) != null) {
                    errorOutput.append(errorLine).append("\n");
                }
                log.error("Python脚本执行错误输出: {}", errorOutput.toString());
            }

            // 清理临时目录
            deleteDirectory(tempDir.toFile());

            return videoFilePath;
        } catch (Exception e) {
            log.error("执行Python脚本时发生异常", e);
            return null;
        }
    }

    /**
     * 处理Python脚本内容，去除多余的转义字符
     * @param pythonScript 原始Python脚本内容
     * @return 处理后的脚本内容
     */
    private static String processPythonScriptContent(String pythonScript) {
        // 替换转义的双引号
        String processed = pythonScript.replace("\\\"", "\"");
        
        // 替换转义的换行符
        processed = processed.replace("\\n", "\n");
        
        // 替换转义的制表符
        processed = processed.replace("\\t", "\t");
        
        // 替换转义的反斜杠
        processed = processed.replace("\\\\", "\\");
        
        return processed;
    }

    /**
     * 检查Python包是否已安装
     *
     * @param packageName 包名
     * @param tempDir     临时目录
     * @return 是否已安装
     */
    private static boolean isPackageInstalled(String packageName, Path tempDir) {
        try {
            ProcessBuilder processBuilder = new ProcessBuilder("python", "-c",
                    "import pkg_resources; pkg_resources.get_distribution('" + packageName + "')");
            processBuilder.directory(tempDir.toFile());
            Process process = processBuilder.start();
            int exitCode = process.waitFor();
            return exitCode == 0;
        } catch (Exception e) {
            log.debug("检查包{}是否安装时发生异常: {}", packageName, e.getMessage());
            return false;
        }
    }

    /**
     * 从Python脚本中提取并安装依赖包
     *
     * @param pythonScript Python脚本内容
     * @param tempDir      临时目录
     */
    private static void installDependencies(String pythonScript, Path tempDir) {
        try {
            // 使用正则表达式匹配常见的依赖声明模式
            // 匹配 pip install 命令
            Pattern pipPattern = Pattern.compile("pip\\s+install\\s+([\\w\\-]+)");
            Matcher pipMatcher = pipPattern.matcher(pythonScript);

            // 匹配注释中的依赖声明，例如: # Required: numpy, pandas, matplotlib
            Pattern commentPattern = Pattern.compile("#\\s*(?:Required|Dependencies?):\\s*([\\w\\-,\\s]+)");
            Matcher commentMatcher = commentPattern.matcher(pythonScript);

            // 收集需要安装的包
            List<String> packagesToInstall = new ArrayList<>();

            // 从pip install命令中提取包名
            while (pipMatcher.find()) {
                String packageName = pipMatcher.group(1);
                if (!packagesToInstall.contains(packageName)) {
                    packagesToInstall.add(packageName);
                }
            }

            // 从注释中提取包名
            while (commentMatcher.find()) {
                String packagesStr = commentMatcher.group(1);
                String[] packages = packagesStr.split("[,\\s]+");
                for (String pkg : packages) {
                    if (!pkg.isEmpty() && !packagesToInstall.contains(pkg)) {
                        packagesToInstall.add(pkg);
                    }
                }
            }

            // 安装依赖包
            if (!packagesToInstall.isEmpty()) {
                log.info("发现依赖包: {}", packagesToInstall);

                for (String packageName : packagesToInstall) {
                    // 检查包是否已经安装
                    if (isPackageInstalled(packageName, tempDir)) {
                        log.info("依赖包 {} 已经安装，无需重复安装", packageName);
                        continue;
                    }

                    ProcessBuilder processBuilder = new ProcessBuilder("pip", "install", packageName);
                    processBuilder.directory(tempDir.toFile());
                    Process process = processBuilder.start();
                    int exitCode = process.waitFor();

                    if (exitCode == 0) {
                        log.info("依赖包 {} 安装成功", packageName);
                    } else {
                        log.warn("依赖包 {} 安装失败，退出码: {}", packageName, exitCode);
                    }
                }
            } else {
                log.info("未发现需要安装的依赖包");
            }
        } catch (Exception e) {
            log.error("安装依赖包时发生异常", e);
        }
    }

    /**
     * 删除目录及其内容
     *
     * @param directory 要删除的目录
     */
    private static void deleteDirectory(File directory) {
        if (directory.isDirectory()) {
            File[] files = directory.listFiles();
            if (files != null) {
                for (File file : files) {
                    deleteDirectory(file);
                }
            }
        }
        directory.delete();
    }
}