using System.Diagnostics;
using System.IO;
using System.Text;
using System.Text.Json;
using Microsoft.Win32;

namespace AxCopilot.Services.Agent;

/// <summary>
/// 개발 환경 감지 도구.
/// IDE, 언어 런타임, 빌드 도구의 설치 여부와 경로를 자동 감지합니다.
/// 사내 환경에서 설치된 도구만 사용하도록 LLM에 정보를 제공합니다.
/// </summary>
public class DevEnvDetectTool : IAgentTool
{
    public string Name => "dev_env_detect";
    public string Description =>
        "Detect installed development tools on this machine. " +
        "Returns: IDEs (VS Code, Visual Studio, IntelliJ, PyCharm), " +
        "language runtimes (dotnet, python/conda, java, node, gcc/g++), " +
        "and build tools (MSBuild, Maven, Gradle, CMake, npm/yarn). " +
        "Use this before running build/test commands to know what's available.";

    public ToolParameterSchema Parameters => new()
    {
        Properties = new()
        {
            ["category"] = new()
            {
                Type = "string",
                Description = "Detection category: all (default), ides, runtimes, build_tools",
                Enum = ["all", "ides", "runtimes", "build_tools"],
            },
        },
        Required = []
    };

    // 60초 캐시
    private static (DateTime Time, string Result)? _cache;

    public Task<ToolResult> ExecuteAsync(JsonElement args, AgentContext context, CancellationToken ct)
    {
        var category = args.TryGetProperty("category", out var cat) ? cat.GetString() ?? "all" : "all";

        // 캐시 확인
        if (_cache.HasValue && (DateTime.UtcNow - _cache.Value.Time).TotalSeconds < 60)
            return Task.FromResult(ToolResult.Ok(_cache.Value.Result));

        var sb = new StringBuilder();
        sb.AppendLine("=== 개발 환경 감지 보고서 ===\n");

        if (category is "all" or "ides")
        {
            sb.AppendLine("## IDE");
            DetectIde(sb, "VS Code", DetectVsCode);
            DetectIde(sb, "Visual Studio", DetectVisualStudio);
            DetectIde(sb, "IntelliJ IDEA", () => DetectJetBrains("IntelliJ"));
            DetectIde(sb, "PyCharm", () => DetectJetBrains("PyCharm"));
            sb.AppendLine();
        }

        if (category is "all" or "runtimes")
        {
            sb.AppendLine("## Language Runtimes");
            DetectCommand(sb, "dotnet", "dotnet --version", "DOTNET_ROOT");
            DetectCommand(sb, "python", "python --version", "PYTHON_HOME");
            DetectCommand(sb, "conda", "conda --version", "CONDA_PREFIX");
            DetectCommand(sb, "java", "java -version", "JAVA_HOME");
            DetectCommand(sb, "node", "node --version", "NODE_HOME");
            DetectCommand(sb, "npm", "npm --version", null);
            DetectCommand(sb, "gcc", "gcc --version", null);
            DetectCommand(sb, "g++", "g++ --version", null);
            sb.AppendLine();
        }

        if (category is "all" or "build_tools")
        {
            sb.AppendLine("## Build Tools");
            DetectCommand(sb, "MSBuild", "msbuild -version", null);
            DetectCommand(sb, "Maven", "mvn --version", "MAVEN_HOME");
            DetectCommand(sb, "Gradle", "gradle --version", "GRADLE_HOME");
            DetectCommand(sb, "CMake", "cmake --version", null);
            DetectCommand(sb, "yarn", "yarn --version", null);
            DetectCommand(sb, "pip", "pip --version", null);
            sb.AppendLine();
        }

        var result = sb.ToString();
        _cache = (DateTime.UtcNow, result);
        return Task.FromResult(ToolResult.Ok(result));
    }

    private static void DetectIde(StringBuilder sb, string name, Func<string?> detector)
    {
        var path = detector();
        sb.AppendLine(path != null ? $"  ✅ {name}: {path}" : $"  ❌ {name}: 미설치");
    }

