using System.Runtime.InteropServices;
using AxCopilot.SDK;
using AxCopilot.Services;
using AxCopilot.Themes;

namespace AxCopilot.Handlers;

/// <summary>
/// 미디어 컨트롤 핸들러. "media" 프리픽스로 사용합니다.
/// 예: media play      → 재생/일시정지
///     media next      → 다음 트랙
///     media prev      → 이전 트랙
///     media vol+      → 볼륨 올리기
///     media vol-      → 볼륨 낮추기
///     media mute      → 음소거 토글
/// </summary>
public class MediaHandler : IActionHandler
{
    public string? Prefix => "media";

    public PluginMetadata Metadata => new(
        "MediaControl",
        "미디어 컨트롤 — media 뒤에 명령어 입력",
        "1.0",
        "AX");

    // Windows 미디어/볼륨 가상 키 코드
    private const byte VK_MEDIA_PLAY_PAUSE  = 0xB3;
    private const byte VK_MEDIA_NEXT_TRACK  = 0xB0;
    private const byte VK_MEDIA_PREV_TRACK  = 0xB1;
    private const byte VK_VOLUME_UP         = 0xAF;
    private const byte VK_VOLUME_DOWN       = 0xAE;
    private const byte VK_VOLUME_MUTE       = 0xAD;

    // KEYEVENTF flags
    private const uint KEYEVENTF_EXTENDEDKEY = 0x0001;
    private const uint KEYEVENTF_KEYUP       = 0x0002;

    [DllImport("user32.dll", SetLastError = false)]
    private static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, nuint dwExtraInfo);

    // 명령어 → (제목, 설명, VK코드, 심볼)
    private static readonly List<(string[] Keys, string Title, string Subtitle, byte Vk, string Symbol)> _commands =
    [
        (["play", "pause", "pp"],  "재생 / 일시정지",     "현재 미디어 재생 또는 일시정지",   VK_MEDIA_PLAY_PAUSE, Symbols.MediaPlay),
        (["next", ">>"],           "다음 트랙",           "다음 곡으로 이동",                  VK_MEDIA_NEXT_TRACK, Symbols.MediaNext),
        (["prev", "previous", "<<"], "이전 트랙",         "이전 곡으로 이동",                  VK_MEDIA_PREV_TRACK, Symbols.MediaPrev),
        (["vol+", "volup", "up"],  "볼륨 올리기",         "시스템 볼륨 증가",                  VK_VOLUME_UP,        Symbols.VolumeUp),
        (["vol-", "voldown", "down"], "볼륨 낮추기",      "시스템 볼륨 감소",                  VK_VOLUME_DOWN,      Symbols.VolumeDown),
        (["mute", "음소거"],        "음소거 토글",         "볼륨 음소거 / 해제",                VK_VOLUME_MUTE,      Symbols.VolumeMute),
    ];

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

        IEnumerable<(string[] Keys, string Title, string Subtitle, byte Vk, string Symbol)> matches;

        if (string.IsNullOrEmpty(q))
        {
            // 쿼리 없으면 전체 목록 표시
            matches = _commands;
        }
        else
        {
            // 입력어와 일치하는 명령 필터
            matches = _commands.Where(c =>
                c.Keys.Any(k => k.StartsWith(q, StringComparison.OrdinalIgnoreCase)) ||
                c.Title.Contains(q, StringComparison.OrdinalIgnoreCase));
        }

        var items = matches
            .Select(c => new LauncherItem(c.Title, c.Subtitle, null, new MediaKeyData(c.Vk), Symbol: c.Symbol))
            .ToList();

        if (items.Count == 0)
        {
            items.Add(new LauncherItem(
                "알 수 없는 명령어",
                "play · next · prev · vol+ · vol- · mute 중 하나를 입력하세요",
                null, null, Symbol: Symbols.Warning));
        }

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

    public Task ExecuteAsync(LauncherItem item, CancellationToken ct)
    {
        if (item.Data is not MediaKeyData data) return Task.CompletedTask;

        try
        {
            // 키 누름 → 키 뗌
            keybd_event(data.Vk, 0, KEYEVENTF_EXTENDEDKEY, 0);
            keybd_event(data.Vk, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
            LogService.Info($"미디어 키 전송: VK=0x{data.Vk:X2}");
        }
        catch (Exception ex)
        {
            LogService.Warn($"미디어 키 전송 실패: {ex.Message}");
        }

        return Task.CompletedTask;
    }

    private record MediaKeyData(byte Vk);
}
