using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Myra.Graphics2D;
using Myra.Graphics2D.Brushes;
using Myra.Graphics2D.UI;
using Theriapolis.Core.Data;
using Theriapolis.Core.Rules.Quests;

namespace Theriapolis.Game.Screens;

/// <summary>
/// Phase 6 M4 — quest journal modal (J key). Two columns: active quests
/// on the left (current step + waypoint hint), completed/failed quests
/// on the right. A tail block shows the engine's recent journal entries.
///
/// Hidden quests stay hidden until they activate; once started, they
/// appear in the active list normally.
/// </summary>
public sealed class QuestLogScreen : IScreen
{
    private readonly QuestEngine     _engine;
    private readonly ContentResolver _content;
    private Game1   _game = null!;
    private Desktop _desktop = null!;
    private bool _jWasDown   = true;
    private bool _escWasDown = true;

    public QuestLogScreen(QuestEngine engine, ContentResolver content)
    {
        _engine  = engine  ?? throw new System.ArgumentNullException(nameof(engine));
        _content = content ?? throw new System.ArgumentNullException(nameof(content));
    }

    public void Initialize(Game1 game)
    {
        _game = game;
        BuildUI();
    }

    private void BuildUI()
    {
        var root = new VerticalStackPanel
        {
            Spacing             = 8,
            HorizontalAlignment = HorizontalAlignment.Center,
            VerticalAlignment   = VerticalAlignment.Top,
            Margin              = new Thickness(20),
            Padding             = new Thickness(20, 12, 20, 12),
            Background          = new SolidBrush(new Color(15, 12, 8, 235)),
            Width               = 880,
        };

        root.Widgets.Add(new Label
        {
            Text                = "QUEST JOURNAL",
            HorizontalAlignment = HorizontalAlignment.Center,
            TextColor           = new Color(255, 230, 170),
        });
        root.Widgets.Add(new Label { Text = " " });

        var twoCol = new HorizontalStackPanel { Spacing = 24 };

        // Active.
        var leftCol = new VerticalStackPanel { Spacing = 4, Width = 420 };
        leftCol.Widgets.Add(new Label { Text = "ACTIVE", TextColor = new Color(200, 180, 130) });
        var active = _engine.Active.Values.OrderBy(s => s.StartedAt).ToList();
        if (active.Count == 0)
            leftCol.Widgets.Add(new Label { Text = "(none yet)", TextColor = new Color(120, 110, 100) });
        foreach (var st in active)
        {
            var def = _content.Quests.TryGetValue(st.QuestId, out var d) ? d : null;
            string title = def?.Title ?? st.QuestId;
            leftCol.Widgets.Add(new Label
            {
                Text      = $"  {title}",
                TextColor = new Color(220, 220, 200),
            });
            // Step description if available.
            var step = def?.Steps.FirstOrDefault(x =>
                string.Equals(x.Id, st.CurrentStep, System.StringComparison.OrdinalIgnoreCase));
            if (step is not null && !string.IsNullOrEmpty(step.Description))
                leftCol.Widgets.Add(new Label
                {
                    Text      = $"     • {step.Description}",
                    TextColor = new Color(170, 200, 220),
                    Wrap      = true,
                    Width     = 410,
                });
            if (step is not null && !string.IsNullOrEmpty(step.Waypoint))
                leftCol.Widgets.Add(new Label
                {
                    Text      = $"     → {step.Waypoint}",
                    TextColor = new Color(140, 180, 110),
                });
        }
        twoCol.Widgets.Add(leftCol);

        // Completed / failed.
        var rightCol = new VerticalStackPanel { Spacing = 4, Width = 420 };
        rightCol.Widgets.Add(new Label { Text = "ARCHIVE", TextColor = new Color(200, 180, 130) });
        var done = _engine.Completed.Values.OrderByDescending(s => s.StartedAt).ToList();
        if (done.Count == 0)
            rightCol.Widgets.Add(new Label { Text = "(none yet)", TextColor = new Color(120, 110, 100) });
        foreach (var st in done)
        {
            var def = _content.Quests.TryGetValue(st.QuestId, out var d) ? d : null;
            string title = def?.Title ?? st.QuestId;
            string mark  = st.Status == QuestStatus.Completed ? "✓" : "✗";
            Color  color = st.Status == QuestStatus.Completed
                ? new Color(140, 200, 130)
                : new Color(200, 130, 130);
            rightCol.Widgets.Add(new Label
            {
                Text      = $"  {mark} {title}",
                TextColor = color,
            });
        }
        twoCol.Widgets.Add(rightCol);

        root.Widgets.Add(twoCol);

        // Recent journal tail.
        root.Widgets.Add(new Label { Text = " " });
        root.Widgets.Add(new Label { Text = "RECENT", TextColor = new Color(200, 180, 130) });
        var tail = _engine.Journal.Skip(System.Math.Max(0, _engine.Journal.Count - 8)).ToList();
        if (tail.Count == 0)
            root.Widgets.Add(new Label { Text = "  (no entries)", TextColor = new Color(120, 110, 100) });
        foreach (var line in tail)
            root.Widgets.Add(new Label
            {
                Text      = $"  {line}",
                TextColor = new Color(180, 180, 170),
                Wrap      = true,
                Width     = 840,
            });

        root.Widgets.Add(new Label { Text = " " });
        root.Widgets.Add(new Label
        {
            Text                = "(J / Esc to close)",
            HorizontalAlignment = HorizontalAlignment.Center,
            TextColor           = new Color(120, 110, 100),
        });

        _desktop = new Desktop { Root = root };
    }

    public void Update(GameTime gt)
    {
        var ks = Keyboard.GetState();
        bool j   = ks.IsKeyDown(Keys.J);
        bool esc = ks.IsKeyDown(Keys.Escape);
        bool jPressed   = j   && !_jWasDown;
        bool escPressed = esc && !_escWasDown;
        _jWasDown = j; _escWasDown = esc;
        if (jPressed || escPressed) _game.Screens.Pop();
    }

    public void Draw(GameTime gt, SpriteBatch sb) => _desktop.Render();
    public void Deactivate() { }
    public void Reactivate() { BuildUI(); }
}
