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;
using Theriapolis.Game.Platform;

namespace Theriapolis.Game.Screens;

/// <summary>
/// Phase 5 M2 pause menu. Pushed by <see cref="PlayScreen"/> when the player
/// presses ESC during play. Provides Save Game (any slot, any time —
/// "save-anywhere" per the Phase 5 plan), Resume, and Quit to Title.
///
/// Cut-scene exclusion is forward-compat: Phase 5 has no cut scenes, so
/// save-anywhere is unconditional. When cut scenes arrive (Phase 6+), the
/// caller can suppress this push or grey out the Save Game button.
/// </summary>
public sealed class PauseMenuScreen : IScreen
{
    private readonly PlayScreen _playScreen;
    private Game1 _game = null!;
    private Desktop _desktop = null!;
    private Label? _statusLabel;
    private bool _showingSlots;
    // ESC was already down when PauseMenu was pushed (the same press that
    // opened it). Wait for release before treating ESC as "close the menu".
    private bool _escWasDown = true;

    public PauseMenuScreen(PlayScreen playScreen)
    {
        _playScreen = playScreen ?? throw new ArgumentNullException(nameof(playScreen));
    }

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

    private void BuildMain()
    {
        _showingSlots = false;
        var root = new VerticalStackPanel
        {
            Spacing             = 12,
            HorizontalAlignment = HorizontalAlignment.Center,
            VerticalAlignment   = VerticalAlignment.Center,
            Background          = new SolidBrush(new Color(0, 0, 0, 200)),
            Padding             = new Thickness(40, 30, 40, 30),
        };

        root.Widgets.Add(new Label { Text = "PAUSED", HorizontalAlignment = HorizontalAlignment.Center });
        root.Widgets.Add(new Label { Text = " " });

        var resume = new TextButton { Text = "Resume",      Width = 220, HorizontalAlignment = HorizontalAlignment.Center };
        resume.Click += (_, _) => _game.Screens.Pop();
        root.Widgets.Add(resume);

        // Phase 6.5 M0 — surface the level-up affordance when eligible.
        var pcChar = _playScreen.PlayerCharacter();
        if (pcChar is not null && Theriapolis.Core.Rules.Character.LevelUpFlow.CanLevelUp(pcChar))
        {
            var lvlBtn = new TextButton
            {
                Text  = $"★ Level Up ({pcChar.Level} → {pcChar.Level + 1})",
                Width = 220,
                HorizontalAlignment = HorizontalAlignment.Center,
            };
            lvlBtn.Click += (_, _) =>
            {
                _game.Screens.Pop();
                _game.Screens.Push(new LevelUpScreen(
                    pcChar,
                    _playScreen.WorldSeed(),
                    subclasses: _playScreen.ContentResolver?.Subclasses));
            };
            root.Widgets.Add(lvlBtn);
        }

        var saveBtn = new TextButton { Text = "Save Game",  Width = 220, HorizontalAlignment = HorizontalAlignment.Center };
        saveBtn.Click += (_, _) => BuildSlotPicker();
        root.Widgets.Add(saveBtn);

        var quickSave = new TextButton { Text = "Quicksave (autosave slot)", Width = 220, HorizontalAlignment = HorizontalAlignment.Center };
        quickSave.Click += (_, _) =>
        {
            bool ok = _playScreen.SaveTo(SavePaths.AutosavePath());
            ShowStatus(ok ? "Quicksaved." : "Quicksave failed.");
        };
        root.Widgets.Add(quickSave);

        var quit = new TextButton { Text = "Quit to Title", Width = 220, HorizontalAlignment = HorizontalAlignment.Center };
        quit.Click += (_, _) =>
        {
            // Autosave on quit-to-title (matches existing Phase 4 behaviour).
            _playScreen.SaveTo(SavePaths.AutosavePath());
            // Pop the pause menu, then pop the play screen.
            _game.Screens.Pop();
            _game.Screens.Pop();
        };
        root.Widgets.Add(quit);

        _statusLabel = new Label { Text = " ", HorizontalAlignment = HorizontalAlignment.Center };
        root.Widgets.Add(_statusLabel);

        _desktop = new Desktop { Root = root };
    }

    private void BuildSlotPicker()
    {
        _showingSlots = true;
        var root = new VerticalStackPanel
        {
            Spacing             = 6,
            HorizontalAlignment = HorizontalAlignment.Center,
            VerticalAlignment   = VerticalAlignment.Center,
            Background          = new SolidBrush(new Color(0, 0, 0, 200)),
            Padding             = new Thickness(40, 20, 40, 20),
        };
        root.Widgets.Add(new Label { Text = "Save to slot:", HorizontalAlignment = HorizontalAlignment.Center });
        root.Widgets.Add(new Label { Text = " " });

        for (int i = 1; i <= C.SAVE_SLOT_COUNT; i++)
        {
            int slotNum = i;  // capture
            string path = SavePaths.SlotPath(slotNum);
            string label = $"Slot {slotNum:D2}";
            if (File.Exists(path))
            {
                try
                {
                    var bytes = File.ReadAllBytes(path);
                    var header = Theriapolis.Core.Persistence.SaveCodec.DeserializeHeaderOnly(bytes);
                    label += " — " + header.SlotLabel();
                }
                catch { label += " — <unreadable>"; }
            }
            else { label += " — <empty>"; }

            var btn = new TextButton { Text = label, Width = 480, HorizontalAlignment = HorizontalAlignment.Center };
            btn.Click += (_, _) =>
            {
                bool ok = _playScreen.SaveTo(path);
                if (ok)
                {
                    ShowStatus($"Saved to slot {slotNum:D2}.");
                    BuildMain();
                }
                else ShowStatus("Save failed.");
            };
            root.Widgets.Add(btn);
        }

        root.Widgets.Add(new Label { Text = " " });
        var back = new TextButton { Text = "Back", Width = 220, HorizontalAlignment = HorizontalAlignment.Center };
        back.Click += (_, _) => BuildMain();
        root.Widgets.Add(back);

        _statusLabel = new Label { Text = " ", HorizontalAlignment = HorizontalAlignment.Center };
        root.Widgets.Add(_statusLabel);

        _desktop.Root = root;
    }

    private void ShowStatus(string text)
    {
        if (_statusLabel is not null) _statusLabel.Text = text;
    }

    public void Update(GameTime gt)
    {
        // ESC dismisses the pause menu (resume), or backs out of the slot picker.
        // Edge-detect so the press that opened the menu doesn't immediately close it.
        bool down = Keyboard.GetState().IsKeyDown(Keys.Escape);
        bool justPressed = down && !_escWasDown;
        _escWasDown = down;
        if (justPressed)
        {
            if (_showingSlots) BuildMain();
            else _game.Screens.Pop();
        }
    }

    public void Draw(GameTime gt, SpriteBatch sb)
    {
        // Don't clear — let the play screen's last frame remain visible underneath.
        _desktop.Render();
    }

    public void Deactivate() { }
    public void Reactivate() { }
}
