using System.Text;
using System.Windows;
using AxCopilot.SDK;
using AxCopilot.Services;
using AxCopilot.Themes;

namespace AxCopilot.Handlers;

/// <summary>
/// L15-1: WSL(Windows Subsystem for Linux) 관리 핸들러. "wsl" 프리픽스로 사용합니다.
///
/// 예: wsl                   → 설치된 distro 목록 + 상태
///     wsl ubuntu            → Ubuntu 실행 (새 터미널)
///     wsl stop ubuntu       → 특정 distro 종료
///     wsl stop all          → 전체 WSL 종료
///     wsl default ubuntu    → 기본 distro 변경
/// Enter → distro 실행 또는 명령 실행.
/// </summary>
public class WslHandler : IActionHandler
{
    public string? Prefix => "wsl";

    public PluginMetadata Metadata => new(
        "WSL",
        "WSL 관리 — distro 목록 · 실행 · 종료",
        "1.0",
        "AX");

    public Task<IEnumerable<LauncherItem>> GetItemsAsync(string query, CancellationToken ct)
    {
        var q     = query.Trim();
        var items = new List<LauncherItem>();

        var distros = GetDistros();

        if (string.IsNullOrWhiteSpace(q))
        {
            if (distros.Count == 0)
            {
                items.Add(new LauncherItem("WSL 없음",
                    "WSL이 설치되지 않았거나 distro가 없습니다", null, null, Symbol: "\uE756"));
                items.Add(new LauncherItem("WSL 설치",
                    "Microsoft Store에서 Ubuntu 등 설치", null,
                    ("open_url", "ms-windows-store://search/?query=linux"), Symbol: "\uE756"));
                return Task.FromResult<IEnumerable<LauncherItem>>(items);
            }

            items.Add(new LauncherItem(
                $"WSL distro  {distros.Count}개",
                "Enter → 실행  /  wsl stop all → 전체 종료",
                null, null, Symbol: "\uE756"));

            foreach (var d in distros)
                items.Add(MakeDistroItem(d));

            items.Add(new LauncherItem("wsl stop all", "전체 WSL 종료 (wsl --shutdown)", null,
                ("shutdown", ""), Symbol: "\uE756"));
            return Task.FromResult<IEnumerable<LauncherItem>>(items);
        }

        var parts = q.Split(' ', StringSplitOptions.RemoveEmptyEntries);
        var sub   = parts[0].ToLowerInvariant();

        switch (sub)
        {
            case "stop":
            case "shutdown":
            case "kill":
            {
                var target = parts.Length > 1 ? parts[1].ToLowerInvariant() : "all";
                if (target == "all" || target == "--all")
                {
                    items.Add(new LauncherItem("WSL 전체 종료", "wsl --shutdown  · Enter 실행",
                        null, ("shutdown", ""), Symbol: "\uE756"));
                }
                else
                {
                    var found = distros.FirstOrDefault(d =>
                        d.Name.Contains(target, StringComparison.OrdinalIgnoreCase));
                    if (found == null)
                        items.Add(new LauncherItem("없는 distro", $"'{target}'를 찾을 수 없습니다", null, null, Symbol: "\uE783"));
                    else
                        items.Add(new LauncherItem($"{found.Name} 종료", $"wsl --terminate {found.Name}",
                            null, ("terminate", found.Name), Symbol: "\uE756"));
                }
                break;
            }

            case "default":
            case "set-default":
            {
                var target = parts.Length > 1 ? parts[1] : "";
                if (string.IsNullOrWhiteSpace(target))
                {
                    items.Add(new LauncherItem("distro 이름 입력", "예: wsl default Ubuntu", null, null, Symbol: "\uE783"));
                    break;
                }
                items.Add(new LauncherItem($"기본 distro: {target}",
                    $"wsl --set-default {target}  · Enter 실행",
                    null, ("set_default", target), Symbol: "\uE756"));
                break;
            }

            default:
            {
                // distro 이름 검색 → 실행
                var found = distros.Where(d =>
                    d.Name.Contains(q, StringComparison.OrdinalIgnoreCase)).ToList();

                if (found.Count > 0)
                    foreach (var d in found)
                        items.Add(MakeDistroItem(d));
                else
                    items.Add(new LauncherItem($"'{q}' distro 없음",
                        "wsl 입력으로 전체 목록 확인", null, null, Symbol: "\uE946"));
                break;
            }
        }

        return Task.FromResult<IEnumerable<LauncherItem>>(items);
    }

