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

namespace AxCopilot.Views;

public partial class WorkflowAnalyzerWindow
{
    // ─── 병목 분석 차트 렌더링 ─────────────────────────────────────

    private void ClearBottleneckCharts()
    {
        WaterfallCanvas.Children.Clear();
        ToolTimePanel.Children.Clear();
        TokenTrendCanvas.Children.Clear();
    }

    private void RenderBottleneckCharts()
    {
        ClearBottleneckCharts();
        RenderWaterfallChart();
        RenderToolTimeChart();
        RenderTokenTrendChart();
    }

    /// <summary>워터폴 차트: LLM 호출과 도구 실행을 시간 순서로 표시. 병목 구간은 빨간색.</summary>
    private void RenderWaterfallChart()
    {
        if (_waterfallEntries.Count == 0)
        {
            WaterfallCanvas.Height = 40;
            var emptyMsg = new TextBlock
            {
                Text = "실행 데이터가 없습니다",
                FontSize = 11,
                Foreground = TryFindResource("SecondaryText") as Brush ?? Brushes.Gray,
            };
            Canvas.SetLeft(emptyMsg, 10);
            Canvas.SetTop(emptyMsg, 10);
            WaterfallCanvas.Children.Add(emptyMsg);
            return;
        }

        // 병목 판정: 평균 × 2.0 이상 = 빨강, × 1.5 이상 = 주황
        var avgDuration = _waterfallEntries.Average(e => e.DurationMs);
        var maxEndMs = _waterfallEntries.Max(e => e.StartMs + e.DurationMs);
        if (maxEndMs <= 0) maxEndMs = 1;

        var rowHeight = 22;
        var labelWidth = 90.0;
        var chartHeight = _waterfallEntries.Count * rowHeight + 10;
        WaterfallCanvas.Height = Math.Max(chartHeight, 60);

        var canvasWidth = WaterfallCanvas.ActualWidth > 0 ? WaterfallCanvas.ActualWidth : 480;
        var barAreaWidth = canvasWidth - labelWidth - 60; // 우측에 시간 텍스트 공간

        for (int i = 0; i < _waterfallEntries.Count; i++)
        {
            var entry = _waterfallEntries[i];
            var y = i * rowHeight + 4;

            // 색상 결정
            Color barColor;
            if (entry.DurationMs >= avgDuration * 2.0)
                barColor = Color.FromRgb(0xEF, 0x44, 0x44); // 빨강 (병목)
            else if (entry.DurationMs >= avgDuration * 1.5)
                barColor = Color.FromRgb(0xF9, 0x73, 0x16); // 주황 (주의)
            else if (entry.Type == "llm")
                barColor = Color.FromRgb(0x60, 0xA5, 0xFA); // 파랑 (LLM)
            else
                barColor = Color.FromRgb(0x34, 0xD3, 0x99); // 녹색 (도구)

            // 라벨
            var label = new TextBlock
            {
                Text = Truncate(entry.Label, 12),
                FontSize = 10,
                FontFamily = ThemeResourceHelper.Consolas,
                Foreground = new SolidColorBrush(barColor),
                Width = labelWidth,
                TextAlignment = TextAlignment.Right,
            };
            Canvas.SetLeft(label, 0);
            Canvas.SetTop(label, y + 2);
            WaterfallCanvas.Children.Add(label);

            // 바
            var barStart = (entry.StartMs / (double)maxEndMs) * barAreaWidth;
            var barWidth = Math.Max((entry.DurationMs / (double)maxEndMs) * barAreaWidth, 3);

            var bar = new Rectangle
            {
                Width = barWidth,
                Height = 14,
                RadiusX = 3, RadiusY = 3,
                Fill = new SolidColorBrush(barColor),
                Opacity = 0.85,
                ToolTip = $"{entry.Label}: {FormatMs(entry.DurationMs)}",
            };
            Canvas.SetLeft(bar, labelWidth + 8 + barStart);
            Canvas.SetTop(bar, y + 1);
            WaterfallCanvas.Children.Add(bar);

            // 시간 텍스트
            var timeText = new TextBlock
            {
                Text = FormatMs(entry.DurationMs),
                FontSize = 9,
                Foreground = new SolidColorBrush(barColor),
                FontFamily = ThemeResourceHelper.Consolas,
            };
            Canvas.SetLeft(timeText, labelWidth + 8 + barStart + barWidth + 4);
            Canvas.SetTop(timeText, y + 3);
            WaterfallCanvas.Children.Add(timeText);

            // 병목 아이콘
            if (entry.DurationMs >= avgDuration * 2.0)
            {
                var icon = new TextBlock
                {
                    Text = "🔴",
                    FontSize = 9,
                };
                Canvas.SetLeft(icon, labelWidth + 8 + barStart + barWidth + 44);
                Canvas.SetTop(icon, y + 2);
                WaterfallCanvas.Children.Add(icon);
            }
        }
    }

