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

namespace AxCopilot.Handlers;

/// <summary>
/// L7-3: 시간대 변환기 핸들러. "tz" 프리픽스로 사용합니다.
///
/// 예: tz                    → 주요 도시 현재 시각 목록
///     tz seoul              → 서울 현재 시각
///     tz new york           → 뉴욕 현재 시각
///     tz 14:30 to la        → 현재 시간대(KST) 14:30을 LA 시각으로 변환
///     tz meeting 09:00      → 서울 기준 9시 = 주요 도시별 동일 시각 표시
/// Enter → 결과를 클립보드에 복사.
/// </summary>
public class TimeZoneHandler : IActionHandler
{
    public string? Prefix => "tz";

    public PluginMetadata Metadata => new(
        "TimeZone",
        "시간대 변환기 — 주요 도시 현재 시각 · 시각 변환",
        "1.0",
        "AX");

    // ── 주요 도시 시간대 목록 ──────────────────────────────────────────────
    private static readonly (string City, string TzId, string Flag, string[] Aliases)[] Cities =
    [
        ("서울",       "Korea Standard Time",            "🇰🇷", ["seoul", "서울", "부산", "인천", "kst", "한국"]),
        ("도쿄",       "Tokyo Standard Time",            "🇯🇵", ["tokyo", "도쿄", "osaka", "오사카", "jst", "일본"]),
        ("베이징",     "China Standard Time",            "🇨🇳", ["beijing", "베이징", "상하이", "shanghai", "cst", "중국"]),
        ("방콕",       "SE Asia Standard Time",          "🇹🇭", ["bangkok", "방콕", "ict", "태국"]),
        ("두바이",     "Arabian Standard Time",          "🇦🇪", ["dubai", "두바이", "gst", "uae"]),
        ("모스크바",   "Russia Time Zone 2",             "🇷🇺", ["moscow", "모스크바", "msk", "러시아"]),
        ("파리",       "Romance Standard Time",          "🇫🇷", ["paris", "파리", "cet", "프랑스"]),
        ("런던",       "GMT Standard Time",              "🇬🇧", ["london", "런던", "gmt", "영국"]),
        ("뉴욕",       "Eastern Standard Time",          "🇺🇸", ["new york", "뉴욕", "nyc", "est", "동부"]),
        ("시카고",     "Central Standard Time",          "🇺🇸", ["chicago", "시카고", "cst", "중부"]),
        ("로스앤젤레스","Pacific Standard Time",         "🇺🇸", ["los angeles", "la", "로스앤젤레스", "pst", "서부"]),
        ("시드니",     "AUS Eastern Standard Time",      "🇦🇺", ["sydney", "시드니", "aest", "호주"]),
        ("싱가포르",   "Singapore Standard Time",        "🇸🇬", ["singapore", "싱가포르", "sgt"]),
        ("뭄바이",     "India Standard Time",            "🇮🇳", ["mumbai", "뭄바이", "ist", "인도"]),
        ("도하",       "Arab Standard Time",             "🇶🇦", ["doha", "도하", "ast", "카타르"]),
    ];

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

        if (string.IsNullOrWhiteSpace(q))
        {
            // 주요 도시 현재 시각 목록
            items.Add(new LauncherItem(
                "주요 도시 현재 시각",
                $"기준: UTC {now:HH:mm}",
                null, null, Symbol: "\uE917"));

            foreach (var (city, tzId, flag, _) in Cities)
            {
                var (timeStr, offsetStr) = GetCityTime(tzId, now);
                items.Add(new LauncherItem(
                    $"{flag} {city}",
                    $"{timeStr}  ({offsetStr})",
                    null,
                    ("copy_time", $"{city}: {timeStr} ({offsetStr})"),
                    Symbol: "\uE917"));
            }
            return Task.FromResult<IEnumerable<LauncherItem>>(items);
        }

        // "meeting HH:mm" 모드 — 서울 기준 특정 시각을 전 도시 변환
        if (q.StartsWith("meeting ") || q.StartsWith("미팅 "))
        {
            var timePart = q.Contains(' ') ? q[(q.IndexOf(' ') + 1)..].Trim() : "";
            return Task.FromResult<IEnumerable<LauncherItem>>(
                BuildMeetingItems(timePart, now));
        }

        // "HH:mm to <city>" 또는 "HH:mm <city>" 변환 모드
        var convResult = TryParseConversion(q, now);
        if (convResult != null)
            return Task.FromResult<IEnumerable<LauncherItem>>(convResult);

        // 도시 검색
        var matched = Cities
            .Where(c => c.Aliases.Any(a => a.Contains(q)))
            .ToList();

        if (matched.Count > 0)
        {
            foreach (var (city, tzId, flag, _) in matched)
            {
                var (timeStr, offsetStr) = GetCityTime(tzId, now);
                items.Add(new LauncherItem(
                    $"{flag} {city}  {timeStr}",
                    $"UTC {offsetStr}",
                    null,
                    ("copy_time", $"{city}: {timeStr} ({offsetStr})"),
                    Symbol: "\uE917"));

                // 이 도시와 서울의 시차
                var seoulOffset = GetOffset("Korea Standard Time");
                var cityOffset  = GetOffset(tzId);
                var diff        = (cityOffset - seoulOffset).TotalHours;
                var diffStr     = diff == 0 ? "서울과 동일" :
                                  diff > 0  ? $"서울보다 +{diff:+0;-0}시간" :
                                              $"서울보다 {diff:+0;-0}시간";
                items.Add(new LauncherItem(
                    diffStr,
                    "서울(KST) 기준 시차",
                    null, null, Symbol: "\uE8F4"));
            }
        }
        else
        {
            // 미인식 → 모든 도시 표시
            foreach (var (city, tzId, flag, _) in Cities)
            {
                var (timeStr, offsetStr) = GetCityTime(tzId, now);
                items.Add(new LauncherItem(
                    $"{flag} {city}  {timeStr}",
                    offsetStr,
                    null,
                    ("copy_time", $"{city}: {timeStr} ({offsetStr})"),
                    Symbol: "\uE917"));
            }
        }

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

