using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;
using AxCopilot.Views;

namespace AxCopilot.Services;

/// <summary>
/// 간이 마크다운 → WPF UIElement 변환기.
/// 지원: **볼드**, *이탤릭*, `인라인코드`, ```코드블록```, ### 헤더, - 리스트, --- 구분선
/// </summary>
public static partial class MarkdownRenderer
{
    public static StackPanel Render(string markdown, Brush textColor, Brush secondaryColor, Brush accentColor, Brush codeBg)
    {
        var panel = new StackPanel();
        if (string.IsNullOrEmpty(markdown))
            return panel;

        var lines = markdown.Replace("\r\n", "\n").Split('\n');
        var i = 0;

        while (i < lines.Length)
        {
            var line = lines[i];

            // 코드 블록 ```
            if (line.TrimStart().StartsWith("```"))
            {
                var lang = line.TrimStart().Length > 3 ? line.TrimStart()[3..].Trim() : "";
                var codeLines = new System.Text.StringBuilder();
                i++;
                while (i < lines.Length && !lines[i].TrimStart().StartsWith("```"))
                {
                    codeLines.AppendLine(lines[i]);
                    i++;
                }
                if (i < lines.Length) i++; // skip closing ```

                var codeBlock = CreateCodeBlock(codeLines.ToString().TrimEnd(), lang, textColor, codeBg, accentColor);
                panel.Children.Add(codeBlock);
                continue;
            }

            // 빈 줄
            if (string.IsNullOrWhiteSpace(line))
            {
                panel.Children.Add(new Border { Height = 6 });
                i++;
                continue;
            }

            // 구분선 ---
            if (Regex.IsMatch(line.Trim(), @"^-{3,}$|^\*{3,}$"))
            {
                panel.Children.Add(new Border
                {
                    Height = 1,
                    Background = secondaryColor,
                    Opacity = 0.3,
                    Margin = new Thickness(0, 8, 0, 8)
                });
                i++;
                continue;
            }

            // 헤더 ###
            if (line.StartsWith('#'))
            {
                var level = 0;
                while (level < line.Length && line[level] == '#') level++;
                var headerText = line[level..].Trim();
                var fontSize = level switch { 1 => 20.0, 2 => 17.0, 3 => 15.0, _ => 14.0 };

                var tb = new TextBlock
                {
                    FontSize = fontSize,
                    FontWeight = FontWeights.Bold,
                    Foreground = textColor,
                    TextWrapping = TextWrapping.Wrap,
                    Margin = new Thickness(0, level == 1 ? 12 : 8, 0, 4)
                };
                AddInlines(tb.Inlines, headerText, textColor, accentColor, codeBg);
                panel.Children.Add(tb);
                i++;
                continue;
            }

            // 리스트 항목 - 또는 * 또는 숫자.
            if (Regex.IsMatch(line, @"^\s*[-*]\s") || Regex.IsMatch(line, @"^\s*\d+\.\s"))
            {
                var match = Regex.Match(line, @"^(\s*)([-*]|\d+\.)\s(.*)");
                if (match.Success)
                {
                    var indent = match.Groups[1].Value.Length / 2;
                    var bullet = match.Groups[2].Value;
                    var content = match.Groups[3].Value;

                    var bulletChar = bullet is "-" or "*" ? "•" : bullet;
                    var grid = new Grid
                    {
                        Margin = new Thickness(12 + indent * 16, 2, 0, 2)
                    };
                    grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(18) });
                    grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });

                    var bulletTb = new TextBlock
                    {
                        Text = bulletChar,
                        FontSize = 13.5,
                        Foreground = accentColor,
                        VerticalAlignment = VerticalAlignment.Top
                    };
                    Grid.SetColumn(bulletTb, 0);
                    grid.Children.Add(bulletTb);

