//! Git merge tool

use kodegen_mcp_tool::{Tool, ToolExecutionContext, error::McpError};
use kodegen_mcp_schema::git::{GitMergeArgs, GitMergePromptArgs};
use rmcp::model::{PromptArgument, PromptMessage, PromptMessageContent, PromptMessageRole, Content};
use serde_json::json;
use std::path::Path;

/// Tool for merging branches
#[derive(Clone)]
pub struct GitMergeTool;

impl Tool for GitMergeTool {
    type Args = GitMergeArgs;
    type PromptArgs = GitMergePromptArgs;

    fn name() -> &'static str {
        kodegen_mcp_schema::git::GIT_MERGE
    }

    fn description() -> &'static str {
        "Merge a branch or commit into the current branch. \
         Joins two or more development histories together."
    }

    fn read_only() -> bool {
        false // Modifies HEAD and working tree
    }

    fn destructive() -> bool {
        true // Can overwrite local changes
    }

    fn idempotent() -> bool {
        false // Creates new commits
    }

    async fn execute(&self, args: Self::Args, _ctx: ToolExecutionContext) -> Result<Vec<Content>, McpError> {
        let path = Path::new(&args.path);

        // Open repository
        let repo = crate::open_repo(path)
            .await
            .map_err(|e| McpError::Other(anyhow::anyhow!("Task execution failed: {e}")))?
            .map_err(|e| McpError::Other(anyhow::anyhow!("{e}")))?;

        // Build merge options (note inverse logic for no_ff)
        let mut opts = crate::MergeOpts::new(&args.branch);
        opts = opts.no_ff(!args.fast_forward); // Inverse logic
        opts = opts.commit(args.auto_commit);

        // Execute merge
        let outcome = crate::merge(repo, opts)
            .await
            .map_err(|e| McpError::Other(anyhow::anyhow!("{e}")))?;

        let mut contents = Vec::new();

        let (merge_type, commit_id) = match outcome {
            crate::MergeOutcome::FastForward(id) => {
                ("fast_forward", id.to_string())
            },
            crate::MergeOutcome::MergeCommit(id) => {
                ("merge_commit", id.to_string())
            },
            crate::MergeOutcome::AlreadyUpToDate => {
                // Terminal summary
                let summary = format!("✓ Already up to date\n\nBranch: {}", args.branch);
                contents.push(Content::text(summary));

                // JSON metadata
                let metadata = json!({
                    "success": true,
                    "merge_type": "already_up_to_date",
                    "message": "Already up to date"
                });
                let json_str = serde_json::to_string_pretty(&metadata)
                    .unwrap_or_else(|_| "{}".to_string());
                contents.push(Content::text(json_str));

                return Ok(contents);
            }
        };

        // Terminal summary with ANSI yellow color and Nerd Font icons
        // Successful merges have no conflicts (conflicts cause errors in the merge operation)
        let summary = format!(
            "\x1b[33m\u{e727} Merge: {}\x1b[0m\n\
             \u{2139} Strategy: {} · Conflicts: 0",
            args.branch, merge_type
        );
        contents.push(Content::text(summary));

        // JSON metadata
        let metadata = json!({
            "success": true,
            "merge_type": merge_type,
            "commit_id": commit_id,
            "message": format!("Merged '{}' ({})", args.branch, merge_type)
        });
        let json_str = serde_json::to_string_pretty(&metadata)
            .unwrap_or_else(|_| "{}".to_string());
        contents.push(Content::text(json_str));

        Ok(contents)
    }

    fn prompt_arguments() -> Vec<PromptArgument> {
        vec![PromptArgument {
            name: "merge_strategy".to_string(),
            title: None,
            description: Some(
                "Type of merge example to focus on (e.g., 'fast_forward', 'merge_commit', 'conflicts')".to_string()
            ),
            required: Some(false),
        }]
    }

    async fn prompt(&self, _args: Self::PromptArgs) -> Result<Vec<PromptMessage>, McpError> {
        Ok(vec![
            PromptMessage {
                role: PromptMessageRole::User,
                content: PromptMessageContent::text(
                    "How do I merge branches with git_merge? What are the different merge strategies?",
                ),
            },
            PromptMessage {
                role: PromptMessageRole::Assistant,
                content: PromptMessageContent::text(
                    "The git_merge tool integrates changes from one branch into another. It supports \
                     two merge strategies:\n\n\
                     1. Fast-forward (default): Directly moves HEAD to the merged commit if possible\n\
                        git_merge({\"path\": \".\", \"branch\": \"feature\", \"fast_forward\": true})\n\n\
                     2. Merge commit: Always creates a merge commit, even if fast-forward is possible\n\
                        git_merge({\"path\": \".\", \"branch\": \"feature\", \"fast_forward\": false})\n\n\
                     Key parameters:\n\
                     - path: Repository directory\n\
                     - branch: Branch name to merge into current branch\n\
                     - fast_forward: Allow fast-forward merges (default: true)\n\
                     - auto_commit: Automatically commit after merge (default: true)\n\n\
                     Common workflows:\n\
                     - Feature branch merge: merge feature into main with merge commit\n\
                     - Rebase alternative: use fast_forward for linear history\n\
                     - Manual conflict resolution: use auto_commit=false to stage changes\n\n\
                     Important notes:\n\
                     - Conflicts cause the merge to fail (prevents accidental commits)\n\
                     - Use auto_commit=false to review and stage changes before committing\n\
                     - Fast-forward requires linear history (no diverging commits)\n\
                     - Merge commits preserve branch history in the repository",
                ),
            },
        ])
    }
}
