using Dalamud.Bindings.ImGui;
using Dalamud.Interface.Utility;
using Dalamud.Interface.Utility.Raii;
using Dalamud.Utility;
using LightlessSync.LightlessConfiguration;
using LightlessSync.Services;
using LightlessSync.Services.Mediator;
using Microsoft.Extensions.Logging;
using System.Numerics;
using System.Reflection;
using System.Text;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;
using Dalamud.Interface;
using LightlessSync.UI.Models;
using LightlessSync.UI.Style;
using LightlessSync.Utils;

namespace LightlessSync.UI;

// Inspiration taken from Brio and Character Select+ (goats)
public class UpdateNotesUi : WindowMediatorSubscriberBase
{
    private readonly UiSharedService _uiShared;
    private readonly LightlessConfigService _configService;

    private ChangelogFile _changelog = new();
    private CreditsFile _credits = new();
    private bool _scrollToTop;
    private bool _hasInitializedCollapsingHeaders;
    private readonly AnimatedHeader _animatedHeader = new();

    public UpdateNotesUi(ILogger<UpdateNotesUi> logger,
        LightlessMediator mediator,
        UiSharedService uiShared,
        LightlessConfigService configService,
        PerformanceCollectorService performanceCollectorService)
        : base(logger, mediator, "Lightless Sync — Update Notes", performanceCollectorService)
    {
        logger.LogInformation("UpdateNotesUi constructor called");
        _uiShared = uiShared;
        _configService = configService;

        RespectCloseHotkey = true;
        ShowCloseButton = true;

        Flags = ImGuiWindowFlags.NoSavedSettings | ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoCollapse |
                ImGuiWindowFlags.NoTitleBar | ImGuiWindowFlags.NoMove;

        PositionCondition = ImGuiCond.Always;

        WindowBuilder.For(this)
            .AllowPinning(false)
            .AllowClickthrough(false)
            .SetFixedSize(new Vector2(800, 700))
            .Apply();

        LoadEmbeddedResources();
        logger.LogInformation("UpdateNotesUi constructor completed successfully");
    }

    public override void OnOpen()
    {
        _scrollToTop = true;
        _hasInitializedCollapsingHeaders = false;
    }

    public override void OnClose()
    {
        _animatedHeader.ClearParticles();
    }

    private void CenterWindow()
    {
        var viewport = ImGui.GetMainViewport();
        var center = viewport.GetCenter();
        var windowSize = new Vector2(800f * ImGuiHelpers.GlobalScale, 700f * ImGuiHelpers.GlobalScale);
        Position = center - windowSize / 2f;
    }

    protected override void DrawInternal()
    {
        if (_uiShared.IsInGpose)
            return;

        CenterWindow();
        DrawHeader();
        ImGuiHelpers.ScaledDummy(6);
        DrawTabs();
        DrawCloseButton();
    }

    private void DrawHeader()
    {
        var windowPadding = ImGui.GetStyle().WindowPadding;
        var headerWidth = (800f * ImGuiHelpers.GlobalScale) - (windowPadding.X * 2);

        var buttons = new List<HeaderButton>
        {
            new(FontAwesomeIcon.Comments, "Join our Discord", () => Util.OpenLink("https://discord.gg/dsbjcXMnhA")),
            new(FontAwesomeIcon.Code, "View on Git", () => Util.OpenLink("https://git.lightless-sync.org/Lightless-Sync"))
        };

        _animatedHeader.DrawWithButtons(headerWidth, "Lightless Sync", "Update Notes", buttons, _uiShared.UidFont);

        ImGui.SetCursorPosY(windowPadding.Y + _animatedHeader.Height + 5);
        ImGui.SetCursorPosX(20);
        using (ImRaii.PushFont(UiBuilder.IconFont))
        {
            ImGui.TextColored(UIColors.Get("LightlessGreen"), FontAwesomeIcon.Star.ToIconString());
        }

        ImGui.SameLine();

        ImGui.TextColored(UIColors.Get("LightlessGreen"), "What's New");

        if (!string.IsNullOrEmpty(_changelog.Tagline))
        {
            ImGui.SameLine();
            ImGui.SetCursorPosX(ImGui.GetCursorPosX() + 10);
            ImGui.TextColored(new Vector4(0.75f, 0.75f, 0.85f, 1.0f), _changelog.Tagline);

            if (!string.IsNullOrEmpty(_changelog.Subline))
            {
                ImGui.SameLine();
                ImGui.TextColored(new Vector4(0.65f, 0.65f, 0.75f, 1.0f), $" – {_changelog.Subline}");
            }
        }

        ImGuiHelpers.ScaledDummy(3);
    }

