using System.Globalization;
using System.Text.RegularExpressions;
using System.Windows;
using AxCopilot.SDK;
using AxCopilot.Themes;

namespace AxCopilot.Handlers;

/// <summary>
/// 날짜/시간 변환기 핸들러. "date" 프리픽스로 사용합니다.
/// 예: date              → 현재 날짜/시간 + 유닉스 타임스탬프
///     date +30d         → 오늘 + 30일
///     date -100d        → 오늘 - 100일
///     date 2026-12-25   → 해당 날짜까지 D-day + 요일
///     date 1711584000   → 유닉스 타임스탬프 → 날짜
///     date to unix      → 현재 시각의 유닉스 타임스탬프
/// Enter → 결과를 클립보드에 복사.
/// </summary>
public class DateCalcHandler : IActionHandler
{
    public string? Prefix => "date";

    public PluginMetadata Metadata => new(
        "DateCalc",
        "날짜 계산 · D-day · 타임스탬프 변환",
        "1.0",
        "AX");

    private static readonly string[] DateFormats =
        ["yyyy-MM-dd", "yyyy/MM/dd", "yyyyMMdd", "MM/dd/yyyy", "dd-MM-yyyy"];

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

        if (string.IsNullOrWhiteSpace(q))
        {
            // 현재 날짜/시간 정보
            var dayName = now.ToString("dddd", new CultureInfo("ko-KR"));
            items.Add(Item($"{now:yyyy-MM-dd} ({dayName})", $"{now:HH:mm:ss}  ·  {now:yyyy-MM-dd}"));
            items.Add(Item($"유닉스 타임스탬프: {new DateTimeOffset(now).ToUnixTimeSeconds()}", "현재 시각의 Unix epoch"));
            items.Add(Item($"올해 {now.DayOfYear}일째 / 남은 일: {(new DateTime(now.Year, 12, 31) - now).Days}일",
                $"ISO 주차: {ISOWeek.GetWeekOfYear(now)}주"));
            return Task.FromResult<IEnumerable<LauncherItem>>(items);
        }

        // +30d / -100d 패턴
        var offsetMatch = Regex.Match(q, @"^([+-])(\d+)([dDwWmMyY])$");
        if (offsetMatch.Success)
        {
            var sign = offsetMatch.Groups[1].Value == "+" ? 1 : -1;
            var val = int.Parse(offsetMatch.Groups[2].Value) * sign;
            var unit = offsetMatch.Groups[3].Value.ToLowerInvariant();
            var target = unit switch
            {
                "d" => now.AddDays(val),
                "w" => now.AddDays(val * 7),
                "m" => now.AddMonths(val),
                "y" => now.AddYears(val),
                _ => now
            };
            var dayName = target.ToString("dddd", new CultureInfo("ko-KR"));
            var diff = (target.Date - now.Date).Days;
            var diffStr = diff >= 0 ? $"오늘로부터 {diff}일 후" : $"오늘로부터 {Math.Abs(diff)}일 전";

            items.Add(Item($"{target:yyyy-MM-dd} ({dayName})", diffStr));
            return Task.FromResult<IEnumerable<LauncherItem>>(items);
        }

        // 유닉스 타임스탬프 (10자리 또는 13자리 숫자)
        if (Regex.IsMatch(q, @"^\d{10,13}$") && long.TryParse(q, out long epoch))
        {
            var ts = epoch > 9_999_999_999 ? epoch / 1000 : epoch; // 밀리초→초
            var dt = DateTimeOffset.FromUnixTimeSeconds(ts).LocalDateTime;
            var dayName = dt.ToString("dddd", new CultureInfo("ko-KR"));
            items.Add(Item($"{dt:yyyy-MM-dd HH:mm:ss} ({dayName})", $"Unix {epoch} → 로컬 시간"));
            return Task.FromResult<IEnumerable<LauncherItem>>(items);
        }

        // "to unix" / "unix" 키워드
        if (q.Equals("unix", StringComparison.OrdinalIgnoreCase) ||
            q.Equals("to unix", StringComparison.OrdinalIgnoreCase))
        {
            var unix = new DateTimeOffset(now).ToUnixTimeSeconds();
            items.Add(Item($"{unix}", $"현재 시각 ({now:yyyy-MM-dd HH:mm:ss}) → Unix 타임스탬프"));
            return Task.FromResult<IEnumerable<LauncherItem>>(items);
        }

        // 날짜 파싱 → D-day 계산
        if (DateTime.TryParseExact(q, DateFormats, CultureInfo.InvariantCulture,
                DateTimeStyles.None, out var parsed))
        {
            var dayName = parsed.ToString("dddd", new CultureInfo("ko-KR"));
            var diff = (parsed.Date - now.Date).Days;
            var dday = diff switch
            {
                0 => "오늘",
                > 0 => $"D-{diff} (앞으로 {diff}일)",
                _ => $"D+{Math.Abs(diff)} ({Math.Abs(diff)}일 지남)"
            };

            items.Add(Item($"{parsed:yyyy-MM-dd} ({dayName})", dday));
            return Task.FromResult<IEnumerable<LauncherItem>>(items);
        }

        items.Add(new LauncherItem(
            "날짜 형식을 인식할 수 없습니다",
            "예: +30d, -100d, 2026-12-25, 1711584000, unix",
            null, null, Symbol: Symbols.Warning));

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

    private static LauncherItem Item(string title, string subtitle) =>
        new(title, $"{subtitle}  ·  Enter로 복사", null, title, Symbol: Symbols.Clock);

    public Task ExecuteAsync(LauncherItem item, CancellationToken ct)
    {
        if (item.Data is string text && !string.IsNullOrWhiteSpace(text))
        {
            try { Application.Current?.Dispatcher.Invoke(() => Clipboard.SetText(text)); }
            catch (Exception) { }
        }
        return Task.CompletedTask;
    }
}
