using Nexus.Api.Data;
using Xunit;

namespace Nexus.Api.Tests;

public class TaskBoardTests
{
    // ── TaskStateHelper: BoardGroupKey ──

    [Theory]
    [InlineData("Backlog", "offen")]
    [InlineData("In progress", "inProgress")]
    [InlineData("Delegated", "delegated")]
    [InlineData("Review", "review")]
    [InlineData("Blocked", "blocked")]
    [InlineData("Done", "done")]
    [InlineData("backlog", "offen")]
    [InlineData("in progress", "inProgress")]
    [InlineData("delegated", "delegated")]
    [InlineData("review", "review")]
    [InlineData("blocked", "blocked")]
    [InlineData("done", "done")]
    [InlineData("", "offen")]
    [InlineData(null, "offen")]
    [InlineData("unknown", "offen")]
    public void BoardGroupKey_ReturnsExpectedGroup(string? state, string expected)
    {
        var result = TaskStateHelper.BoardGroupKey(state);
        Assert.Equal(expected, result);
    }

    // ── TaskStateHelper: BoardGroupToState ──

    [Theory]
    [InlineData("offen", "Backlog")]
    [InlineData("inProgress", "In progress")]
    [InlineData("inprogress", "In progress")]
    [InlineData("delegated", "Delegated")]
    [InlineData("review", "Review")]
    [InlineData("blocked", "Blocked")]
    [InlineData("done", "Done")]
    [InlineData("Offen", "Backlog")]
    [InlineData("", null)]
    [InlineData(null, null)]
    [InlineData("unknown", null)]
    public void BoardGroupToState_ReturnsExpectedState(string? groupKey, string? expected)
    {
        var result = TaskStateHelper.BoardGroupToState(groupKey);
        Assert.Equal(expected, result);
    }

    // ── TaskStateHelper: AllStates has 6 entries ──

    [Fact]
    public void AllStates_ContainsAllSixStates()
    {
        var states = TaskStateHelper.AllStates;
        Assert.Equal(6, states.Length);
        Assert.Contains("Backlog", states);
        Assert.Contains("In progress", states);
        Assert.Contains("Delegated", states);
        Assert.Contains("Review", states);
        Assert.Contains("Blocked", states);
        Assert.Contains("Done", states);
    }

    // ── TaskStateHelper: IsValidState ──

    [Theory]
    [InlineData("Backlog", true)]
    [InlineData("In progress", true)]
    [InlineData("Delegated", true)]
    [InlineData("Review", true)]
    [InlineData("Blocked", true)]
    [InlineData("Done", true)]
    [InlineData("backlog", true)]
    [InlineData("offen", false)]
    [InlineData("", false)]
    [InlineData(null, false)]
    [InlineData("unknown", false)]
    public void IsValidState_ReturnsCorrectResult(string? state, bool expected)
    {
        Assert.Equal(expected, TaskStateHelper.IsValidState(state));
    }

    // ── TaskStateHelper: IsInProgressOrBlocked ──

    [Theory]
    [InlineData("In progress", true)]
    [InlineData("Blocked", true)]
    [InlineData("Backlog", false)]
    [InlineData("Delegated", false)]
    [InlineData("Review", false)]
    [InlineData("Done", false)]
    [InlineData(null, false)]
    public void IsInProgressOrBlocked_ReturnsCorrectResult(string? state, bool expected)
    {
        Assert.Equal(expected, TaskStateHelper.IsInProgressOrBlocked(state));
    }

    // ── TaskStateHelper: IsDoneOrBacklog ──

    [Theory]
    [InlineData("Done", true)]
    [InlineData("Backlog", true)]
    [InlineData("In progress", false)]
    [InlineData("Delegated", false)]
    [InlineData("Review", false)]
    [InlineData("Blocked", false)]
    [InlineData(null, false)]
    public void IsDoneOrBacklog_ReturnsCorrectResult(string? state, bool expected)
    {
        Assert.Equal(expected, TaskStateHelper.IsDoneOrBacklog(state));
    }

    // ── TaskStateHelper: ToDisplayString ──

    [Theory]
    [InlineData("Backlog", "Offen")]
    [InlineData("In progress", "In Bearbeitung")]
    [InlineData("Delegated", "Delegiert")]
    [InlineData("Review", "Review")]
    [InlineData("Blocked", "Blockiert")]
    [InlineData("Done", "Erledigt")]
    [InlineData("backlog", "Offen")]
    [InlineData("", "")]
    [InlineData(null, "")]
    [InlineData("unknown", "unknown")]
    public void ToDisplayString_ReturnsGermanLabel(string? state, string expected)
    {
        Assert.Equal(expected, TaskStateHelper.ToDisplayString(state));
    }