    /// <summary>도구별 누적 소요시간 수평 바 차트.</summary>
    private void RenderToolTimeChart()
    {
        ToolTimePanel.Children.Clear();

        if (_toolTimeAccum.Count == 0)
        {
            ToolTimePanel.Children.Add(new TextBlock
            {
                Text = "도구 실행 데이터가 없습니다",
                FontSize = 11,
                Foreground = TryFindResource("SecondaryText") as Brush ?? Brushes.Gray,
                Margin = new Thickness(0, 4, 0, 4),
            });
            return;
        }

        // LLM 시간 합산
        var llmTime = _waterfallEntries
            .Where(e => e.Type == "llm")
            .Sum(e => e.DurationMs);
        var allEntries = _toolTimeAccum
            .Select(kv => (Name: kv.Key, Ms: kv.Value))
            .ToList();
        if (llmTime > 0)
            allEntries.Add(("LLM 호출", llmTime));

        var sorted = allEntries.OrderByDescending(e => e.Ms).ToList();
        var maxMs = sorted.Max(e => e.Ms);
        if (maxMs <= 0) maxMs = 1;

        foreach (var (name, ms) in sorted)
        {
            var isBottleneck = ms == sorted[0].Ms;
            var barColor = name == "LLM 호출"
                ? Color.FromRgb(0x60, 0xA5, 0xFA)
                : isBottleneck
                    ? Color.FromRgb(0xEF, 0x44, 0x44)
                    : Color.FromRgb(0x34, 0xD3, 0x99);

            var row = new Grid { Margin = new Thickness(0, 2, 0, 2) };
            row.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(90) });
            row.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
            row.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(60) });

            // 도구명
            var nameText = new TextBlock
            {
                Text = Truncate(name, 12),
                FontSize = 11,
                FontFamily = ThemeResourceHelper.Consolas,
                Foreground = new SolidColorBrush(barColor),
                TextAlignment = TextAlignment.Right,
                VerticalAlignment = VerticalAlignment.Center,
                Margin = new Thickness(0, 0, 8, 0),
            };
            Grid.SetColumn(nameText, 0);

            // 바
            var barWidth = (ms / (double)maxMs);
            var barBorder = new Border
            {
                Background = new SolidColorBrush(barColor),
                CornerRadius = new CornerRadius(3),
                Height = 14,
                HorizontalAlignment = HorizontalAlignment.Left,
                Width = 0, // 나중에 SizeChanged에서 설정
                Opacity = 0.8,
            };
            var barContainer = new Border { Margin = new Thickness(0, 2, 0, 2) };
            barContainer.Child = barBorder;
            barContainer.SizeChanged += (_, _) =>
            {
                barBorder.Width = Math.Max(barContainer.ActualWidth * barWidth, 4);
            };
            Grid.SetColumn(barContainer, 1);

            // 시간
            var timeText = new TextBlock
            {
                Text = FormatMs(ms),
                FontSize = 10,
                Foreground = new SolidColorBrush(barColor),
                FontFamily = ThemeResourceHelper.Consolas,
                VerticalAlignment = VerticalAlignment.Center,
                Margin = new Thickness(4, 0, 0, 0),
            };
            Grid.SetColumn(timeText, 2);

            row.Children.Add(nameText);
            row.Children.Add(barContainer);
            row.Children.Add(timeText);
            ToolTimePanel.Children.Add(row);
        }
    }

    /// <summary>반복별 토큰 추세 꺾은선 그래프.</summary>
    private void RenderTokenTrendChart()
    {
        TokenTrendCanvas.Children.Clear();

        if (_tokenTrend.Count < 2)
        {
            TokenTrendCanvas.Height = 40;
            TokenTrendCanvas.Children.Add(new TextBlock
            {
                Text = _tokenTrend.Count == 0 ? "토큰 데이터가 없습니다" : "2회 이상 반복이 필요합니다",
                FontSize = 11,
                Foreground = TryFindResource("SecondaryText") as Brush ?? Brushes.Gray,
            });
            Canvas.SetLeft(TokenTrendCanvas.Children[0], 10);
            Canvas.SetTop(TokenTrendCanvas.Children[0], 10);
            return;
        }

        TokenTrendCanvas.Height = 100;
        var canvasWidth = TokenTrendCanvas.ActualWidth > 0 ? TokenTrendCanvas.ActualWidth : 480;
        var canvasHeight = 90.0;
        var marginLeft = 45.0;
        var marginRight = 10.0;
        var chartWidth = canvasWidth - marginLeft - marginRight;
        var sorted = _tokenTrend.OrderBy(t => t.Iteration).ToList();
        var maxToken = sorted.Max(t => Math.Max(t.Input, t.Output));
        if (maxToken <= 0) maxToken = 1;

        // Y축 눈금
        for (int i = 0; i <= 2; i++)
        {
            var y = canvasHeight * (1 - i / 2.0);
            var val = maxToken * i / 2;
            var gridLine = new Line
            {
                X1 = marginLeft, Y1 = y,
                X2 = canvasWidth - marginRight, Y2 = y,
                Stroke = TryFindResource("BorderColor") as Brush ?? Brushes.Gray,
                StrokeThickness = 0.5,
                Opacity = 0.4,
            };
            TokenTrendCanvas.Children.Add(gridLine);

            var yLabel = new TextBlock
            {
                Text = val >= 1000 ? $"{val / 1000.0:F0}k" : val.ToString(),
                FontSize = 9,
                Foreground = TryFindResource("SecondaryText") as Brush ?? Brushes.Gray,
                TextAlignment = TextAlignment.Right,
                Width = marginLeft - 6,
            };
            Canvas.SetLeft(yLabel, 0);
            Canvas.SetTop(yLabel, y - 6);
            TokenTrendCanvas.Children.Add(yLabel);
        }

        // 입력 토큰 선 (파랑)
        DrawPolyline(sorted.Select((t, i) => new Point(
            marginLeft + (i / (double)(sorted.Count - 1)) * chartWidth,
            canvasHeight * (1 - t.Input / (double)maxToken)
        )).ToList(), "#3B82F6");

        // 출력 토큰 선 (녹색)
        DrawPolyline(sorted.Select((t, i) => new Point(
            marginLeft + (i / (double)(sorted.Count - 1)) * chartWidth,
            canvasHeight * (1 - t.Output / (double)maxToken)
        )).ToList(), "#10B981");

        // X축 라벨
        foreach (var (iter, _, _) in sorted)
        {
            var idx = sorted.FindIndex(t => t.Iteration == iter);
            var x = marginLeft + (idx / (double)(sorted.Count - 1)) * chartWidth;
            var xLabel = new TextBlock
            {
                Text = $"#{iter}",
                FontSize = 9,
                Foreground = TryFindResource("SecondaryText") as Brush ?? Brushes.Gray,
            };
            Canvas.SetLeft(xLabel, x - 8);
            Canvas.SetTop(xLabel, canvasHeight + 2);
            TokenTrendCanvas.Children.Add(xLabel);
        }

        // 범례
        var legend = new StackPanel { Orientation = Orientation.Horizontal };
        legend.Children.Add(CreateLegendDot("#3B82F6", "입력"));
        legend.Children.Add(CreateLegendDot("#10B981", "출력"));
        Canvas.SetRight(legend, 10);
        Canvas.SetTop(legend, 0);
        TokenTrendCanvas.Children.Add(legend);

        // 컨텍스트 폭발 경고
        if (sorted.Count >= 3)
        {
            var inputValues = sorted.Select(t => t.Input).ToList();
            bool increasing = true;
            for (int i = 1; i < inputValues.Count; i++)
            {
                if (inputValues[i] <= inputValues[i - 1]) { increasing = false; break; }
            }
            if (increasing && inputValues[^1] > inputValues[0] * 2)
            {
                var warning = new TextBlock
                {
                    Text = "⚠ 컨텍스트 크기 급증",
                    FontSize = 10,
                    Foreground = new SolidColorBrush(Color.FromRgb(0xEF, 0x44, 0x44)),
                    FontWeight = FontWeights.SemiBold,
                };
                Canvas.SetLeft(warning, marginLeft + 4);
                Canvas.SetTop(warning, 0);
                TokenTrendCanvas.Children.Add(warning);
            }
        }
    }

    private void DrawPolyline(List<Point> points, string colorHex)
    {
        if (points.Count < 2) return;
        var color = (Color)ColorConverter.ConvertFromString(colorHex);

        var polyline = new Polyline
        {
            Stroke = new SolidColorBrush(color),
            StrokeThickness = 2,
            StrokeLineJoin = PenLineJoin.Round,
        };
        foreach (var p in points)
            polyline.Points.Add(p);
        TokenTrendCanvas.Children.Add(polyline);

        // 점 찍기
        foreach (var p in points)
        {
            var dot = new Ellipse
            {
                Width = 6, Height = 6,
                Fill = new SolidColorBrush(color),
            };
            Canvas.SetLeft(dot, p.X - 3);
            Canvas.SetTop(dot, p.Y - 3);
            TokenTrendCanvas.Children.Add(dot);
        }
    }

    private static StackPanel CreateLegendDot(string colorHex, string text)
    {
        var color = (Color)ColorConverter.ConvertFromString(colorHex);
        var sp = new StackPanel { Orientation = Orientation.Horizontal, Margin = new Thickness(8, 0, 0, 0) };
        sp.Children.Add(new Ellipse
        {
            Width = 6, Height = 6,
            Fill = new SolidColorBrush(color),
            VerticalAlignment = VerticalAlignment.Center,
            Margin = new Thickness(0, 0, 3, 0),
        });
        sp.Children.Add(new TextBlock
        {
            Text = text,
            FontSize = 9,
            Foreground = new SolidColorBrush(color),
            VerticalAlignment = VerticalAlignment.Center,
        });
        return sp;
    }
}
