using Markdig;
using Markdig.Extensions.AutoLinks;
using Markdig.Extensions.Yaml;
using Markdig.Renderers;
using Markdig.Syntax;
using Microsoft.AspNetCore.Components;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;

namespace PancakesWeb.Components.UI;

public partial class BlogPosts : ComponentBase
{
    public static List<Post> Posts = new();

    static BlogPosts()
    {
        foreach (var file in Directory.EnumerateFiles("BlogPosts"))
        {
            if (file.EndsWith(".md"))
            {
                Posts.Add(new Post(Path.GetFileNameWithoutExtension(file)));
            }
        }

        Posts = Posts.OrderByDescending(p => p.Published).ToList();
    }

    public class Post
    {
        public readonly string Slug;
        public string Content = null!;

        public string Title = null!;
        public string Description = null!;
        public DateTime Published = DateTime.Today;
        public DateTime? Edited;
        public PostFooter? Footer;
        public string? HeaderFilename;
        public string? HeaderAlt;
        public string? HeaderCaption;

        public Post(string slug)
        {
            Slug = slug;
            UpdatePost();
        }

        public void UpdatePost()
        {
            var text = File.ReadAllText($"BlogPosts/{Slug}.md");
            var (metadata, html) = ParseMarkdown(text);

            Content = html;
            Title = metadata.Title;
            Description = metadata.Description;
            Published = metadata.Published;
            Edited = metadata.Edited;
            Footer = metadata.Footer;
            HeaderFilename = metadata.Header;
            HeaderAlt = metadata.HeaderAlt;
            HeaderCaption = metadata.HeaderCaption;
        }

        private static (PostMetadata metadata, string html) ParseMarkdown(string markdown)
        {
            var pipeline = new MarkdownPipelineBuilder().UseAbbreviations().UseAlertBlocks().UseAutoIdentifiers()
                .UseAutoLinks(new AutoLinkOptions { OpenInNewWindow = true }).UseEmphasisExtras().UseFootnotes()
                .UseGenericAttributes().UseMediaLinks().UsePipeTables().UseSmartyPants().UseTaskLists()
                .UseYamlFrontMatter().Build();
            var writer = new StringWriter();
            var renderer = new HtmlRenderer(writer);
            pipeline.Setup(renderer);

            var document = Markdown.Parse(markdown, pipeline);

            var yaml = "";
            var frontMatter = document.Descendants<YamlFrontMatterBlock>().FirstOrDefault();
            if (frontMatter != null)
                yaml = markdown.Substring(frontMatter.Span.Start + 4, frontMatter.Span.Length - 8);

            renderer.Render(document);
            writer.Flush();

            var deserializer = new DeserializerBuilder().WithNamingConvention(UnderscoredNamingConvention.Instance)
                .WithEnumNamingConvention(UnderscoredNamingConvention.Instance).Build();
            var metadata = deserializer.Deserialize<PostMetadata>(yaml);

            return (metadata, writer.ToString());
        }
    }

    private class PostMetadata
    {
        public string Title { get; set; } = null!;
        public string Description { get; set; } = null!;
        public string? Header { get; set; }
        public string? HeaderAlt { get; set; }
        public string? HeaderCaption { get; set; }
        public PostFooter? Footer { get; set; }
        public DateTime Published { get; set; }
        public DateTime? Edited { get; set; }
    }

    public enum PostFooter
    {
        CcBy
    }
}