using System.IO;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Windows;
using AxCopilot.SDK;
using AxCopilot.Services;

namespace AxCopilot.Handlers;

/// <summary>
/// L27-4: 회의 링크 전용 관리 핸들러. "meet" 프리픽스로 사용합니다.
///
/// 예: meet                            → 전체 회의 목록
///     meet 스탠드업                   → 이름 검색
///     meet add 스탠드업 https://...   → 회의 추가
///     meet del 스탠드업               → 회의 삭제
/// Enter → 기본 브라우저로 회의 링크 열기.
/// 저장: %APPDATA%\AxCopilot\meet.json
/// </summary>
public class MeetHandler : IActionHandler
{
    public string? Prefix => "meet";

    public PluginMetadata Metadata => new(
        "회의 링크",
        "회의 링크 관리 — 추가 · 검색 · 즉시 열기",
        "1.0",
        "AX");

    private record MeetEntry(
        [property: JsonPropertyName("name")] string Name,
        [property: JsonPropertyName("url")]  string Url,
        [property: JsonPropertyName("service")] string Service);

    private static readonly string DataPath = Path.Combine(
        Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
        "AxCopilot", "meet.json");

    private static readonly JsonSerializerOptions JsonOpt = new()
    {
        WriteIndented = true,
        Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
    };

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

        // ── add 명령 ─────────────────────────────────────────────────────────
        if (q.StartsWith("add ", StringComparison.OrdinalIgnoreCase))
        {
            var parts = q[4..].Trim().Split(' ', 2, StringSplitOptions.RemoveEmptyEntries);
            if (parts.Length < 2 || !Uri.TryCreate(parts[1], UriKind.Absolute, out _))
            {
                items.Add(new LauncherItem("사용법: meet add {이름} {URL}",
                    "예: meet add 스탠드업 https://teams.microsoft.com/...",
                    null, null, Symbol: "\uE710"));
            }
            else
            {
                var name = parts[0];
                var url  = parts[1];
                var svc  = DetectService(url);
                items.Add(new LauncherItem(
                    $"회의 추가: {name}",
                    $"{svc} · {url}",
                    null, ("add", $"{name}\t{url}\t{svc}"), Symbol: "\uE710"));
            }
            return Task.FromResult<IEnumerable<LauncherItem>>(items);
        }

        // ── del 명령 ─────────────────────────────────────────────────────────
        if (q.StartsWith("del ", StringComparison.OrdinalIgnoreCase))
        {
            var name = q[4..].Trim();
            var found = meets.FirstOrDefault(m =>
                m.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
            if (found != null)
            {
                items.Add(new LauncherItem(
                    $"회의 삭제: {found.Name}",
                    $"{found.Service} · {found.Url}",
                    null, ("del", found.Name), Symbol: "\uE74D"));
            }
            else
            {
                items.Add(new LauncherItem($"'{name}' 회의를 찾을 수 없습니다",
                    "meet del {이름}", null, null, Symbol: "\uE783"));
            }
            return Task.FromResult<IEnumerable<LauncherItem>>(items);
        }

        // ── 빈 쿼리 → 전체 목록 ──────────────────────────────────────────────
        if (string.IsNullOrWhiteSpace(q))
        {
            if (meets.Count == 0)
            {
                items.Add(new LauncherItem("등록된 회의가 없습니다",
                    "meet add {이름} {URL} 로 추가하세요",
                    null, null, Symbol: "\uE8D6"));
                return Task.FromResult<IEnumerable<LauncherItem>>(items);
            }

            items.Add(new LauncherItem(
                $"회의 {meets.Count}개 등록됨",
                "Enter: 브라우저로 열기 · meet add/del 로 관리",
                null, null, Symbol: "\uE8D6"));

            foreach (var m in meets)
                items.Add(MeetItem(m));

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

        // ── 검색 ──────────────────────────────────────────────────────────────
        var searched = meets.Where(m =>
            m.Name.Contains(q, StringComparison.OrdinalIgnoreCase) ||
            m.Service.Contains(q, StringComparison.OrdinalIgnoreCase) ||
            m.Url.Contains(q, StringComparison.OrdinalIgnoreCase)).ToList();

        if (searched.Count == 0)
        {
            items.Add(new LauncherItem($"'{q}' 회의를 찾을 수 없습니다",
                "meet add {이름} {URL} 로 추가하세요",
                null, null, Symbol: "\uE783"));
        }
        else
        {
            foreach (var m in searched)
                items.Add(MeetItem(m));
        }

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

    public Task ExecuteAsync(LauncherItem item, CancellationToken ct)
    {
        if (item.Data is ("add", string addData))
        {
            var parts = addData.Split('\t');
            if (parts.Length >= 3)
            {
                var meets = Load();
                meets.RemoveAll(m => m.Name.Equals(parts[0], StringComparison.OrdinalIgnoreCase));
                meets.Add(new MeetEntry(parts[0], parts[1], parts[2]));
                Save(meets);
                NotificationService.Notify("meet", $"'{parts[0]}' 회의가 추가되었습니다.");
            }
        }
        else if (item.Data is ("del", string delName))
        {
            var meets = Load();
            int removed = meets.RemoveAll(m => m.Name.Equals(delName, StringComparison.OrdinalIgnoreCase));
            Save(meets);
            if (removed > 0)
                NotificationService.Notify("meet", $"'{delName}' 회의가 삭제되었습니다.");
        }
        else if (item.Data is ("open", string url))
        {
            try
            {
                System.Diagnostics.Process.Start(
                    new System.Diagnostics.ProcessStartInfo(url) { UseShellExecute = true });
            }
            catch (Exception ex)
            {
                NotificationService.Notify("meet", $"열기 실패: {ex.Message}");
            }
        }

        return Task.CompletedTask;
    }

    // ─── 헬퍼 ────────────────────────────────────────────────────────────────

    private static LauncherItem MeetItem(MeetEntry m)
    {
        var icon = m.Service switch
        {
            "Zoom"        => "\uE774",
            "Teams"       => "\uE8D6",
            "Google Meet" => "\uE774",
            "Webex"       => "\uE774",
            _             => "\uE774"
        };

        return new LauncherItem(
            $"{m.Name}  [{m.Service}]",
            m.Url,
            null, ("open", m.Url), Symbol: icon);
    }

    private static string DetectService(string url)
    {
        var lower = url.ToLowerInvariant();
        if (lower.Contains("zoom.us") || lower.Contains("zoom.com")) return "Zoom";
        if (lower.Contains("teams.microsoft.com") || lower.Contains("teams.live.com")) return "Teams";
        if (lower.Contains("meet.google.com")) return "Google Meet";
        if (lower.Contains("webex.com")) return "Webex";
        if (lower.Contains("discord.gg") || lower.Contains("discord.com")) return "Discord";
        if (lower.Contains("slack.com")) return "Slack";
        return "기타";
    }

    // ─── JSON 파일 I/O ───────────────────────────────────────────────────────

    private static List<MeetEntry> Load()
    {
        try
        {
            if (!File.Exists(DataPath)) return [];
            var json = File.ReadAllText(DataPath);
            return JsonSerializer.Deserialize<List<MeetEntry>>(json) ?? [];
        }
        catch { return []; }
    }

    private static void Save(List<MeetEntry> list)
    {
        try
        {
            var dir = Path.GetDirectoryName(DataPath)!;
            if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);
            File.WriteAllText(DataPath, JsonSerializer.Serialize(list, JsonOpt));
        }
        catch { }
    }
}