    private static void DetectCommand(StringBuilder sb, string name, string versionCmd, string? envVar)
    {
        // 환경변수 확인
        string? envPath = null;
        if (envVar != null)
            envPath = Environment.GetEnvironmentVariable(envVar);

        // where.exe로 PATH 확인
        var wherePath = RunQuick("where.exe", name);
        var version = "";

        if (wherePath != null)
        {
            // 버전 확인
            var parts = versionCmd.Split(' ', 2);
            var verOutput = RunQuick(parts[0], parts.Length > 1 ? parts[1] : "");
            if (verOutput != null)
                version = verOutput.Split('\n')[0].Trim();
        }

        if (wherePath != null)
            sb.AppendLine($"  ✅ {name}: {version} ({wherePath.Split('\n')[0].Trim()})");
        else if (envPath != null)
            sb.AppendLine($"  ⚠ {name}: 환경변수만 ({envVar}={envPath})");
        else
            sb.AppendLine($"  ❌ {name}: 미설치");
    }

    private static string? RunQuick(string exe, string args)
    {
        try
        {
            var psi = new ProcessStartInfo(exe, args)
            {
                RedirectStandardOutput = true,
                RedirectStandardError = true,
                UseShellExecute = false,
                CreateNoWindow = true,
            };
            using var proc = Process.Start(psi);
            if (proc == null) return null;
            var output = proc.StandardOutput.ReadToEnd();
            var error = proc.StandardError.ReadToEnd();
            proc.WaitForExit(5000);
            var result = string.IsNullOrWhiteSpace(output) ? error : output;
            return string.IsNullOrWhiteSpace(result) ? null : result.Trim();
        }
        catch (Exception) { return null; }
    }

    private static string? DetectVsCode()
    {
        // PATH 확인
        var where = RunQuick("where.exe", "code");
        if (where != null) return where.Split('\n')[0].Trim();

        // 기본 설치 경로
        var localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
        var defaultPath = Path.Combine(localAppData, "Programs", "Microsoft VS Code", "Code.exe");
        return File.Exists(defaultPath) ? defaultPath : null;
    }

    private static string? DetectVisualStudio()
    {
        try
        {
            // 레지스트리에서 Visual Studio 설치 경로 검색
            using var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\VisualStudio\SxS\VS7");
            if (key != null)
            {
                foreach (var name in key.GetValueNames().OrderByDescending(n => n))
                {
                    var path = key.GetValue(name)?.ToString();
                    if (!string.IsNullOrEmpty(path) && Directory.Exists(path))
                        return $"Visual Studio {name} ({path})";
                }
            }

            // WOW6432Node 확인
            using var key32 = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\WOW6432Node\Microsoft\VisualStudio\SxS\VS7");
            if (key32 != null)
            {
                foreach (var name in key32.GetValueNames().OrderByDescending(n => n))
                {
                    var path = key32.GetValue(name)?.ToString();
                    if (!string.IsNullOrEmpty(path) && Directory.Exists(path))
                        return $"Visual Studio {name} ({path})";
                }
            }
        }
        catch (Exception) { }

        // devenv.exe PATH 확인
        var where = RunQuick("where.exe", "devenv");
        return where != null ? where.Split('\n')[0].Trim() : null;
    }

    private static string? DetectJetBrains(string product)
    {
        try
        {
            using var key = Registry.LocalMachine.OpenSubKey($@"SOFTWARE\JetBrains\{product}");
            if (key != null)
            {
                var subKeys = key.GetSubKeyNames().OrderByDescending(n => n).ToArray();
                if (subKeys.Length > 0)
                {
                    using var verKey = key.OpenSubKey(subKeys[0]);
                    var installDir = verKey?.GetValue("InstallDir")?.ToString()
                                  ?? verKey?.GetValue("")?.ToString();
                    if (!string.IsNullOrEmpty(installDir))
                        return $"{product} {subKeys[0]} ({installDir})";
                }
            }
        }
        catch (Exception) { }
        return null;
    }
}
