using ClaudeDo.Data.Filtering;
using ClaudeDo.Data.Models;
using TaskStatus = ClaudeDo.Data.Models.TaskStatus;

namespace ClaudeDo.Data.Tests.Filtering;

public sealed class VirtualFilterTests
{
    // --- Queued ---

    [Fact]
    public void Queued_matches_every_queued_task_regardless_of_parent()
    {
        var f = new StatusFilter("virtual:queued", TaskStatus.Queued);
        Assert.True (f.Matches(TaskFactory.Make("a", status: TaskStatus.Queued)));
        Assert.True (f.Matches(TaskFactory.Make("b", status: TaskStatus.Queued, parentId: "p")));
        Assert.False(f.Matches(TaskFactory.Make("c", status: TaskStatus.Running)));
    }

    [Fact]
    public void Queued_count_equals_match_for_top_level_and_children_alike()
    {
        // The point of the consolidation: counter must agree with display set.
        var f      = new StatusFilter("virtual:queued", TaskStatus.Queued);
        var orphan = TaskFactory.Make("o", status: TaskStatus.Queued, parentId: "missing");
        Assert.True(f.Matches(orphan));
        Assert.True(f.ShouldCount(orphan));
    }

    [Fact]
    public void Queued_planning_parent_with_queued_kid_is_context_match()
    {
        var f      = new StatusFilter("virtual:queued", TaskStatus.Queued);
        var parent = TaskFactory.Make("p", phase: PlanningPhase.Active, status: TaskStatus.Done);
        var kid    = TaskFactory.Make("k", parentId: "p", status: TaskStatus.Queued);
        var all    = new List<TaskEntity> { parent, kid };

        Assert.False(f.Matches(parent));
        Assert.True (f.MatchesAsContext(parent, all));
    }

    [Fact]
    public void Queued_non_planning_parent_is_never_context_match()
    {
        var f      = new StatusFilter("virtual:queued", TaskStatus.Queued);
        var parent = TaskFactory.Make("p", phase: PlanningPhase.None, status: TaskStatus.Done);
        var kid    = TaskFactory.Make("k", parentId: "p", status: TaskStatus.Queued);
        var all    = new List<TaskEntity> { parent, kid };

        Assert.False(f.MatchesAsContext(parent, all));
    }

    [Fact]
    public void Queued_planning_parent_without_queued_kid_is_not_context_match()
    {
        var f      = new StatusFilter("virtual:queued", TaskStatus.Queued);
        var parent = TaskFactory.Make("p", phase: PlanningPhase.Active);
        var kid    = TaskFactory.Make("k", parentId: "p", status: TaskStatus.Done);
        var all    = new List<TaskEntity> { parent, kid };

        Assert.False(f.MatchesAsContext(parent, all));
    }

    // --- Running mirrors Queued ---

    [Fact]
    public void Running_matches_and_context_mirror_queued()
    {
        var f      = new StatusFilter("virtual:running", TaskStatus.Running);
        var parent = TaskFactory.Make("p", phase: PlanningPhase.Active);
        var kid    = TaskFactory.Make("k", parentId: "p", status: TaskStatus.Running);
        var all    = new List<TaskEntity> { parent, kid };

        Assert.True (f.Matches(kid));
        Assert.True (f.MatchesAsContext(parent, all));
    }

    // --- Review ---

    [Fact]
    public void Review_matches_only_waiting_for_review()
    {
        var f = new ReviewFilter();
        Assert.True (f.Matches(TaskFactory.Make("a", status: TaskStatus.WaitingForReview, worktreeState: WorktreeState.Active)));
        Assert.True (f.Matches(TaskFactory.Make("b", status: TaskStatus.WaitingForReview, worktreeState: null)));
        Assert.False(f.Matches(TaskFactory.Make("c", status: TaskStatus.Done,             worktreeState: WorktreeState.Active)));
        Assert.False(f.Matches(TaskFactory.Make("d", status: TaskStatus.Failed,           worktreeState: WorktreeState.Active)));
    }

    [Fact]
    public void Review_count_equals_match()
    {
        var f = new ReviewFilter();
        var t = TaskFactory.Make("a", status: TaskStatus.WaitingForReview, worktreeState: WorktreeState.Active);
        Assert.Equal(f.Matches(t), f.ShouldCount(t));
    }
}
