namespace Armada.Helm.Commands
{
    using System.ComponentModel;
    using Spectre.Console;
    using Spectre.Console.Cli;
    using Armada.Core.Settings;

    /// <summary>
    /// Configure MCP integration for supported clients.
    /// </summary>
    [Description("Configure MCP integration for Claude Code, Codex, Gemini, and Cursor")]
    public class McpInstallCommand : BaseCommand<McpInstallSettings>
    {
        /// <inheritdoc />
        public override async Task<int> ExecuteAsync(CommandContext context, McpInstallSettings settings, CancellationToken cancellationToken)
        {
            ArmadaSettings armadaSettings = await ArmadaSettings.LoadAsync().ConfigureAwait(false);
            string mcpRpcUrl = McpConfigHelper.GetMcpRpcUrl(armadaSettings.McpPort);
            List<McpConfigHelper.ConfigTarget> targets = McpConfigHelper.BuildTargets(armadaSettings.McpPort);
            List<McpConfigHelper.InstructionTarget> instructionTargets = McpConfigHelper.BuildInstructionTargets();

            AnsiConsole.MarkupLine("[bold dodgerblue1]Armada MCP Install[/]");
            AnsiConsole.MarkupLine($"[dim]MCP endpoint:[/] [green]{Markup.Escape(mcpRpcUrl)}[/]");
            AnsiConsole.WriteLine();

            if (settings.DryRun)
            {
                AnsiConsole.MarkupLine("[yellow]Dry run:[/] no files will be modified.");
                AnsiConsole.WriteLine();
            }

            foreach (McpConfigHelper.ConfigTarget target in targets)
            {
                WriteClientHeader(target.ClientName);

                bool shouldWrite = settings.DryRun || settings.Yes || AnsiConsole.Confirm(
                    $"[dodgerblue1]Configure[/] [green]{target.ClientName}[/] at [green]{Markup.Escape(target.FilePath)}[/]?",
                    true);

                if (!shouldWrite)
                {
                    AnsiConsole.MarkupLine($"[yellow]{target.ClientName}[/]: skipped.");
                }
                else if (!settings.DryRun)
                {
                    McpConfigHelper.ApplyResult result = await McpConfigHelper.InstallTargetAsync(target).ConfigureAwait(false);
                    WriteResult(result);
                }
                else
                {
                    AnsiConsole.MarkupLine($"[yellow]{target.ClientName}[/]: would configure [green]{Markup.Escape(target.FilePath)}[/].");
                }

                if (target.InstallAgent)
                {
                    bool shouldInstallAgent = settings.DryRun || settings.Yes || AnsiConsole.Confirm(
                        $"[dodgerblue1]Install/update[/] Claude Code Armada agent at [green]{Markup.Escape(McpConfigHelper.GetClaudeAgentPath())}[/]?",
                        true);

                    if (!shouldInstallAgent)
                    {
                        AnsiConsole.MarkupLine("[yellow]Claude Code Agent[/]: skipped.");
                    }
                    else if (!settings.DryRun)
                    {
                        McpConfigHelper.ApplyResult agentResult = await McpConfigHelper.InstallClaudeAgentAsync().ConfigureAwait(false);
                        WriteResult(agentResult);
                    }
                    else
                    {
                        AnsiConsole.MarkupLine($"[yellow]Claude Code Agent[/]: would configure [green]{Markup.Escape(McpConfigHelper.GetClaudeAgentPath())}[/].");
                    }
                }

                WriteManualSection(target, armadaSettings.McpPort);
            }

            foreach (McpConfigHelper.InstructionTarget target in instructionTargets)
            {
                WriteClientHeader(target.ClientName);

                bool shouldWrite = settings.DryRun || settings.Yes || AnsiConsole.Confirm(
                    $"[dodgerblue1]Install/update[/] Armada instructions for [green]{target.ClientName}[/] at [green]{Markup.Escape(target.FilePath)}[/]?",
                    true);

                if (!shouldWrite)
                {
                    AnsiConsole.MarkupLine($"[yellow]{target.ClientName}[/]: skipped.");
                }
                else if (!settings.DryRun)
                {
                    WriteResult(await McpConfigHelper.InstallInstructionTargetAsync(target).ConfigureAwait(false));
                }
                else
                {
                    AnsiConsole.MarkupLine($"[yellow]{target.ClientName}[/]: would configure [green]{Markup.Escape(target.FilePath)}[/].");
                }
            }

            AnsiConsole.WriteLine();
            AnsiConsole.MarkupLine("[bold]What You Need To Do[/]");
            AnsiConsole.WriteLine();
            AnsiConsole.MarkupLine("[bold]Required[/]");
            AnsiConsole.MarkupLine("[green]1.[/] Start the Admiral server for Claude Code, Gemini CLI, and Cursor: [green]armada server start[/]");
            AnsiConsole.MarkupLine("[green]2.[/] Restart any MCP client you want to use so it reloads the new config.");
            AnsiConsole.WriteLine();
            AnsiConsole.MarkupLine("[bold]Only If Needed[/]");
            AnsiConsole.MarkupLine("[green]3.[/] Re-run [green]install-mcp[/] from each project where you want project-scoped files updated.");
            AnsiConsole.MarkupLine($"[dim]Project-scoped files:[/] [green]{Markup.Escape(McpConfigHelper.GetProjectAgentsPath())}[/], [green]{Markup.Escape(McpConfigHelper.GetProjectGeminiInstructionsPath())}[/], [green]{Markup.Escape(McpConfigHelper.GetCursorConfigPath())}[/]");
            AnsiConsole.MarkupLine("[green]4.[/] Use the manual snippets above only if automatic setup was skipped or failed.");
            AnsiConsole.WriteLine();
            AnsiConsole.MarkupLine("[dim]Codex uses stdio MCP by default, so it does not need the HTTP server.[/]");

            return 0;
        }

