using System.Windows;
using System.Windows.Documents;
using System.Windows.Media;
using Markdig;
using Markdig.Wpf;

namespace PSLauncher.App.Views;

/// <summary>
/// Helper pour rendre un FlowDocument à partir de Markdown avec le thème sombre du launcher.
/// Markdig.Wpf produit un FlowDocument dont le Background est blanc et le Foreground noir
/// par défaut — on force ici les couleurs sur le document et tous ses éléments visuels.
/// </summary>
internal static class MarkdownTheming
{
    public static FlowDocument BuildThemedDocument(string markdown)
    {
        var pipeline = new MarkdownPipelineBuilder().UseSupportedExtensions().Build();
        FlowDocument doc;
        try
        {
            doc = Markdig.Wpf.Markdown.ToFlowDocument(markdown, pipeline);
        }
        catch
        {
            doc = new FlowDocument(new Paragraph(new Run(markdown)));
        }
        ApplyDarkTheme(doc);
        return doc;
    }

    public static void ApplyDarkTheme(FlowDocument doc)
    {
        var bg = (Brush)Application.Current.FindResource("Brush.Bg.Card");
        var fg = (Brush)Application.Current.FindResource("Brush.Text.Primary");
        var fgSecondary = (Brush)Application.Current.FindResource("Brush.Text.Secondary");
        var border = (Brush)Application.Current.FindResource("Brush.Border");
        var accent = (Brush)Application.Current.FindResource("Brush.Accent");

        doc.Background = Brushes.Transparent;
        doc.Foreground = fg;
        doc.FontFamily = new FontFamily("Segoe UI");
        doc.FontSize = 13;
        doc.LineHeight = 20;
        doc.PagePadding = new Thickness(0);

        foreach (var block in doc.Blocks.ToList())
            ApplyToBlock(block, fg, fgSecondary, border, accent, bg);
    }

    private static void ApplyToBlock(Block block, Brush fg, Brush fgSecondary, Brush border, Brush accent, Brush bg)
    {
        block.Foreground = fg;
        block.Background = Brushes.Transparent;

        switch (block)
        {
            case Paragraph p:
                foreach (var inline in p.Inlines.ToList())
                    ApplyToInline(inline, fg, fgSecondary, accent);
                break;

            case Section s:
                foreach (var b in s.Blocks.ToList())
                    ApplyToBlock(b, fg, fgSecondary, border, accent, bg);
                break;

            case List list:
                foreach (var item in list.ListItems.ToList())
                {
                    item.Foreground = fg;
                    foreach (var b in item.Blocks.ToList())
                        ApplyToBlock(b, fg, fgSecondary, border, accent, bg);
                }
                break;

            case Table tbl:
                foreach (var rg in tbl.RowGroups.ToList())
                    foreach (var row in rg.Rows.ToList())
                        foreach (var cell in row.Cells.ToList())
                        {
                            cell.Foreground = fg;
                            cell.BorderBrush = border;
                            foreach (var b in cell.Blocks.ToList())
                                ApplyToBlock(b, fg, fgSecondary, border, accent, bg);
                        }
                break;

            case BlockUIContainer:
                // Contenu UI custom — laissé tel quel.
                break;
        }
    }

    private static void ApplyToInline(Inline inline, Brush fg, Brush fgSecondary, Brush accent)
    {
        inline.Foreground = fg;
        switch (inline)
        {
            case Hyperlink h:
                h.Foreground = accent;
                foreach (var i in h.Inlines.ToList())
                    ApplyToInline(i, accent, fgSecondary, accent);
                break;

            case Run r:
                // Markdig.Wpf rend `inline code` en tant que <Run> avec un Style
                // par défaut qui pose un Background clair + Foreground "fancy" — illisible
                // sur notre thème sombre. On détecte le code inline par sa FontFamily
                // (monospace appliquée par le style Markdig) et on rebadge avec des couleurs
                // qui matchent le reste de la UI : fond noir foncé + texte primaire.
                var fontFamilyName = r.FontFamily?.Source ?? string.Empty;
                if (fontFamilyName.Contains("Consolas", StringComparison.OrdinalIgnoreCase)
                    || fontFamilyName.Contains("Courier", StringComparison.OrdinalIgnoreCase)
                    || fontFamilyName.Contains("Typewriter", StringComparison.OrdinalIgnoreCase))
                {
                    r.Background = new SolidColorBrush(Color.FromRgb(0x1A, 0x1F, 0x2A));
                    r.Foreground = new SolidColorBrush(Color.FromRgb(0xCD, 0xD6, 0xE4));
                    r.FontFamily = new FontFamily("Cascadia Code, Consolas, monospace");
                }
                break;

            case Span s:
                foreach (var i in s.Inlines.ToList())
                    ApplyToInline(i, fg, fgSecondary, accent);
                break;
        }
    }
}
