/**
 * Python环境管理命令
 * 用于管理Python环境和依赖
 */

use serde::{Deserialize, Serialize};
use tauri::{command, AppHandle};
use std::process::Command;
use std::path::PathBuf;

#[derive(Debug, Serialize, Deserialize)]
pub struct PythonEnvInfo {
    pub python_type: String,
    pub python_path: Option<String>,
    pub version: Option<String>,
    pub is_available: bool,
    pub error: Option<String>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct PythonPackage {
    pub name: String,
    pub version: String,
    pub location: Option<String>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct PythonEnvStatus {
    pub embedded: PythonEnvInfo,
    pub system: PythonEnvInfo,
    pub current_env: String,
    pub packages: Vec<PythonPackage>,
}

/// 获取嵌入式Python路径
fn get_embedded_python_path() -> Option<PathBuf> {
    let python_exe = if cfg!(target_os = "windows") {
        "python.exe"
    } else {
        "python3"
    };
    
    let possible_paths = vec![
        std::env::current_dir().ok()
            .map(|p| p.join("src-tauri").join("python-embed").join(python_exe)),
        std::env::current_exe().ok()
            .and_then(|p| p.parent().map(|p| p.join("python-embed").join(python_exe))),
    ];
    
    for path in possible_paths.into_iter().flatten() {
        if path.exists() {
            return Some(path);
        }
    }
    
    None
}

/// 检查Python环境信息
fn check_python_env(python_path: &str) -> PythonEnvInfo {
    let mut cmd = Command::new(python_path);
    cmd.arg("--version");
    
    match cmd.output() {
        Ok(output) => {
            if output.status.success() {
                let version = String::from_utf8_lossy(&output.stdout).trim().to_string();
                PythonEnvInfo {
                    python_type: if python_path.contains("python-embed") { "embedded".to_string() } else { "system".to_string() },
                    python_path: Some(python_path.to_string()),
                    version: Some(version),
                    is_available: true,
                    error: None,
                }
            } else {
                let error = String::from_utf8_lossy(&output.stderr).trim().to_string();
                PythonEnvInfo {
                    python_type: if python_path.contains("python-embed") { "embedded".to_string() } else { "system".to_string() },
                    python_path: Some(python_path.to_string()),
                    version: None,
                    is_available: false,
                    error: Some(error),
                }
            }
        }
        Err(e) => PythonEnvInfo {
            python_type: if python_path.contains("python-embed") { "embedded".to_string() } else { "system".to_string() },
            python_path: Some(python_path.to_string()),
            version: None,
            is_available: false,
            error: Some(e.to_string()),
        }
    }
}

/// 获取已安装的Python包列表
fn get_installed_packages(python_path: &str) -> Vec<PythonPackage> {
    let mut cmd = Command::new(python_path);
    cmd.args(&["-m", "pip", "list", "--format=json"]);
    
    match cmd.output() {
        Ok(output) => {
            if output.status.success() {
                let stdout = String::from_utf8_lossy(&output.stdout);
                match serde_json::from_str::<Vec<serde_json::Value>>(&stdout) {
                    Ok(packages) => {
                        packages.into_iter().filter_map(|pkg| {
                            let name = pkg.get("name")?.as_str()?.to_string();
                            let version = pkg.get("version")?.as_str()?.to_string();
                            Some(PythonPackage {
                                name,
                                version,
                                location: None,
                            })
                        }).collect()
                    }
                    Err(_) => Vec::new(),
                }
            } else {
                Vec::new()
            }
        }
        Err(_) => Vec::new(),
    }
}

/// 获取Python环境状态
#[command]
pub async fn get_python_env_status(_app: AppHandle) -> Result<PythonEnvStatus, String> {
    println!("Getting Python environment status...");
    
    // 检查嵌入式Python
    let embedded_info = if let Some(embedded_path) = get_embedded_python_path() {
        check_python_env(&embedded_path.to_string_lossy())
    } else {
        PythonEnvInfo {
            python_type: "embedded".to_string(),
            python_path: None,
            version: None,
            is_available: false,
            error: Some("Embedded Python not found".to_string()),
        }
    };
    
    // 检查系统Python
    let system_info = check_python_env("python");
    
    // 确定当前使用的环境
    let current_env = if embedded_info.is_available {
        "embedded".to_string()
    } else if system_info.is_available {
        "system".to_string()
    } else {
        "none".to_string()
    };
    
    // 获取当前环境的包列表
    let packages = if embedded_info.is_available {
        if let Some(ref path) = embedded_info.python_path {
            get_installed_packages(path)
        } else {
            Vec::new()
        }
    } else if system_info.is_available {
        get_installed_packages("python")
    } else {
        Vec::new()
    };
    
    Ok(PythonEnvStatus {
        embedded: embedded_info,
        system: system_info,
        current_env,
        packages,
    })
}

/// 安装Python包
#[command]
pub async fn install_python_package(_app: AppHandle, package_name: String) -> Result<String, String> {
    println!("Installing Python package: {}", package_name);
    
    // 确定使用哪个Python
    let python_path = if let Some(embedded_path) = get_embedded_python_path() {
        embedded_path.to_string_lossy().to_string()
    } else {
        "python".to_string()
    };
    
    let mut cmd = Command::new(&python_path);
    cmd.args(&["-m", "pip", "install", &package_name]);
    
    match cmd.output() {
        Ok(output) => {
            if output.status.success() {
                let stdout = String::from_utf8_lossy(&output.stdout);
                Ok(format!("Successfully installed {}: {}", package_name, stdout))
            } else {
                let stderr = String::from_utf8_lossy(&output.stderr);
                Err(format!("Failed to install {}: {}", package_name, stderr))
            }
        }
        Err(e) => Err(format!("Failed to execute pip install: {}", e))
    }
}

/// 卸载Python包
#[command]
pub async fn uninstall_python_package(_app: AppHandle, package_name: String) -> Result<String, String> {
    println!("Uninstalling Python package: {}", package_name);
    
    // 确定使用哪个Python
    let python_path = if let Some(embedded_path) = get_embedded_python_path() {
        embedded_path.to_string_lossy().to_string()
    } else {
        "python".to_string()
    };
    
    let mut cmd = Command::new(&python_path);
    cmd.args(&["-m", "pip", "uninstall", "-y", &package_name]);
    
    match cmd.output() {
        Ok(output) => {
            if output.status.success() {
                let stdout = String::from_utf8_lossy(&output.stdout);
                Ok(format!("Successfully uninstalled {}: {}", package_name, stdout))
            } else {
                let stderr = String::from_utf8_lossy(&output.stderr);
                Err(format!("Failed to uninstall {}: {}", package_name, stderr))
            }
        }
        Err(e) => Err(format!("Failed to execute pip uninstall: {}", e))
    }
}

/// 升级Python包
#[command]
pub async fn upgrade_python_package(_app: AppHandle, package_name: String) -> Result<String, String> {
    println!("Upgrading Python package: {}", package_name);
    
    // 确定使用哪个Python
    let python_path = if let Some(embedded_path) = get_embedded_python_path() {
        embedded_path.to_string_lossy().to_string()
    } else {
        "python".to_string()
    };
    
    let mut cmd = Command::new(&python_path);
    cmd.args(&["-m", "pip", "install", "--upgrade", &package_name]);
    
    match cmd.output() {
        Ok(output) => {
            if output.status.success() {
                let stdout = String::from_utf8_lossy(&output.stdout);
                Ok(format!("Successfully upgraded {}: {}", package_name, stdout))
            } else {
                let stderr = String::from_utf8_lossy(&output.stderr);
                Err(format!("Failed to upgrade {}: {}", package_name, stderr))
            }
        }
        Err(e) => Err(format!("Failed to execute pip upgrade: {}", e))
    }
}

/// 设置嵌入式Python环境
#[command]
pub async fn setup_embedded_python(_app: AppHandle) -> Result<String, String> {
    println!("Setting up embedded Python environment...");

    // 尝试多个可能的脚本路径
    let possible_script_paths = vec![
        // 开发环境：从项目根目录
        std::env::current_dir().ok()
            .map(|p| p.join("scripts").join("setup_embedded_python.py")),
        // 相对路径
        Some(std::path::PathBuf::from("scripts/setup_embedded_python.py")),
        Some(std::path::PathBuf::from("./scripts/setup_embedded_python.py")),
        // 绝对路径（如果在scripts目录中运行）
        Some(std::path::PathBuf::from("setup_embedded_python.py")),
    ];

    let mut script_path = None;
    for path in possible_script_paths.into_iter().flatten() {
        println!("Checking script path: {:?}", path);
        if path.exists() {
            script_path = Some(path);
            break;
        }
    }

    let script_path = script_path.ok_or_else(|| {
        let current_dir = std::env::current_dir().unwrap_or_default();
        format!(
            "Setup script not found. Current directory: {:?}. Please ensure scripts/setup_embedded_python.py exists.",
            current_dir
        )
    })?;

    println!("Using script path: {:?}", script_path);

    // 尝试多个Python命令
    let python_commands = vec!["python", "python3", "py"];
    let mut last_error = String::new();

    for python_cmd in python_commands {
        println!("Trying Python command: {}", python_cmd);

        let mut cmd = Command::new(python_cmd);
        cmd.arg(&script_path);
        cmd.current_dir(std::env::current_dir().unwrap_or_default());

        match cmd.output() {
            Ok(output) => {
                if output.status.success() {
                    let stdout = String::from_utf8_lossy(&output.stdout);
                    return Ok(format!("Embedded Python setup completed using {}: {}", python_cmd, stdout));
                } else {
                    let stderr = String::from_utf8_lossy(&output.stderr);
                    last_error = format!("Failed with {}: {}", python_cmd, stderr);
                    println!("{}", last_error);
                }
            }
            Err(e) => {
                last_error = format!("Failed to execute {} {}: {}", python_cmd, script_path.display(), e);
                println!("{}", last_error);
            }
        }
    }

    Err(format!("All Python commands failed. Last error: {}", last_error))
}

/// 简化的嵌入式Python设置（使用批处理脚本）
#[command]
pub async fn setup_embedded_python_simple(_app: AppHandle) -> Result<String, String> {
    println!("Setting up embedded Python environment using batch script...");

    // 查找批处理脚本
    let possible_script_paths = vec![
        std::env::current_dir().ok()
            .map(|p| p.join("scripts").join("setup_embedded_python.bat")),
        Some(std::path::PathBuf::from("scripts/setup_embedded_python.bat")),
        Some(std::path::PathBuf::from("./scripts/setup_embedded_python.bat")),
    ];

    let mut script_path = None;
    for path in possible_script_paths.into_iter().flatten() {
        println!("Checking batch script path: {:?}", path);
        if path.exists() {
            script_path = Some(path);
            break;
        }
    }

    let script_path = script_path.ok_or_else(|| {
        let current_dir = std::env::current_dir().unwrap_or_default();
        format!(
            "Batch script not found. Current directory: {:?}. Please ensure scripts/setup_embedded_python.bat exists.",
            current_dir
        )
    })?;

    println!("Using batch script: {:?}", script_path);

    // 在Windows上运行批处理脚本
    #[cfg(target_os = "windows")]
    {
        let mut cmd = Command::new("cmd");
        cmd.args(&["/C", &script_path.to_string_lossy()]);
        cmd.current_dir(std::env::current_dir().unwrap_or_default());

        match cmd.output() {
            Ok(output) => {
                let stdout = String::from_utf8_lossy(&output.stdout);
                let stderr = String::from_utf8_lossy(&output.stderr);

                if output.status.success() {
                    Ok(format!("Embedded Python setup completed:\nOutput: {}\nErrors: {}", stdout, stderr))
                } else {
                    Err(format!("Batch script failed:\nOutput: {}\nErrors: {}", stdout, stderr))
                }
            }
            Err(e) => Err(format!("Failed to execute batch script: {}", e))
        }
    }

    // 在非Windows系统上返回错误
    #[cfg(not(target_os = "windows"))]
    {
        Err("Batch script setup is only available on Windows. Please run the Python script manually.".to_string())
    }
}
