namespace ReactorMaintenance.Simulation.Tests;

public sealed class LevelEditorTests
{
    [Fact]
    public void DoorToolRequiresExplicitAdjacentEdgeSelection()
    {
        var level = LevelState.Create("Door editor", 6, 6);

        var withDoorProp = LevelEditor.Apply(level, new(2, 2), new() { Tool = EEditorTool.Door });
        var withDoorEdge = LevelEditor.SetDoorEdge(withDoorProp, new(2, 2), new(3, 2));
        var rejected = LevelEditor.SetDoorEdge(withDoorEdge, new(2, 2), new(4, 2));

        Assert.Equal(EPropType.Door, withDoorProp.GetProp(new(2, 2)).Type);
        Assert.Empty(withDoorProp.Doors);
        Assert.Single(withDoorEdge.Doors);
        Assert.Equal(withDoorEdge.Doors, rejected.Doors);
    }

    [Fact]
    public void ElectricityLeakUsesAuthoredWallAccessFace()
    {
        var level = LevelState.Create("Electricity leak editor", 6, 6);
        level = level.SetTerrain(new(2, 2), ECellTerrain.Wall);

        var next = LevelEditor.SetLeak(level, new(2, 2), new(2, 3), ECarrierType.Electricity);
        var rejected = LevelEditor.SetLeak(next, new(2, 2), new(4, 4), ECarrierType.Electricity);

        Assert.Single(next.Leaks);
        Assert.Equal(new(2, 3), next.Leaks[0].AccessPosition);
        Assert.Equal(EUndergroundState.Leaking, next.GetUnderground(new(2, 2), ECarrierType.Electricity).State);
        Assert.Equal(next.Leaks, rejected.Leaks);
    }

    [Fact]
    public void ReactorBindingUpdatesOnlyMatchingCarrierConsumer()
    {
        var level = LevelState.Create("Binding editor", 8, 6);
        level = level.SetProp(new(1, 1), new() { Type = EPropType.ReactorControl, ReactorId = 1 });
        level = level.SetProp(new(2, 1), new() { Type = EPropType.Consumer, Carrier = ECarrierType.Fuel });
        level = level.SetProp(new(3, 1), new() { Type = EPropType.Consumer, Carrier = ECarrierType.Coolant }) with {
            Reactors = [
                new() {
                    ReactorId = 1,
                    ControlPosition = new(1, 1),
                    FuelConsumerPosition = new(1, 1),
                    CoolantConsumerPosition = new(1, 1),
                    ElectricityConsumerPosition = new(1, 1)
                }
            ]
        };

        var bound = LevelEditor.BindReactorConsumer(level, 1, ECarrierType.Fuel, new(2, 1));
        var rejected = LevelEditor.BindReactorConsumer(bound, 1, ECarrierType.Fuel, new(3, 1));

        Assert.Equal(new(2, 1), bound.Reactors[0].FuelConsumerPosition);
        Assert.Equal(bound.Reactors[0].FuelConsumerPosition, rejected.Reactors[0].FuelConsumerPosition);
    }

    [Fact]
    public void RuleEventEditorAssignsStableIdsAndCanRemoveEvents()
    {
        var level = LevelState.Create("Rule editor", 6, 6);

        var withRule = LevelEditor.AddRuleEvent(level, new() {
            Phase = ERuleEventPhase.EndOfTurn,
            Predicates = [new() { Kind = ERulePredicateKind.TurnAtLeast, Turn = 1 }],
            Effects = [new() { Kind = ERuleEffectKind.EmitWarning, Message = "authored" }]
        });
        var removed = LevelEditor.RemoveRuleEvent(withRule, "rule-1");

        Assert.Single(withRule.RuleEvents);
        Assert.Equal("rule-1", withRule.RuleEvents[0].Id);
        Assert.Empty(removed.RuleEvents);
    }
}