        private static void WriteResult(McpConfigHelper.ApplyResult result)
        {
            string scope = result.IsProjectScoped ? "project" : "user";
            string color = result.Changed ? "green" : "gold1";
            AnsiConsole.MarkupLine($"[{color}]{result.ClientName}[/] ({scope}-scoped): {Markup.Escape(result.Message)}");
            AnsiConsole.MarkupLine($"  [dim]{Markup.Escape(result.FilePath)}[/]");
        }

        private static void WriteManualSection(McpConfigHelper.ConfigTarget target, int mcpPort)
        {
            AnsiConsole.WriteLine();
            AnsiConsole.MarkupLine($"[bold]{target.ClientName} manual snippet[/] -> [green]{Markup.Escape(target.FilePath)}[/]");
            if (!String.IsNullOrEmpty(target.ManualInstallCommand))
            {
                AnsiConsole.MarkupLine("[dim]Run this command:[/]");
                AnsiConsole.MarkupLine($"[green]  {Markup.Escape(McpConfigHelper.BuildManualSnippet(target))}[/]");
            }
            else
            {
                Console.WriteLine(McpConfigHelper.BuildManualSnippet(target));
            }
            if (target.ClientName == "Claude Code")
            {
                AnsiConsole.MarkupLine("[dim]Claude CLI helper:[/]");
                AnsiConsole.MarkupLine($"[green]  {Markup.Escape(McpConfigHelper.BuildClaudeCliCommand(mcpPort))}[/]");
                AnsiConsole.MarkupLine("[dim]Claude stdio alternative:[/]");
                AnsiConsole.MarkupLine($"[green]  {Markup.Escape(McpConfigHelper.BuildClaudeStdioCommand())}[/]");
                AnsiConsole.MarkupLine($"[dim]Claude agent file:[/] [green]{Markup.Escape(McpConfigHelper.GetClaudeAgentPath())}[/]");
            }
            AnsiConsole.WriteLine();
        }

        private static void WriteClientHeader(string clientName)
        {
            AnsiConsole.WriteLine();
            AnsiConsole.Write(new Rule($"[bold]{Markup.Escape(clientName)}[/]").RuleStyle("grey"));
            AnsiConsole.WriteLine();
        }
    }
}