    public Task ExecuteAsync(LauncherItem item, CancellationToken ct)
    {
        switch (item.Data)
        {
            case ("launch", string distro):
                RunWsl($"-d \"{distro}\"");
                break;

            case ("shutdown", _):
                RunWslSilent("--shutdown");
                NotificationService.Notify("WSL", "WSL 전체 종료 요청됨");
                break;

            case ("terminate", string distro):
                RunWslSilent($"--terminate \"{distro}\"");
                NotificationService.Notify("WSL", $"{distro} 종료됨");
                break;

            case ("set_default", string distro):
                RunWslSilent($"--set-default \"{distro}\"");
                NotificationService.Notify("WSL", $"기본 distro → {distro}");
                break;

            case ("open_url", string url):
                try
                {
                    System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo
                    {
                        FileName = url, UseShellExecute = true,
                    });
                }
                catch { /* 비핵심 */ }
                break;

            case ("copy", string text):
                try
                {
                    System.Windows.Application.Current.Dispatcher.Invoke(() => Clipboard.SetText(text));
                    NotificationService.Notify("WSL", "복사됨");
                }
                catch { /* 비핵심 */ }
                break;
        }
        return Task.CompletedTask;
    }

    // ── WSL 조회 ─────────────────────────────────────────────────────────────

    private record WslDistro(string Name, string State, string Version, bool IsDefault);

    private static List<WslDistro> GetDistros()
    {
        var result = new List<WslDistro>();
        try
        {
            var psi = new System.Diagnostics.ProcessStartInfo
            {
                FileName               = "wsl",
                Arguments              = "--list --verbose",
                UseShellExecute        = false,
                RedirectStandardOutput = true,
                CreateNoWindow         = true,
                StandardOutputEncoding = Encoding.Unicode, // WSL outputs UTF-16
            };
            using var proc = System.Diagnostics.Process.Start(psi);
            if (proc == null) return result;

            var output = proc.StandardOutput.ReadToEnd();
            proc.WaitForExit(3000);

            foreach (var line in output.Split('\n').Skip(1)) // 첫 줄은 헤더
            {
                var trimmed = line.Trim().TrimEnd('\r');
                if (string.IsNullOrWhiteSpace(trimmed)) continue;

                var isDefault = trimmed.StartsWith('*');
                trimmed = trimmed.TrimStart('*').Trim();

                var parts = trimmed.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
                if (parts.Length < 2) continue;

                result.Add(new WslDistro(
                    Name:      parts[0],
                    State:     parts.Length > 1 ? parts[1] : "Unknown",
                    Version:   parts.Length > 2 ? parts[2] : "?",
                    IsDefault: isDefault));
            }
        }
        catch { /* WSL 없음 */ }
        return result;
    }

    private static LauncherItem MakeDistroItem(WslDistro d)
    {
        var icon    = d.State.Equals("Running", StringComparison.OrdinalIgnoreCase) ? "\uE768" : "\uE756";
        var label   = d.IsDefault ? $"★ {d.Name}" : d.Name;
        var subtitle = $"{d.State}  ·  WSL {d.Version}" + (d.IsDefault ? "  (기본)" : "");
        return new LauncherItem(label, subtitle, null, ("launch", d.Name), Symbol: icon);
    }

    private static void RunWsl(string args)
    {
        // 터미널에서 실행 (wt 또는 powershell 폴백)
        var wtPath = FindExe("wt.exe");
        if (wtPath != null)
        {
            System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo
            {
                FileName        = wtPath,
                Arguments       = $"wsl {args}",
                UseShellExecute = false,
            });
        }
        else
        {
            System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo
            {
                FileName        = "wsl",
                Arguments       = args,
                UseShellExecute = true,
            });
        }
    }

    private static void RunWslSilent(string args)
    {
        try
        {
            var psi = new System.Diagnostics.ProcessStartInfo
            {
                FileName        = "wsl",
                Arguments       = args,
                UseShellExecute = false,
                CreateNoWindow  = true,
            };
            using var proc = System.Diagnostics.Process.Start(psi);
            proc?.WaitForExit(5000);
        }
        catch { /* 비핵심 */ }
    }

    private static string? FindExe(string name)
    {
        var pathEnv = Environment.GetEnvironmentVariable("PATH") ?? "";
        foreach (var dir in pathEnv.Split(';'))
        {
            var full = System.IO.Path.Combine(dir.Trim(), name);
            if (System.IO.File.Exists(full)) return full;
        }
        return null;
    }
}