                    var tb = new TextBlock
                    {
                        FontSize = 13.5,
                        Foreground = textColor,
                        TextWrapping = TextWrapping.Wrap,
                        VerticalAlignment = VerticalAlignment.Top
                    };
                    Grid.SetColumn(tb, 1);
                    AddInlines(tb.Inlines, content, textColor, accentColor, codeBg);
                    grid.Children.Add(tb);
                    panel.Children.Add(grid);
                }
                i++;
                continue;
            }

            // 인용 블록 >
            if (line.TrimStart().StartsWith('>'))
            {
                var quoteLines = new List<string>();
                while (i < lines.Length && lines[i].TrimStart().StartsWith('>'))
                {
                    var ql = lines[i].TrimStart();
                    quoteLines.Add(ql.Length > 1 ? ql[1..].TrimStart() : "");
                    i++;
                }
                var quoteBorder = new Border
                {
                    BorderBrush = accentColor,
                    BorderThickness = new Thickness(3, 0, 0, 0),
                    Padding = new Thickness(12, 6, 8, 6),
                    Margin = new Thickness(4, 4, 0, 4),
                    Background = new SolidColorBrush(Color.FromArgb(0x10, 0xFF, 0xFF, 0xFF)),
                };
                var quoteTb = new TextBlock
                {
                    FontSize = 13,
                    FontStyle = FontStyles.Italic,
                    Foreground = secondaryColor,
                    TextWrapping = TextWrapping.Wrap,
                    LineHeight = 20,
                };
                AddInlines(quoteTb.Inlines, string.Join("\n", quoteLines), textColor, accentColor, codeBg);
                quoteBorder.Child = quoteTb;
                panel.Children.Add(quoteBorder);
                continue;
            }

            // 테이블 | col1 | col2 |
            if (line.Contains('|') && line.Trim().StartsWith('|'))
            {
                var tableRows = new List<string>();
                while (i < lines.Length && lines[i].Contains('|'))
                {
                    tableRows.Add(lines[i]);
                    i++;
                }
                var table = CreateMarkdownTable(tableRows, textColor, accentColor, codeBg);
                if (table != null) panel.Children.Add(table);
                continue;
            }

            // 일반 텍스트 단락
            var para = new TextBlock
            {
                FontSize = 13.5,
                Foreground = textColor,
                TextWrapping = TextWrapping.Wrap,
                LineHeight = 22,
                Margin = new Thickness(0, 2, 0, 2)
            };
            AddInlines(para.Inlines, line, textColor, accentColor, codeBg);
            panel.Children.Add(para);
            i++;
        }

        return panel;
    }

    /// <summary>인라인 마크다운 처리: **볼드**, *이탤릭*, `코드`, ~~취소선~~, [링크](url)</summary>
    private static void AddInlines(InlineCollection inlines, string text, Brush textColor, Brush accentColor, Brush codeBg)
    {
        // 패턴: [link](url) | ~~strikethrough~~ | **bold** | *italic* | `code` | 일반텍스트
        var pattern = @"(\[([^\]]+)\]\(([^)]+)\)|~~(.+?)~~|\*\*(.+?)\*\*|\*(.+?)\*|`(.+?)`|([^*`~\[]+))";
        var matches = Regex.Matches(text, pattern);

        foreach (Match m in matches)
        {
            if (m.Groups[2].Success && m.Groups[3].Success) // [link](url)
            {
                var linkUrl = m.Groups[3].Value;
                var hl = new Hyperlink(new Run(m.Groups[2].Value))
                {
                    Foreground = accentColor,
                    TextDecorations = null,
                    Cursor = System.Windows.Input.Cursors.Hand,
                };
                hl.Click += (_, _) =>
                {
                    try { System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo(linkUrl) { UseShellExecute = true }); } catch (Exception) { }
                };
                inlines.Add(hl);
            }
            else if (m.Groups[4].Success) // ~~strikethrough~~
            {
                inlines.Add(new Run(m.Groups[4].Value)
                {
                    TextDecorations = TextDecorations.Strikethrough,
                    Foreground = new SolidColorBrush(Color.FromArgb(0x99, 0xFF, 0xFF, 0xFF)),
                });
            }
            else if (m.Groups[5].Success) // **bold**
            {
                inlines.Add(new Run(m.Groups[5].Value) { FontWeight = FontWeights.Bold });
            }
            else if (m.Groups[6].Success) // *italic*
            {
                inlines.Add(new Run(m.Groups[6].Value) { FontStyle = FontStyles.Italic });
            }
            else if (m.Groups[7].Success) // `code`
            {
                var codeBorder = new Border
                {
                    Background = codeBg,
                    CornerRadius = new CornerRadius(4),
                    Padding = new Thickness(5, 1, 5, 1),
                    Margin = new Thickness(1, 0, 1, 0),
                    Child = new TextBlock
                    {
                        Text = m.Groups[7].Value,
                        FontFamily = ThemeResourceHelper.CascadiaCode,
                        FontSize = 12.5,
                        Foreground = accentColor
                    }
                };
                inlines.Add(new InlineUIContainer(codeBorder) { BaselineAlignment = BaselineAlignment.Center });
            }
            else if (m.Groups[8].Success) // 일반 텍스트
            {
                AddPlainTextWithFilePaths(inlines, m.Groups[8].Value);
            }
        }
    }

    /// <summary>파일 경로 패턴을 파란색 강조하여 추가하는 정적 Regex.</summary>
    private static readonly Regex FilePathPattern = new(
        @"(?<![""'=/>])(" +
        @"[A-Za-z]:\\[^\s<>""',;)]+|" +                               // 절대 경로: C:\folder\file.ext
        @"\.{1,2}/[\w\-./]+(?:\.[a-zA-Z]{1,10})?|" +                  // 상대 경로: ./src/file.cs
        @"[\w\-]+(?:/[\w\-\.]+){1,}(?:\.[a-zA-Z]{1,10})?|" +          // 폴더/파일: src/utils/helper.cs
        @"[\w\-]+\.(?:cs|py|js|ts|tsx|jsx|json|xml|html|htm|css|md|txt|yml|yaml|toml|sh|bat|ps1|csproj|sln|docx|xlsx|pptx|pdf|csv|enc|skill))" +
        @"(?=[,\s;)""'<]|$)",
        RegexOptions.Compiled);

    /// <summary>파일 경로 활성 여부 (설정 연동).</summary>
    public static bool EnableFilePathHighlight { get; set; } = true;

    /// <summary>일반 텍스트에서 파일 경로 패턴을 감지하여 파란색으로 강조합니다.</summary>
    private static void AddPlainTextWithFilePaths(InlineCollection inlines, string text)
    {
        if (!EnableFilePathHighlight)
        {
            inlines.Add(new Run(text));
            return;
        }

        var matches = FilePathPattern.Matches(text);
        if (matches.Count == 0)
        {
            inlines.Add(new Run(text));
            return;
        }

        var lastIndex = 0;
        foreach (Match pm in matches)
        {
            // 매치 전 텍스트
            if (pm.Index > lastIndex)
                inlines.Add(new Run(text[lastIndex..pm.Index]));

            // 파일 경로 — 파란색 강조
            inlines.Add(new Run(pm.Value)
            {
                Foreground = new SolidColorBrush(Color.FromRgb(0x3B, 0x82, 0xF6)), // #3B82F6
                FontWeight = FontWeights.Medium,
            });
            lastIndex = pm.Index + pm.Length;
        }

        // 남은 텍스트
        if (lastIndex < text.Length)
            inlines.Add(new Run(text[lastIndex..]));
    }

    /// <summary>마크다운 테이블을 Grid로 렌더링합니다.</summary>
    private static FrameworkElement? CreateMarkdownTable(List<string> rows, Brush textColor, Brush accentColor, Brush codeBg)
    {
        if (rows.Count < 2) return null;

        // 셀 파싱
        static string[] ParseRow(string row)
        {
            var trimmed = row.Trim().Trim('|');
            return trimmed.Split('|').Select(c => c.Trim()).ToArray();
        }

        var headers = ParseRow(rows[0]);
        var colCount = headers.Length;
        if (colCount == 0) return null;

        // 구분선 행(---|---) 건너뛰기
        var dataStart = 1;
        if (rows.Count > 1 && Regex.IsMatch(rows[1].Trim(), @"^[\|\s:\-]+$"))
            dataStart = 2;

        var grid = new Grid { Margin = new Thickness(0, 6, 0, 6) };
        for (int c = 0; c < colCount; c++)
            grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });

        var rowIndex = 0;

        // 헤더 행
        grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
        for (int c = 0; c < colCount; c++)
        {
            var cell = new Border
            {
                Background = new SolidColorBrush(Color.FromArgb(0x20, 0xFF, 0xFF, 0xFF)),
                BorderBrush = new SolidColorBrush(Color.FromArgb(0x30, 0xFF, 0xFF, 0xFF)),
                BorderThickness = new Thickness(0, 0, c < colCount - 1 ? 1 : 0, 1),
                Padding = new Thickness(8, 5, 8, 5),
            };
            var tb = new TextBlock
            {
                Text = c < headers.Length ? headers[c] : "",
                FontSize = 12, FontWeight = FontWeights.SemiBold,
                Foreground = textColor, TextWrapping = TextWrapping.Wrap,
            };
            cell.Child = tb;
            Grid.SetRow(cell, rowIndex);
            Grid.SetColumn(cell, c);
            grid.Children.Add(cell);
        }
        rowIndex++;

        // 데이터 행
        for (int r = dataStart; r < rows.Count; r++)
        {
            var cols = ParseRow(rows[r]);
            grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
            for (int c = 0; c < colCount; c++)
            {
                var cell = new Border
                {
                    Background = r % 2 == 0
                        ? new SolidColorBrush(Color.FromArgb(0x08, 0xFF, 0xFF, 0xFF))
                        : Brushes.Transparent,
                    BorderBrush = new SolidColorBrush(Color.FromArgb(0x18, 0xFF, 0xFF, 0xFF)),
                    BorderThickness = new Thickness(0, 0, c < colCount - 1 ? 1 : 0, 1),
                    Padding = new Thickness(8, 4, 8, 4),
                };
                var tb = new TextBlock
                {
                    FontSize = 12, Foreground = textColor, TextWrapping = TextWrapping.Wrap,
                };
                AddInlines(tb.Inlines, c < cols.Length ? cols[c] : "", textColor, accentColor, codeBg);
                cell.Child = tb;
                Grid.SetRow(cell, rowIndex);
                Grid.SetColumn(cell, c);
                grid.Children.Add(cell);
            }
            rowIndex++;
        }

        var wrapper = new Border
        {
            CornerRadius = new CornerRadius(6),
            BorderBrush = new SolidColorBrush(Color.FromArgb(0x30, 0xFF, 0xFF, 0xFF)),
            BorderThickness = new Thickness(1),
            ClipToBounds = true,
            Margin = new Thickness(0, 4, 0, 4),
        };
        wrapper.Child = grid;
        return wrapper;
    }

}
