using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
using AxCopilot.Services;

namespace AxCopilot.Views;

/// <summary>에이전트 실행 통계 대시보드 창.</summary>
public partial class AgentStatsDashboardWindow : Window
{
    private int _currentDays = 1; // 현재 필터 (오늘=1)

    public AgentStatsDashboardWindow()
    {
        InitializeComponent();
        Loaded += (_, _) => LoadStats(_currentDays);
    }

    // ─── 이벤트 핸들러 ────────────────────────────────────────────────────

    private void TitleBar_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        // 타이틀바 우측 닫기 버튼 영역에서는 DragMove 실행하지 않음
        var pos = e.GetPosition(this);
        if (pos.X > ActualWidth - 50) return;

        if (e.ClickCount == 2)
        {
            WindowState = WindowState == WindowState.Maximized
                ? WindowState.Normal : WindowState.Maximized;
        }
        else DragMove();
    }

    private void BtnClose_Click(object sender, MouseButtonEventArgs e) => Close();

    private void Filter_Click(object sender, MouseButtonEventArgs e)
    {
        if (sender is not Border b || b.Tag is not string tagStr) return;
        if (!int.TryParse(tagStr, out var days)) return;

        _currentDays = days;
        UpdateFilterButtons(b);
        LoadStats(days);
    }

    private void BtnClearStats_Click(object sender, MouseButtonEventArgs e)
    {
        var result = CustomMessageBox.Show(
            "모든 통계 데이터를 삭제하시겠습니까?\n이 작업은 되돌릴 수 없습니다.",
            "통계 초기화",
            MessageBoxButton.YesNo, MessageBoxImage.Question);
        if (result != MessageBoxResult.Yes) return;

        AgentStatsService.Clear();
        LoadStats(_currentDays);
    }

    // ─── 통계 로드/렌더링 ─────────────────────────────────────────────────

    private void LoadStats(int days)
    {
        var summary = AgentStatsService.Aggregate(days);
        RenderSummaryCards(summary);
        RenderDailyChart(summary, days);
        RenderToolFreq(summary);
        RenderBreakdowns(summary);
        UpdateStatus(summary, days);
    }

    private void RenderSummaryCards(AgentStatsService.AgentStatsSummary s)
    {
        SummaryCards.Children.Clear();
        SummaryCards.Children.Add(MakeSummaryCard("\uE9D9", "총 실행",   s.TotalSessions.ToString("N0"),  "#A78BFA"));
        SummaryCards.Children.Add(MakeSummaryCard("\uE8A7", "도구 호출", s.TotalToolCalls.ToString("N0"), "#3B82F6"));
        SummaryCards.Children.Add(MakeSummaryCard("\uE7C8", "총 토큰",   FormatTokens(s.TotalTokens),     "#10B981"));
        SummaryCards.Children.Add(MakeSummaryCard("\uE916", "평균 시간",
            s.TotalSessions > 0
                ? $"{TimeSpan.FromMilliseconds((double)s.TotalDurationMs / s.TotalSessions):mm\\:ss}"
                : "—",
            "#F59E0B"));
    }

    private Border MakeSummaryCard(string icon, string label, string value, string colorHex)
    {
        var bg  = TryFindResource("ItemBackground") as Brush
                  ?? new SolidColorBrush(Color.FromRgb(0x2A, 0x2A, 0x40));
        var fg  = TryFindResource("PrimaryText")    as Brush ?? Brushes.White;
        var sub = TryFindResource("SecondaryText")  as Brush ?? Brushes.Gray;
        var col = (Color)ColorConverter.ConvertFromString(colorHex);

        var card = new Border
        {
            Background   = bg,
            CornerRadius = new CornerRadius(10),
            Padding      = new Thickness(14, 12, 14, 12),
            Margin       = new Thickness(0, 0, 8, 0),
        };
        var sp = new StackPanel();
        sp.Children.Add(new TextBlock
        {
            Text       = icon,
            FontFamily = ThemeResourceHelper.SegoeMdl2,
            FontSize   = 16,
            Foreground = new SolidColorBrush(col),
            Margin     = new Thickness(0, 0, 0, 6),
        });
        sp.Children.Add(new TextBlock
        {
            Text       = value,
            FontSize   = 20,
            FontWeight = FontWeights.Bold,
            Foreground = fg,
        });
        sp.Children.Add(new TextBlock
        {
            Text       = label,
            FontSize   = 11,
            Foreground = sub,
            Margin     = new Thickness(0, 2, 0, 0),
        });
        card.Child = sp;
        return card;
    }

    private void RenderDailyChart(AgentStatsService.AgentStatsSummary s, int days)
    {
        DailyBarChart.Children.Clear();
        DailyBarLabels.Children.Clear();

        // 최근 N일 날짜 범위 구성
        var endDate   = DateTime.Today;
        int chartDays = days == 1 ? 1 : days == 0 ? 30 : days;
        var dates     = Enumerable.Range(0, chartDays)
                                  .Select(i => endDate.AddDays(-(chartDays - 1 - i)))
                                  .ToList();

        var maxVal = dates
            .Select(d => s.DailySessions.GetValueOrDefault(d.ToString("yyyy-MM-dd"), 0))
            .DefaultIfEmpty(0).Max();
        if (maxVal == 0) maxVal = 1;

        var barColor = (Color)ColorConverter.ConvertFromString("#4B5EFC");
        var chartW   = 748.0; // 근사값 (Canvas는 레이아웃 후 ActualWidth 확정)
        var barGap   = 2.0;
        var barW     = Math.Max(4, (chartW - barGap * dates.Count) / dates.Count);
        var chartH   = 100.0;

        for (int i = 0; i < dates.Count; i++)
        {
            var dateKey = dates[i].ToString("yyyy-MM-dd");
            var val     = s.DailySessions.GetValueOrDefault(dateKey, 0);
            var barH    = Math.Max(2, val / (double)maxVal * (chartH - 4));
            var x       = i * (barW + barGap);

            var rect = new Rectangle
            {
                Width            = barW,
                Height           = barH,
                Fill             = new SolidColorBrush(Color.FromArgb(0xCC,
                    barColor.R, barColor.G, barColor.B)),
                RadiusX          = 3,
                RadiusY          = 3,
                ToolTip          = $"{dateKey}: {val}회",
            };
            Canvas.SetLeft(rect, x);
            Canvas.SetTop(rect, chartH - barH);
            DailyBarChart.Children.Add(rect);

            // 레이블: 7일 이하면 모두 표시, 그 이상이면 월요일만
            if (dates.Count <= 7 || dates[i].DayOfWeek == DayOfWeek.Monday)
            {
                var lbl = new TextBlock
                {
                    Text       = dates[i].ToString("MM/dd"),
                    FontSize   = 9,
                    Foreground = TryFindResource("SecondaryText") as Brush ?? Brushes.Gray,
                };
                Canvas.SetLeft(lbl, x);
                DailyBarLabels.Children.Add(lbl);
            }
        }
    }

    private void RenderToolFreq(AgentStatsService.AgentStatsSummary s)
    {
        ToolFreqPanel.Children.Clear();
        if (s.ToolFrequency.Count == 0)
        {
            ToolFreqPanel.Children.Add(new TextBlock
            {
                Text       = "데이터 없음",
                FontSize   = 12,
                Foreground = TryFindResource("SecondaryText") as Brush ?? Brushes.Gray,
            });
            return;
        }

        var maxVal   = s.ToolFrequency.Values.Max();
        var barColor = (Color)ColorConverter.ConvertFromString("#3B82F6");

        foreach (var (tool, count) in s.ToolFrequency)
        {
            var ratio = (double)count / maxVal;
            var row   = new Grid { Margin = new Thickness(0, 2, 0, 2) };
            row.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(120) });
            row.ColumnDefinitions.Add(new ColumnDefinition());
            row.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(36) });

            var nameTb = new TextBlock
            {
                Text       = tool,
                FontSize   = 11,
                FontFamily = ThemeResourceHelper.Consolas,
                Foreground = TryFindResource("PrimaryText") as Brush ?? Brushes.White,
                TextTrimming = TextTrimming.CharacterEllipsis,
                VerticalAlignment = VerticalAlignment.Center,
            };
            Grid.SetColumn(nameTb, 0);

            var barBg = new Border
            {
                Background   = new SolidColorBrush(Color.FromArgb(0x20, 0x3B, 0x82, 0xF6)),
                CornerRadius = new CornerRadius(3),
                Height       = 10,
                Margin       = new Thickness(6, 0, 4, 0),
                VerticalAlignment = VerticalAlignment.Center,
            };
            var barFg = new Border
            {
                Background   = new SolidColorBrush(Color.FromArgb(0xCC, barColor.R, barColor.G, barColor.B)),
                CornerRadius = new CornerRadius(3),
                Height       = 10,
                HorizontalAlignment = HorizontalAlignment.Left,
            };
            barFg.Width = ratio * 150; // 최대 150px
            barBg.Child = barFg;
            Grid.SetColumn(barBg, 1);

            var countTb = new TextBlock
            {
                Text       = count.ToString(),
                FontSize   = 11,
                FontWeight = FontWeights.SemiBold,
                Foreground = TryFindResource("SecondaryText") as Brush ?? Brushes.Gray,
                HorizontalAlignment = HorizontalAlignment.Right,
                VerticalAlignment   = VerticalAlignment.Center,
            };
            Grid.SetColumn(countTb, 2);

            row.Children.Add(nameTb);
            row.Children.Add(barBg);
            row.Children.Add(countTb);
            ToolFreqPanel.Children.Add(row);
        }
    }

    private void RenderBreakdowns(AgentStatsService.AgentStatsSummary s)
    {
        // 탭 분포
        TabBreakPanel.Children.Clear();
        var tabColors = new Dictionary<string, string>
        {
            ["Cowork"] = "#A78BFA",
            ["Code"]   = "#34D399",
            ["Chat"]   = "#3B82F6",
        };
        foreach (var (tab, count) in s.TabBreakdown.OrderByDescending(kv => kv.Value))
        {
            var c = tabColors.GetValueOrDefault(tab, "#9CA3AF");
            TabBreakPanel.Children.Add(MakeBreakRow(tab, count, c,
                s.TabBreakdown.Values.DefaultIfEmpty(1).Max()));
        }
        if (s.TabBreakdown.Count == 0)
            TabBreakPanel.Children.Add(MakeEmptyText());

        // 모델 분포
        ModelBreakPanel.Children.Clear();
        foreach (var (model, count) in s.ModelBreakdown.OrderByDescending(kv => kv.Value))
        {
            var shortName = model.Length > 18 ? model[..18] + "…" : model;
            ModelBreakPanel.Children.Add(MakeBreakRow(shortName, count, "#F59E0B",
                s.ModelBreakdown.Values.DefaultIfEmpty(1).Max()));
        }
        if (s.ModelBreakdown.Count == 0)
            ModelBreakPanel.Children.Add(MakeEmptyText());
    }

    private UIElement MakeBreakRow(string label, int count, string colorHex, int maxVal)
    {
        var ratio = maxVal > 0 ? (double)count / maxVal : 0;
        var col   = (Color)ColorConverter.ConvertFromString(colorHex);

        var row = new StackPanel { Margin = new Thickness(0, 2, 0, 2) };
        var header = new Grid();
        header.ColumnDefinitions.Add(new ColumnDefinition());
        header.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Auto) });

        var lbl = new TextBlock
        {
            Text      = label,
            FontSize  = 11,
            Foreground = TryFindResource("PrimaryText") as Brush ?? Brushes.White,
        };
        Grid.SetColumn(lbl, 0);

        var cnt = new TextBlock
        {
            Text      = count.ToString(),
            FontSize  = 11,
            FontWeight= FontWeights.SemiBold,
            Foreground = TryFindResource("SecondaryText") as Brush ?? Brushes.Gray,
        };
        Grid.SetColumn(cnt, 1);
        header.Children.Add(lbl);
        header.Children.Add(cnt);
        row.Children.Add(header);

        // 바 차트
        var barBg = new Border
        {
            Background   = new SolidColorBrush(Color.FromArgb(0x20, col.R, col.G, col.B)),
            CornerRadius = new CornerRadius(3),
            Height       = 6,
            Margin       = new Thickness(0, 3, 0, 0),
        };
        var barFg = new Border
        {
            Background   = new SolidColorBrush(Color.FromArgb(0xCC, col.R, col.G, col.B)),
            CornerRadius = new CornerRadius(3),
            Height       = 6,
            HorizontalAlignment = HorizontalAlignment.Left,
        };
        barFg.Width = ratio * 160; // 최대 160px
        barBg.Child = barFg;
        row.Children.Add(barBg);
        return row;
    }

    private TextBlock MakeEmptyText() => new()
    {
        Text       = "데이터 없음",
        FontSize   = 11,
        Foreground = TryFindResource("SecondaryText") as Brush ?? Brushes.Gray,
    };

    private void UpdateFilterButtons(Border active)
    {
        foreach (var btn in new[] { FilterToday, Filter7d, Filter30d, FilterAll })
        {
            var isActive = btn == active;
            btn.Background = isActive
                ? new SolidColorBrush(Color.FromRgb(0x4B, 0x5E, 0xFC))
                : TryFindResource("ItemBackground") as Brush
                  ?? new SolidColorBrush(Color.FromRgb(0x30, 0x30, 0x45));
            if (btn.Child is TextBlock tb)
            {
                tb.Foreground = isActive
                    ? Brushes.White
                    : TryFindResource("SecondaryText") as Brush ?? Brushes.Gray;
            }
        }
    }

    private void UpdateStatus(AgentStatsService.AgentStatsSummary s, int days)
    {
        var period = days switch
        {
            1  => "오늘",
            7  => "최근 7일",
            30 => "최근 30일",
            _  => "전체 기간",
        };
        var fileSize = AgentStatsService.GetFileSize();
        StatusText.Text =
            $"{period} 기준 | 세션 {s.TotalSessions}회, 도구 호출 {s.TotalToolCalls}회, " +
            $"토큰 {FormatTokens(s.TotalTokens)} | 저장 파일 {FormatFileSize(fileSize)}";
    }

    private static string FormatTokens(int t) =>
        t >= 1_000_000 ? $"{t / 1_000_000.0:F1}M"
        : t >= 1_000 ? $"{t / 1_000.0:F1}K"
        : t.ToString();

    private static string FormatFileSize(long bytes) =>
        bytes >= 1024 * 1024 ? $"{bytes / (1024.0 * 1024):F1}MB"
        : bytes >= 1024 ? $"{bytes / 1024.0:F1}KB"
        : $"{bytes}B";
}
