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

namespace AxCopilot.Handlers;

/// <summary>
/// L8-3: 시스템 이벤트 로그 핸들러. "evt" 프리픽스로 사용합니다.
///
/// 예: evt                  → 최근 오류/경고 이벤트 (System + Application 합산)
///     evt error            → 오류(Error) 이벤트만
///     evt warn             → 경고(Warning) 이벤트만
///     evt app              → Application 로그
///     evt sys              → System 로그
///     evt <키워드>          → 소스 또는 메시지에 키워드 포함된 이벤트
/// Enter → 이벤트 내용을 클립보드에 복사.
/// </summary>
public class EventLogHandler : IActionHandler
{
    public string? Prefix => "evt";

    public PluginMetadata Metadata => new(
        "EventLog",
        "Windows 이벤트 로그 — 오류 · 경고 · 소스별 조회",
        "1.0",
        "AX");

    private const int MaxItems  = 20;
    private const int LookbackH = 24; // 최근 24시간

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

        try
        {
            // 필터 결정
            var logName   = "System";
            var level     = EventLogEntryType.Error; // 기본 오류
            bool allLevel = false;
            string keyword = "";

            if (q == "app")    { logName = "Application"; allLevel = false; }
            else if (q == "sys") { logName = "System"; allLevel = false; }
            else if (q == "error")  { allLevel = false; level = EventLogEntryType.Error; }
            else if (q is "warn" or "warning") { allLevel = false; level = EventLogEntryType.Warning; }
            else if (string.IsNullOrEmpty(q))  { allLevel = false; /* Error 기본 */ }
            else { keyword = q; allLevel = true; }

            // System + Application 병합 또는 단일 로그
            var logNames = string.IsNullOrEmpty(q) || q is "error" or "warn" or "warning"
                ? new[] { "System", "Application" }
                : logName == "Application" ? new[] { "Application" } : new[] { logName };

            var entries = new List<EventLogEntry>();
            var cutoff  = DateTime.Now.AddHours(-LookbackH);

            foreach (var ln in logNames)
            {
                try
                {
                    using var log = new EventLog(ln);
                    for (int i = log.Entries.Count - 1; i >= 0 && entries.Count < MaxItems * 2; i--)
                    {
                        var entry = log.Entries[i];
                        if (entry.TimeGenerated < cutoff) break;

                        bool matchLevel = allLevel
                            ? true
                            : entry.EntryType == level;

                        bool matchKeyword = string.IsNullOrEmpty(keyword)
                            ? true
                            : (entry.Source?.Contains(keyword, StringComparison.OrdinalIgnoreCase) == true
                               || entry.Message?.Contains(keyword, StringComparison.OrdinalIgnoreCase) == true);

                        if (matchLevel && matchKeyword)
                            entries.Add(entry);
                    }
                }
                catch { /* 특정 로그 접근 실패 시 무시 */ }
            }

            if (entries.Count == 0)
            {
                items.Add(new LauncherItem(
                    "이벤트 없음",
                    $"최근 {LookbackH}시간 내 해당 이벤트가 없습니다",
                    null, null, Symbol: "\uE73E"));
                return Task.FromResult<IEnumerable<LauncherItem>>(items);
            }

            // 정렬 (최신 순) 및 중복 제거
            var sorted = entries
                .OrderByDescending(e => e.TimeGenerated)
                .Take(MaxItems)
                .ToList();

            foreach (var entry in sorted)
            {
                var icon   = entry.EntryType == EventLogEntryType.Error   ? "\uE783" :
                             entry.EntryType == EventLogEntryType.Warning ? "\uE7BA" : "\uE946";
                var level2 = entry.EntryType == EventLogEntryType.Error   ? "오류"   :
                             entry.EntryType == EventLogEntryType.Warning ? "경고"   : "정보";

                var msg = entry.Message ?? "";
                if (msg.Length > 80) msg = msg[..80].Replace('\n', ' ').Replace('\r', ' ') + "…";

                items.Add(new LauncherItem(
                    $"[{level2}] {entry.Source}",
                    $"{entry.TimeGenerated:MM-dd HH:mm}  ·  {msg}",
                    null,
                    ("copy_event", FormatEvent(entry)),
                    Symbol: icon));
            }
        }
        catch (Exception ex)
        {
            items.Add(new LauncherItem(
                "이벤트 로그 접근 실패",
                ex.Message,
                null, null, Symbol: "\uE783"));
        }

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

    public Task ExecuteAsync(LauncherItem item, CancellationToken ct)
    {
        if (item.Data is ("copy_event", string eventText))
        {
            try
            {
                System.Windows.Application.Current.Dispatcher.Invoke(
                    () => Clipboard.SetText(eventText));
                NotificationService.Notify("EventLog", "이벤트 정보를 클립보드에 복사했습니다.");
            }
            catch { /* 비핵심 */ }
        }
        return Task.CompletedTask;
    }

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

    private static string FormatEvent(EventLogEntry e) =>
        $"""
        [이벤트 ID] {e.InstanceId}
        [시각]      {e.TimeGenerated:yyyy-MM-dd HH:mm:ss}
        [유형]      {e.EntryType}
        [소스]      {e.Source}
        [메시지]
        {e.Message}
        """;
}