    public Task ExecuteAsync(LauncherItem item, CancellationToken ct)
    {
        if (item.Data is ("copy_time", string text))
        {
            try
            {
                System.Windows.Application.Current.Dispatcher.Invoke(
                    () => Clipboard.SetText(text));
                NotificationService.Notify("시간대", "클립보드에 복사했습니다.");
            }
            catch { /* 비핵심 */ }
        }
        return Task.CompletedTask;
    }

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

    private static (string Time, string Offset) GetCityTime(string tzId, DateTimeOffset utcNow)
    {
        try
        {
            var tz  = TimeZoneInfo.FindSystemTimeZoneById(tzId);
            var local = TimeZoneInfo.ConvertTime(utcNow, tz);
            var off   = tz.GetUtcOffset(utcNow);
            var offStr = $"UTC{(off >= TimeSpan.Zero ? "+" : "")}{off.Hours:D2}:{off.Minutes:D2}";
            return (local.ToString("HH:mm (ddd)"), offStr);
        }
        catch
        {
            return ("--:--", "");
        }
    }

    private static TimeSpan GetOffset(string tzId)
    {
        try
        {
            var tz = TimeZoneInfo.FindSystemTimeZoneById(tzId);
            return tz.GetUtcOffset(DateTimeOffset.UtcNow);
        }
        catch { return TimeSpan.Zero; }
    }

    private IEnumerable<LauncherItem> BuildMeetingItems(string timePart, DateTimeOffset utcNow)
    {
        var items = new List<LauncherItem>();

        if (!TimeOnly.TryParse(timePart, out var meetingTime))
        {
            items.Add(new LauncherItem("시각 형식 오류",
                "HH:mm 형식으로 입력하세요 (예: tz meeting 10:00)",
                null, null, Symbol: "\uE783"));
            return items;
        }

        // 서울 기준으로 날짜+시각 설정
        var seoulTz    = TimeZoneInfo.FindSystemTimeZoneById("Korea Standard Time");
        var seoulNow   = TimeZoneInfo.ConvertTime(utcNow, seoulTz);
        var seoulDt    = new DateTimeOffset(seoulNow.Date.AddHours(meetingTime.Hour).AddMinutes(meetingTime.Minute),
                                            seoulTz.GetUtcOffset(utcNow));
        var seoulUtc   = seoulDt.ToUniversalTime();

        items.Add(new LauncherItem(
            $"🇰🇷 서울 미팅 시각: {meetingTime:HH:mm}",
            "주요 도시 동일 시각", null, null, Symbol: "\uE917"));

        foreach (var (city, tzId, flag, _) in Cities)
        {
            if (tzId == "Korea Standard Time") continue;
            var (timeStr, offsetStr) = GetCityTime(tzId, seoulUtc);
            items.Add(new LauncherItem(
                $"{flag} {city}  {timeStr}",
                offsetStr,
                null,
                ("copy_time", $"{city}: {timeStr}"),
                Symbol: "\uE917"));
        }
        return items;
    }

    private IEnumerable<LauncherItem>? TryParseConversion(string q, DateTimeOffset utcNow)
    {
        // "HH:mm to <city>" 또는 "HH:mm <city>" 패턴
        var sep   = q.Contains(" to ") ? " to " : q.Contains(' ') ? " " : null;
        if (sep == null) return null;

        var parts = q.Split(sep, 2);
        if (parts.Length < 2) return null;

        if (!TimeOnly.TryParse(parts[0].Trim(), out var inputTime)) return null;

        var cityQuery = parts[1].Trim().ToLowerInvariant();
        var targetCities = Cities
            .Where(c => c.Aliases.Any(a => a.Contains(cityQuery)))
            .ToList();

        if (targetCities.Count == 0) return null;

        var items = new List<LauncherItem>();
        // 서울 기준으로 입력 시각 해석
        var seoulTz  = TimeZoneInfo.FindSystemTimeZoneById("Korea Standard Time");
        var seoulNow = TimeZoneInfo.ConvertTime(utcNow, seoulTz);
        var seoulDt  = new DateTimeOffset(
            seoulNow.Date.AddHours(inputTime.Hour).AddMinutes(inputTime.Minute),
            seoulTz.GetUtcOffset(utcNow));
        var seoulUtc = seoulDt.ToUniversalTime();

        items.Add(new LauncherItem(
            $"🇰🇷 서울 {inputTime:HH:mm} 기준 변환",
            "Enter → 클립보드 복사", null, null, Symbol: "\uE8F4"));

        foreach (var (city, tzId, flag, _) in targetCities)
        {
            var (timeStr, offsetStr) = GetCityTime(tzId, seoulUtc);
            items.Add(new LauncherItem(
                $"{flag} {city}  {timeStr}",
                offsetStr,
                null,
                ("copy_time", $"{city}: {timeStr}"),
                Symbol: "\uE917"));
        }
        return items;
    }
}
