namespace AxCopilot.Core;

/// <summary>
/// "Alt+Space", "Ctrl+Shift+K" 형식의 핫키 문자열 파싱/포맷 유틸리티.
/// </summary>
public static class HotkeyParser
{
    private static readonly Dictionary<string, int> _keyMap =
        new(StringComparer.OrdinalIgnoreCase)
    {
        // 특수키
        ["Space"]    = 0x20, ["Enter"] = 0x0D, ["Return"] = 0x0D,
        ["Tab"]      = 0x09, ["Esc"]   = 0x1B, ["Escape"] = 0x1B,
        ["Backspace"]= 0x08, ["Back"]  = 0x08,
        ["Delete"]   = 0x2E, ["Del"]   = 0x2E,
        ["Insert"]   = 0x2D, ["Ins"]   = 0x2D,
        ["Home"]     = 0x24, ["End"]   = 0x23,
        ["PageUp"]   = 0x21, ["PgUp"]  = 0x21,
        ["PageDown"] = 0x22, ["PgDn"]  = 0x22,
        ["PrintScreen"] = 0x2C, ["PrtSc"] = 0x2C, ["Snapshot"] = 0x2C,
        ["Pause"] = 0x13, ["Break"] = 0x13,
        ["ScrollLock"] = 0x91,
        // 방향키
        ["Left"] = 0x25, ["Up"] = 0x26, ["Right"] = 0x27, ["Down"] = 0x28,
        // 기호
        ["`"]  = 0xC0, ["Grave"] = 0xC0,
        ["-"]  = 0xBD, ["="]    = 0xBB,
        ["["]  = 0xDB, ["]"]    = 0xDD,
        ["\\"] = 0xDC, [";"]    = 0xBA,
        ["'"]  = 0xDE, [","]    = 0xBC,
        ["."]  = 0xBE, ["/"]    = 0xBF,
    };

    static HotkeyParser()
    {
        // A–Z
        for (char c = 'A'; c <= 'Z'; c++)
            _keyMap[c.ToString()] = c;
        // 0–9
        for (char c = '0'; c <= '9'; c++)
            _keyMap[c.ToString()] = c;
        // F1–F24
        for (int i = 1; i <= 24; i++)
            _keyMap[$"F{i}"] = 0x6F + i;
        // Numpad 0–9
        for (int i = 0; i <= 9; i++)
            _keyMap[$"Num{i}"] = 0x60 + i;
    }

    /// <summary>
    /// "Alt+Space" → <see cref="HotkeyDefinition"/>. 실패 시 false 반환.
    /// </summary>
    public static bool TryParse(string hotkey, out HotkeyDefinition result)
    {
        result = default;
        if (string.IsNullOrWhiteSpace(hotkey)) return false;

        var parts = hotkey.Split('+',
            StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries);

        bool ctrl = false, alt = false, shift = false, win = false;
        int? vkCode = null;

        foreach (var p in parts)
        {
            if (p.Equals("Ctrl", StringComparison.OrdinalIgnoreCase) ||
                p.Equals("Control", StringComparison.OrdinalIgnoreCase))
            { ctrl = true; continue; }

            if (p.Equals("Alt", StringComparison.OrdinalIgnoreCase))
            { alt = true; continue; }

            if (p.Equals("Shift", StringComparison.OrdinalIgnoreCase))
            { shift = true; continue; }

            if (p.Equals("Win", StringComparison.OrdinalIgnoreCase) ||
                p.Equals("Windows", StringComparison.OrdinalIgnoreCase))
            { win = true; continue; }

            if (_keyMap.TryGetValue(p, out int vk))
                vkCode = vk;
            else
                return false; // 알 수 없는 키
        }

        if (vkCode == null) return false;
        result = new HotkeyDefinition(vkCode.Value, ctrl, alt, shift, win);
        return true;
    }

    /// <summary>
    /// <see cref="HotkeyDefinition"/> → "Alt+Space" 형식 문자열.
    /// </summary>
    public static string Format(HotkeyDefinition def)
    {
        var parts = new List<string>(5);
        if (def.Ctrl)  parts.Add("Ctrl");
        if (def.Alt)   parts.Add("Alt");
        if (def.Shift) parts.Add("Shift");
        if (def.Win)   parts.Add("Win");
        parts.Add(VkToName(def.VkCode));
        return string.Join("+", parts);
    }

    // VK 코드 → 읽기 좋은 이름 변환
    private static string VkToName(int vk)
    {
        if (vk >= 0x41 && vk <= 0x5A) return ((char)vk).ToString();   // A–Z
        if (vk >= 0x30 && vk <= 0x39) return ((char)vk).ToString();   // 0–9
        if (vk >= 0x70 && vk <= 0x87) return $"F{vk - 0x6F}";        // F1–F24
        if (vk >= 0x60 && vk <= 0x69) return $"Num{vk - 0x60}";      // Numpad

        // 특수키 테이블에서 긴 이름 우선 검색
        string? best = null;
        foreach (var (name, code) in _keyMap)
        {
            if (code == vk && (best == null || name.Length > best.Length))
                best = name;
        }
        return best ?? $"0x{vk:X2}";
    }
}

/// <summary>
/// 파싱된 핫키 정의. VK 코드 + 요구 수정자 키.
/// </summary>
public record struct HotkeyDefinition(int VkCode, bool Ctrl, bool Alt, bool Shift, bool Win);
