"""Tests for task subsetting — the first and cheapest cost control."""

from __future__ import annotations

import pytest

from ablate.errors import AblateError
from ablate.task import Task, select_tasks


def _task(task_id: str, tags: list[str] | None = None) -> Task:
    return Task(
        id=task_id,
        prompt="do it",
        tags=tags or [],
        **{"assert": [{"id": "a", "type": "exit_code", "run": "true"}]},
    )


SUITE = [
    _task("fix-null-deref", ["smoke", "bug"]),
    _task("fix-race-condition", ["bug"]),
    _task("add-cli-flag", ["smoke", "feature"]),
    _task("refactor-parser", []),
]


def test_no_selection_returns_the_whole_suite():
    assert select_tasks(SUITE) == SUITE


def test_exact_ids_are_selected():
    chosen = select_tasks(SUITE, only="add-cli-flag,refactor-parser")
    assert [t.id for t in chosen] == ["add-cli-flag", "refactor-parser"]


def test_globs_are_supported():
    assert [t.id for t in select_tasks(SUITE, only="fix-*")] == [
        "fix-null-deref",
        "fix-race-condition",
    ]


def test_whitespace_around_ids_is_tolerated():
    assert len(select_tasks(SUITE, only=" add-cli-flag , refactor-parser ")) == 2


def test_tags_are_selected():
    assert [t.id for t in select_tasks(SUITE, tag="smoke")] == [
        "fix-null-deref",
        "add-cli-flag",
    ]


def test_multiple_tags_are_a_union():
    assert len(select_tasks(SUITE, tag="feature,bug")) == 3


def test_id_and_tag_filters_compose():
    chosen = select_tasks(SUITE, only="fix-*", tag="smoke")
    assert [t.id for t in chosen] == ["fix-null-deref"]


def test_selecting_nothing_by_id_is_an_error():
    """Silently running an empty suite would produce a confident-looking
    report over zero trials."""
    with pytest.raises(AblateError, match="no task matched"):
        select_tasks(SUITE, only="nope-*")


def test_selecting_nothing_by_tag_is_an_error():
    with pytest.raises(AblateError, match="no task carries tag"):
        select_tasks(SUITE, tag="nonexistent")


def test_unmatched_id_lists_what_exists():
    with pytest.raises(AblateError, match="add-cli-flag"):
        select_tasks(SUITE, only="nope")


def test_unmatched_tag_lists_the_tags_that_exist():
    with pytest.raises(AblateError, match="smoke"):
        select_tasks(SUITE, tag="nonexistent")


def test_a_suite_with_no_tags_says_so():
    untagged = [_task("only-task")]
    with pytest.raises(AblateError, match="none declared"):
        select_tasks(untagged, tag="smoke")


def test_tags_default_to_empty():
    assert _task("x").tags == []