    private void DrawTabs()
    {
        using (ImRaii.PushStyle(ImGuiStyleVar.FrameRounding, 6f))
        using (ImRaii.PushColor(ImGuiCol.Tab, UIColors.Get("ButtonDefault")))
        using (ImRaii.PushColor(ImGuiCol.TabHovered, UIColors.Get("LightlessPurple")))
        using (ImRaii.PushColor(ImGuiCol.TabActive, UIColors.Get("LightlessPurpleActive")))
        {
            using (var tabBar = ImRaii.TabBar("###ll_tabs", ImGuiTabBarFlags.None))
            {
                if (!tabBar)
                    return;

                using (var changelogTab = ImRaii.TabItem("Changelog"))
                {
                    if (changelogTab)
                    {
                        DrawChangelog();
                    }
                }

                if (_credits.Credits != null && _credits.Credits.Count > 0)
                {
                    using (var creditsTab = ImRaii.TabItem("Credits"))
                    {
                        if (creditsTab)
                        {
                            DrawCredits();
                        }
                    }
                }
            }
        }
    }

    private void DrawCredits()
    {
        using (ImRaii.PushStyle(ImGuiStyleVar.ChildRounding, 6f))
        using (var child = ImRaii.Child("###ll_credits", new Vector2(0, ImGui.GetContentRegionAvail().Y - 60), false,
                   ImGuiWindowFlags.AlwaysVerticalScrollbar))
        {
            if (!child)
                return;

            ImGui.PushTextWrapPos();

            if (_credits.Credits != null)
            {
                foreach (var category in _credits.Credits)
                {
                    DrawCreditCategory(category);
                    ImGuiHelpers.ScaledDummy(10);
                }
            }

            ImGui.PopTextWrapPos();
            ImGui.Spacing();
        }
    }

    private static void DrawCreditCategory(CreditCategory category)
    {
        DrawFeatureSection(category.Category, UIColors.Get("LightlessBlue"));

        foreach (var item in category.Items)
        {
            ImGui.Bullet();
            ImGui.SameLine();
            if (!string.IsNullOrEmpty(item.Role))
            {
                ImGui.TextWrapped($"{item.Name} — {item.Role}");
            }
            else
            {
                ImGui.TextWrapped(item.Name);
            }
        }

        ImGuiHelpers.ScaledDummy(5);
    }

    private void DrawCloseButton()
    {
        ImGuiHelpers.ScaledDummy(5);

        var closeWidth = 200f * ImGuiHelpers.GlobalScale;
        var closeHeight = 35f * ImGuiHelpers.GlobalScale;
        ImGui.SetCursorPosX((ImGui.GetWindowSize().X - closeWidth) / 2);

        using (ImRaii.PushStyle(ImGuiStyleVar.FrameRounding, 8f))
        using (ImRaii.PushColor(ImGuiCol.Button, UIColors.Get("LightlessPurple")))
        using (ImRaii.PushColor(ImGuiCol.ButtonHovered, UIColors.Get("LightlessPurpleActive")))
        using (ImRaii.PushColor(ImGuiCol.ButtonActive, UIColors.Get("ButtonDefault")))
        {
            if (ImGui.Button("Got it!", new Vector2(closeWidth, closeHeight)))
            {
                // Update last seen version when user acknowledges the update notes
                var ver = Assembly.GetExecutingAssembly().GetName().Version;
                var currentVersion = ver == null ? string.Empty : $"{ver.Major}.{ver.Minor}.{ver.Build}";
                _configService.Current.LastSeenVersion = currentVersion;
                _configService.Save();
                
                IsOpen = false;
            }
            
            if (ImGui.IsItemHovered())
            {
                ImGui.SetTooltip("You can view this window again in the settings (title menu)");
            }
        }
    }

    private void DrawChangelog()
    {
        using (ImRaii.PushStyle(ImGuiStyleVar.ChildRounding, 6f))
        using (var child = ImRaii.Child("###ll_changelog", new Vector2(0, ImGui.GetContentRegionAvail().Y - 60), false,
                   ImGuiWindowFlags.AlwaysVerticalScrollbar))
        {
            if (!child)
                return;

            if (_scrollToTop)
            {
                _scrollToTop = false;
                ImGui.SetScrollHereY(0);
            }

            ImGui.PushTextWrapPos(ImGui.GetCursorPosX() + ImGui.GetContentRegionAvail().X);

            foreach (var entry in _changelog.Changelog)
            {
                DrawChangelogEntry(entry);
            }
            
            _hasInitializedCollapsingHeaders = true;

            ImGui.PopTextWrapPos();
            ImGui.Spacing();
        }
    }

