using Theriapolis.Core;
using Theriapolis.Core.Persistence;
using Theriapolis.Core.Rules.Quests;
using Xunit;

namespace Theriapolis.Tests.Quests;

/// <summary>
/// Phase 6 M4 — capture/restore round-trip for quest engine state.
/// </summary>
public sealed class QuestSnapshotTests
{
    [Fact]
    public void CaptureAndRestore_RoundTripActiveAndCompleted()
    {
        var engine = new QuestEngine();
        engine.AdoptActive(new QuestState
        {
            QuestId = "q1", CurrentStep = "step_a", Status = QuestStatus.Active,
            StartedAt = 100, StepStartedAt = 150,
        });
        engine.Get("q1")!.Journal.Add("started q1");
        engine.AdoptCompleted(new QuestState
        {
            QuestId = "q2", CurrentStep = "<end>", Status = QuestStatus.Completed,
            StartedAt = 0, StepStartedAt = 200,
        });
        engine.Journal.Add("global event 1");

        var snap = QuestCodec.Capture(engine);
        Assert.Single(snap.Active);
        Assert.Single(snap.Completed);
        Assert.Single(snap.Journal);

        var rebuilt = new QuestEngine();
        QuestCodec.Restore(rebuilt, snap);
        Assert.True(rebuilt.IsActive("q1"));
        Assert.True(rebuilt.IsCompleted("q2"));
        Assert.Single(rebuilt.Journal);
        Assert.Equal("step_a", rebuilt.Get("q1")!.CurrentStep);
        Assert.Contains("started q1", rebuilt.Get("q1")!.Journal);
    }

    [Fact]
    public void SaveCodec_RoundTripsQuestEngineState()
    {
        var engine = new QuestEngine();
        engine.AdoptActive(new QuestState
        {
            QuestId = "main_act_i_001_arrival",
            CurrentStep = "find_magistrate",
            Status = QuestStatus.Active,
            StartedAt = 500, StepStartedAt = 700,
        });
        engine.Journal.Add("Arrived in Millhaven");

        var body = new SaveBody();
        body.Player.Name = "Tester";
        body.QuestEngineState = QuestCodec.Capture(engine);

        var header = new SaveHeader { Version = C.SAVE_SCHEMA_VERSION, WorldSeedHex = "0xCAFE" };
        var bytes = SaveCodec.Serialize(header, body);
        var (h2, b2) = SaveCodec.Deserialize(bytes);

        Assert.Equal(C.SAVE_SCHEMA_VERSION, h2.Version);
        Assert.Single(b2.QuestEngineState.Active);
        Assert.Equal("find_magistrate", b2.QuestEngineState.Active[0].CurrentStep);
        Assert.Single(b2.QuestEngineState.Journal);
    }

    [Fact]
    public void EmptyEngineState_OmitsTagFromSave()
    {
        // No active/completed/journal → no TAG_QUESTS section written.
        var body = new SaveBody { Player = { Name = "Empty" } };
        var bytes = SaveCodec.Serialize(new SaveHeader(), body);
        var (_, b2) = SaveCodec.Deserialize(bytes);
        Assert.Empty(b2.QuestEngineState.Active);
        Assert.Empty(b2.QuestEngineState.Completed);
        Assert.Empty(b2.QuestEngineState.Journal);
    }
}
