// src/commands/mcp.rs

use std::fs;
use std::path::{PathBuf};
use std::process::Command as OtherCommand;
use serde_json::json;
use seahorse::{Command, Context, Flag, FlagType};
use crate::chat::ask_chat;
use crate::git::{git_init, git_status};
use crate::config::ConfigPaths;
use crate::commands::git_repo::read_all_git_files;
use crate::metrics::{load_user_data, save_user_data};
use crate::memory::{log_message};

pub fn mcp_setup() {
    let config = ConfigPaths::new();
    let dest_dir = config.base_dir.join("mcp");
    let repo_url = "https://github.com/microsoft/MCP.git";
    println!("📁 MCP ディレクトリ: {}", dest_dir.display());

   // 1. git clone(もしまだなければ)
    if !dest_dir.exists() {
        let status = OtherCommand::new("git")
            .args(&["clone", repo_url, dest_dir.to_str().unwrap()])
            .status()
            .expect("git clone に失敗しました");
        assert!(status.success(), "git clone 実行時にエラーが発生しました");
    }

    let asset_base = PathBuf::from("mcp");
    let files_to_copy = vec![
        "cli.py",
        "setup.py",
        "scripts/ask.py",
        "scripts/summarize.py",
        "scripts/context_loader.py",
        "scripts/prompt_template.py",
    ];

    for rel_path in files_to_copy {
        let src = asset_base.join(rel_path);
        let dst = dest_dir.join(rel_path);
        if let Some(parent) = dst.parent() {
            let _ = fs::create_dir_all(parent);
        }
        if let Err(e) = fs::copy(&src, &dst) {
            eprintln!("❌ コピー失敗: {} → {}: {}", src.display(), dst.display(), e);
        } else {
            println!("✅ コピー: {} → {}", src.display(), dst.display());
        }
    }

    // venvの作成
    let venv_path = dest_dir.join(".venv");
    if !venv_path.exists() {
        println!("🐍 仮想環境を作成しています...");
        let output = OtherCommand::new("python3")
            .args(&["-m", "venv", ".venv"])
            .current_dir(&dest_dir)
            .output()
            .expect("venvの作成に失敗しました");

        if !output.status.success() {
            eprintln!("❌ venv作成エラー: {}", String::from_utf8_lossy(&output.stderr));
            return;
        }
    }

    // `pip install -e .` を仮想環境で実行
    let pip_path = if cfg!(target_os = "windows") {
        dest_dir.join(".venv/Scripts/pip.exe").to_string_lossy().to_string()
    } else {
        dest_dir.join(".venv/bin/pip").to_string_lossy().to_string()
    };

    println!("📦 必要なパッケージをインストールしています...");
    let output = OtherCommand::new(&pip_path)
        .arg("install")
        .arg("openai")
        .arg("requests")
        .arg("fastmcp")
        .arg("uvicorn")
        .arg("fastapi")
        .arg("fastapi_mcp")
        .arg("mcp")
        .current_dir(&dest_dir)
        .output()
        .expect("pip install に失敗しました");

    if !output.status.success() {
        eprintln!(
            "❌ pip エラー: {}\n{}",
            String::from_utf8_lossy(&output.stderr),
            String::from_utf8_lossy(&output.stdout)
        );
        return;
    }

    println!("📦 pip install -e . を実行します...");
    let output = OtherCommand::new(&pip_path)
        .arg("install")
        .arg("-e")
        .arg(".")
        .current_dir(&dest_dir)
        .output()
        .expect("pip install に失敗しました");

    if output.status.success() {
        println!("🎉 MCP セットアップが完了しました!");
    } else {
        eprintln!(
            "❌ pip エラー: {}\n{}",
            String::from_utf8_lossy(&output.stderr),
            String::from_utf8_lossy(&output.stdout)
        );
    }
}

fn set_api_key_cmd() -> Command {
    Command::new("set-api")
        .description("OpenAI APIキーを設定")
        .usage("mcp set-api --api <API_KEY>")
        .flag(Flag::new("api", FlagType::String).description("OpenAI APIキー").alias("a"))
        .action(|c: &Context| {
            if let Ok(api_key) = c.string_flag("api") {
                let config = ConfigPaths::new();
                let path = config.base_dir.join("openai.json");
                let json_data = json!({ "token": api_key });

                if let Err(e) = fs::write(&path, serde_json::to_string_pretty(&json_data).unwrap()) {
                    eprintln!("❌ ファイル書き込み失敗: {}", e);
                } else {
                    println!("✅ APIキーを保存しました: {}", path.display());
                }
            } else {
                eprintln!("❗ APIキーを --api で指定してください");
            }
        })
}