    private void DrawChangelogEntry(ChangelogEntry entry)
    {
        var isCurrent = entry.IsCurrent ?? false;
        
        var currentColor = isCurrent
            ? UIColors.Get("LightlessGreen")
            : new Vector4(0.95f, 0.95f, 1.0f, 1.0f);
        
        var flags = isCurrent ? ImGuiTreeNodeFlags.DefaultOpen : ImGuiTreeNodeFlags.None;
        
        if (!_hasInitializedCollapsingHeaders)
        {
            ImGui.SetNextItemOpen(isCurrent, ImGuiCond.Always);
        }
        
        bool isOpen;
        using (ImRaii.PushStyle(ImGuiStyleVar.FrameRounding, 4f))
        using (ImRaii.PushColor(ImGuiCol.Header, UIColors.Get("ButtonDefault")))
        using (ImRaii.PushColor(ImGuiCol.Text, currentColor))
        {
            isOpen = ImGui.CollapsingHeader($" {entry.Name} — {entry.Date} ", flags);
            
            ImGui.SameLine();
            ImGui.TextColored(new Vector4(0.85f, 0.85f, 0.95f, 1.0f), $"  —  {entry.Tagline}");
        }
        
        if (!isOpen)
            return;

        ImGuiHelpers.ScaledDummy(8);

        if (!string.IsNullOrEmpty(entry.Message))
        {
            ImGui.TextWrapped(entry.Message);
            ImGuiHelpers.ScaledDummy(8);
            return;
        }

        if (entry.Versions != null)
        {
            foreach (var version in entry.Versions)
            {
                DrawFeatureSection(version.Number, UIColors.Get("LightlessGreen"));

                foreach (var item in version.Items)
                {
                    ImGui.Bullet();
                    ImGui.SameLine();
                    ImGui.TextWrapped(item);
                }

                ImGuiHelpers.ScaledDummy(5);
            }
        }
    }

    private static void DrawFeatureSection(string title, Vector4 accentColor)
    {
        var drawList = ImGui.GetWindowDrawList();
        var startPos = ImGui.GetCursorScreenPos();
        var availableWidth = ImGui.GetContentRegionAvail().X;

        var backgroundMin = startPos + new Vector2(-8, -4);
        var backgroundMax = startPos + new Vector2(availableWidth + 8, 28);

        var bgColor = new Vector4(0.12f, 0.12f, 0.15f, 0.7f);
        drawList.AddRectFilled(backgroundMin, backgroundMax, ImGui.GetColorU32(bgColor), 6f);

        drawList.AddRectFilled(
            backgroundMin,
            backgroundMin + new Vector2(4, backgroundMax.Y - backgroundMin.Y),
            ImGui.GetColorU32(accentColor),
            3f
        );

        var glowColor = accentColor with { W = 0.15f };
        drawList.AddRect(
            backgroundMin,
            backgroundMax,
            ImGui.GetColorU32(glowColor),
            6f,
            ImDrawFlags.None,
            1.5f
        );

        // Calculate vertical centering
        var textSize = ImGui.CalcTextSize(title);
        var boxHeight = backgroundMax.Y - backgroundMin.Y;
        var verticalOffset = (boxHeight - textSize.Y) / 5f;

        ImGui.SetCursorPosX(ImGui.GetCursorPosX() + 8);
        ImGui.SetCursorPosY(ImGui.GetCursorPosY() + verticalOffset);
        ImGui.TextColored(accentColor, title);
        ImGui.SetCursorPosY(backgroundMax.Y - startPos.Y + ImGui.GetCursorPosY());
    }

    private void LoadEmbeddedResources()
    {
        try
        {
            var assembly = Assembly.GetExecutingAssembly();
            var deserializer = new DeserializerBuilder()
                .WithNamingConvention(CamelCaseNamingConvention.Instance)
                .IgnoreUnmatchedProperties()
                .Build();

            // Load changelog
            using var changelogStream = assembly.GetManifestResourceStream("LightlessSync.Changelog.changelog.yaml");
            if (changelogStream != null)
            {
                using var reader = new StreamReader(changelogStream, Encoding.UTF8, detectEncodingFromByteOrderMarks: true, 128);
                var yaml = reader.ReadToEnd();
                _changelog = deserializer.Deserialize<ChangelogFile>(yaml) ?? new();
            }

            // Load credits
            using var creditsStream = assembly.GetManifestResourceStream("LightlessSync.Changelog.credits.yaml");
            if (creditsStream != null)
            {
                using var reader = new StreamReader(creditsStream, Encoding.UTF8, detectEncodingFromByteOrderMarks: true, 128);
                var yaml = reader.ReadToEnd();
                _credits = deserializer.Deserialize<CreditsFile>(yaml) ?? new();
            }
        }
        catch
        {
            // Ignore - window will gracefully render with defaults
        }
    }
}