    // ── TaskState helper: ToStateString and ToTaskState roundtrip ──

    [Fact]
    public void ToStateString_And_ToTaskState_RoundTrip()
    {
        var states = new[] { TaskState.Backlog, TaskState.InProgress, TaskState.Delegated, TaskState.Review, TaskState.Blocked, TaskState.Done };
        foreach (var state in states)
        {
            var str = state.ToStateString();
            var parsed = str.ToTaskState();
            Assert.Equal(state, parsed);
        }
    }

    [Fact]
    public void ToTaskState_DefaultsToBacklog_ForUnknownString()
    {
        Assert.Equal(TaskState.Backlog, "unknown".ToTaskState());
    }

    // ── TaskStateHelper: CanChangeState (Iris + Bao policy) ──

    [Fact]
    public void CanChangeState_Iris_CanChangeAnyTask()
    {
        var agentTask = new WorkTask { Title = "test", IsAgentTask = true, Source = "iris" };
        var normalTask = new WorkTask { Title = "test", IsAgentTask = false, Source = "bao" };

        Assert.True(TaskStateHelper.CanChangeState("iris", agentTask));
        Assert.True(TaskStateHelper.CanChangeState("iris", normalTask));
    }

    [Fact]
    public void CanChangeState_Bao_CanChangeAnyTask()
    {
        var agentTask = new WorkTask { Title = "test", IsAgentTask = true, Source = "iris" };
        var normalTask = new WorkTask { Title = "test", IsAgentTask = false, Source = "bao" };

        Assert.True(TaskStateHelper.CanChangeState("bao", agentTask));
        Assert.True(TaskStateHelper.CanChangeState("bao", normalTask));
    }

    [Fact]
    public void CanChangeState_SubAgents_NeverAllowed()
    {
        var task = new WorkTask { Title = "test", IsAgentTask = false, Source = "bao" };

        Assert.False(TaskStateHelper.CanChangeState("programmer", task));
        Assert.False(TaskStateHelper.CanChangeState("reviewer", task));
        Assert.False(TaskStateHelper.CanChangeState("architekt", task));
    }

    [Fact]
    public void CanChangeState_SubAgents_NeverAllowed_EvenForAgentTasks()
    {
        var agentTask = new WorkTask { Title = "test", IsAgentTask = true, Source = "iris" };

        Assert.False(TaskStateHelper.CanChangeState("programmer", agentTask));
        Assert.False(TaskStateHelper.CanChangeState("reviewer", agentTask));
        Assert.False(TaskStateHelper.CanChangeState("architekt", agentTask));
    }

    [Fact]
    public void CanChangeState_NexusSystem_IsAllowed()
    {
        var task = new WorkTask { Title = "test", IsAgentTask = false };
        Assert.True(TaskStateHelper.CanChangeState("nexus-system", task));
        
        var agentTask = new WorkTask { Title = "test", IsAgentTask = true };
        Assert.True(TaskStateHelper.CanChangeState("nexus-system", agentTask));
    }

    [Fact]
    public void CanChangeState_UnknownCaller_Rejected()
    {
        var task = new WorkTask { Title = "test", IsAgentTask = false };
        var agentTask = new WorkTask { Title = "test", IsAgentTask = true };

        Assert.False(TaskStateHelper.CanChangeState("", task));
        Assert.False(TaskStateHelper.CanChangeState("", agentTask));
        Assert.False(TaskStateHelper.CanChangeState("unknown", task));
        Assert.False(TaskStateHelper.CanChangeState(null, task));
    }

    // ── TaskStateHelper: CanEditContent ──

    [Fact]
    public void CanEditContent_Iris_IsAllowed()
    {
        Assert.True(TaskStateHelper.CanEditContent("iris"));
    }

    [Fact]
    public void CanEditContent_Bao_IsAllowed()
    {
        Assert.True(TaskStateHelper.CanEditContent("bao"));
    }

    [Fact]
    public void CanEditContent_SubAgents_AreAllowed()
    {
        Assert.True(TaskStateHelper.CanEditContent("programmer"));
        Assert.True(TaskStateHelper.CanEditContent("reviewer"));
        Assert.True(TaskStateHelper.CanEditContent("architekt"));
    }

    [Fact]
    public void CanEditContent_NexusSystem_IsAllowed()
    {
        Assert.True(TaskStateHelper.CanEditContent("nexus-system"));
    }

    [Fact]
    public void CanEditContent_UnknownCaller_Rejected()
    {
        Assert.False(TaskStateHelper.CanEditContent(""));
        Assert.False(TaskStateHelper.CanEditContent(null));
        Assert.False(TaskStateHelper.CanEditContent("   "));
    }
}