fn chat_cmd() -> Command {
    Command::new("chat")
        .description("チャットで質問を送る")
        .usage("mcp chat '質問内容' --host <OLLAMA_HOST> --model <MODEL> [--provider <ollama|openai>] [--api-key <KEY>] [--repo <REPO_URL>]")
        .flag(
            Flag::new("host", FlagType::String)
                .description("OLLAMAホストのURL")
                .alias("H"),
        )
        .flag(
            Flag::new("model", FlagType::String)
                .description("モデル名 (OLLAMA_MODEL / OPENAI_MODEL)")
                .alias("m"),
        )
        .flag(
            Flag::new("provider", FlagType::String)
                .description("使用するプロバイダ (ollama / openai)")
                .alias("p"),
        )
        .flag(
            Flag::new("api-key", FlagType::String)
                .description("OpenAI APIキー")
                .alias("k"),
        )
        .flag(
            Flag::new("repo", FlagType::String)
                .description("Gitリポジトリのパスを指定 (すべてのコードを読み込む)")
                .alias("r"),
        )
        .action(|c: &Context| {
            let config = ConfigPaths::new();
            let user_path = config.data_file("json");
            let mut user = load_user_data(&user_path);
            // repoがある場合は、コードベース読み込みモード
            if let Ok(repo_url) = c.string_flag("repo") {
                let repo_base = config.base_dir.join("repos");
                let repo_dir = repo_base.join(sanitize_repo_name(&repo_url));

                if !repo_dir.exists() {
                    println!("📥 Gitリポジトリをクローン中: {}", repo_url);
                    let status = OtherCommand::new("git")
                        .args(&["clone", &repo_url, repo_dir.to_str().unwrap()])
                        .status()
                        .expect("❌ Gitのクローンに失敗しました");
                    assert!(status.success(), "Git clone エラー");
                } else {
                    println!("✔ リポジトリはすでに存在します: {}", repo_dir.display());
                }

                let files = read_all_git_files(repo_dir.to_str().unwrap());
                let prompt = format!(
                    "以下のコードベースを読み込んで、改善案や次のステップを提案してください:\n{}",
                    files
                );

                if let Some(response) = ask_chat(c, &prompt) {
                    println!("💬 提案:\n{}", response);
                } else {
                    eprintln!("❗ 提案が取得できませんでした");
                }

                return;
            }

            // 通常のチャット処理(repoが指定されていない場合)
            match c.args.get(0) {
                Some(question) => {
                    log_message(&config.base_dir, "user", question);
                    let response = ask_chat(c, question);

                    if let Some(ref text) = response {
                        println!("💬 応答:\n{}", text);
                        // 返答内容に基づいて増減(返答の感情解析)
                        if text.contains("thank") || text.contains("great") {
                            user.metrics.trust += 0.05;
                        } else if text.contains("hate") || text.contains("bad") {
                            user.metrics.trust -= 0.05;
                        }
                        log_message(&config.base_dir, "ai", &text);
                        save_user_data(&user_path, &user);
                    } else {
                        eprintln!("❗ 応答が取得できませんでした");
                    }
                }
                None => {
                    eprintln!("❗ 質問が必要です: mcp chat 'こんにちは'");
                }
            }
        })
}

fn init_cmd() -> Command {
    Command::new("init")
        .description("Git 初期化")
        .usage("mcp init")
        .action(|_| {
            git_init();
        })
}

fn status_cmd() -> Command {
    Command::new("status")
        .description("Git ステータス表示")
        .usage("mcp status")
        .action(|_| {
            git_status();
        })
}

fn setup_cmd() -> Command {
    Command::new("setup")
        .description("MCP の初期セットアップ")
        .usage("mcp setup")
        .action(|_| {
            mcp_setup();
        })
}

pub fn mcp_cmd() -> Command {
    Command::new("mcp")
        .description("MCP操作コマンド")
        .usage("mcp <subcommand>")
        .alias("m")
        .command(chat_cmd())
        .command(init_cmd())
        .command(status_cmd())
        .command(setup_cmd())
        .command(set_api_key_cmd())
}

// ファイル名として安全な形に変換
fn sanitize_repo_name(repo_url: &str) -> String {
    repo_url.replace("://", "_").replace("/", "_").replace("@", "_")
}