using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Myra.Graphics2D.UI;
using Theriapolis.Core;
using Theriapolis.Core.Persistence;
using Theriapolis.Game.Platform;

namespace Theriapolis.Game.Screens;

/// <summary>
/// Slot picker. Lists C.SAVE_SLOT_COUNT slots plus the autosave slot. Reading
/// each slot only deserializes the JSON header (cheap), so opening the picker
/// is fast even if there are many large saves.
///
/// Phase 4 mode: load only (called from TitleScreen). Save-from-game uses the
/// F5 quicksave; a save-as-slot UI can be added later by extending this screen
/// with an Action.
/// </summary>
public sealed class SaveLoadScreen : IScreen
{
    private Game1 _game = null!;
    private Desktop _desktop = null!;

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

    private void BuildUI()
    {
        var root = new VerticalStackPanel
        {
            Spacing             = 8,
            HorizontalAlignment = HorizontalAlignment.Center,
            VerticalAlignment   = VerticalAlignment.Center,
        };

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

        // Autosave row first.
        AddSlotRow(root, "Autosave", SavePaths.AutosavePath());
        for (int i = 1; i <= C.SAVE_SLOT_COUNT; i++)
            AddSlotRow(root, $"Slot {i:D2}", SavePaths.SlotPath(i));

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

        _desktop = new Desktop { Root = root };
    }

    private void AddSlotRow(VerticalStackPanel parent, string label, string path)
    {
        string text = label;
        bool exists = File.Exists(path);
        bool compatible = false;
        if (exists)
        {
            try
            {
                var bytes = File.ReadAllBytes(path);
                var header = SaveCodec.DeserializeHeaderOnly(bytes);
                if (SaveCodec.IsCompatible(header))
                {
                    text = $"{label}: {header.SlotLabel()}";
                    compatible = true;
                }
                else
                {
                    text = $"{label}: <v{header.Version} — incompatible (Phase 5+ only)>";
                }
            }
            catch
            {
                text = $"{label}: <unreadable>";
            }
        }
        else
        {
            text = $"{label}: <empty>";
        }

        var btn = new TextButton
        {
            Text  = text,
            Width = 480,
            HorizontalAlignment = HorizontalAlignment.Center,
        };
        if (exists && compatible) btn.Click += (_, _) => LoadSlot(path);
        else                       btn.Enabled = false;
        parent.Widgets.Add(btn);
    }

    private void LoadSlot(string path)
    {
        try
        {
            var bytes = File.ReadAllBytes(path);
            var headerOnly = SaveCodec.DeserializeHeaderOnly(bytes);
            if (!SaveCodec.IsCompatible(headerOnly))
            {
                var err = new Label
                {
                    Text = SaveCodec.IncompatibilityReason(headerOnly),
                    HorizontalAlignment = HorizontalAlignment.Center,
                };
                _desktop.Root = err;
                return;
            }
            var (header, body) = SaveCodec.Deserialize(bytes);
            _game.Screens.Pop(); // back to title
            _game.Screens.Push(new WorldGenProgressScreen(header.ParseSeed(), restoreFromSave: body, savedHeader: header));
        }
        catch (Exception ex)
        {
            // Crude error display: replace the screen content with the error.
            var err = new Label { Text = $"Load failed:\n{ex.Message}", HorizontalAlignment = HorizontalAlignment.Center };
            _desktop.Root = err;
        }
    }

    public void Update(GameTime gt)
    {
        if (Keyboard.GetState().IsKeyDown(Keys.Escape)) _game.Screens.Pop();
    }

    public void Draw(GameTime gt, SpriteBatch sb)
    {
        _game.GraphicsDevice.Clear(new Color(20, 20, 30));
        _desktop.Render();
    }

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