"""Step definitions for sandbox dirs cache BDD tests (#7527 / PR #10989)."""

from __future__ import annotations

from behave import given, then, when

from cleveragents.infrastructure.sandbox.dirs_cache import SandboxDirsCache


def _make_cache() -> SandboxDirsCache:
    """Create a fresh cache instance, always starting clean."""
    return SandboxDirsCache()


# Each scenario sets context._sdc (SandboxDirsCache) and context._last_* for result tracking.


@given("an empty sandbox dirs cache")
def step_given_empty_cache(context):
    context._sdc = SandboxDirsCache()


@given('a sandbox dirs cache with one path "{dir_path}" for plan "{plan_id}"')
def step_given_one_dir(context, dir_path, plan_id):
    context._sdc = SandboxDirsCache()
    context._sdc.record(plan_id, dir_path)


@given('a sandbox dirs cache with paths for plans "{plan_a}" and "{plan_b}"')
def step_given_two_plans(context, plan_a, plan_b):
    context._sdc = SandboxDirsCache()
    context._sdc.record(plan_a, f"/tmp/sandboxes/{plan_a}-dir")
    context._sdc.record(plan_b, f"/tmp/sandboxes/{plan_b}-dir")


@when('I record dir "{dir_path}" for plan "{plan_id}"')
def step_when_record_one(context, dir_path, plan_id):
    context._last_result = None
    context._sdc.record(plan_id, dir_path)


@when('I record dir "{dir_path}" for plan "{plan_id}" again')
def step_when_record_duplicate(context, dir_path, plan_id):
    context._last_result = None
    context._sdc.record(plan_id, dir_path)


@when('I purge sandbox dirs for plan "{plan_id}"')
def step_when_purge(context, plan_id):
    context._purged = context._sdc.purge(plan_id)


@when('I check if dir "{dir_path}" belongs to plan "{plan_id}"')
def step_when_check_membership(context, dir_path, plan_id):
    context._check_result = context._sdc.get(plan_id, dir_path)


@when("I clear all entries from the sandbox dirs cache")
def step_when_clear_all(context):
    context._sdc.clear()


@then('the cache should contain one path for plan "{plan_id}"')
def step_then_one_path_for_plan(context, plan_id):
    actual = len(context._sdc._dirs.get(plan_id, set()))
    assert actual == 1, f"Expected 1 path for {plan_id}, got {actual}"


@then('the cache should contain two paths for plan "{plan_id}"')
def step_then_two_paths_for_plan(context, plan_id):
    actual = len(context._sdc._dirs.get(plan_id, set()))
    assert actual == 2, f"Expected 2 paths for {plan_id}, got {actual}"


@then("the total tracked plan count should be 1")
def step_then_plan_count_one(context):
    assert context._sdc.plan_count == 1


@then("the total tracked path count should be 2")
def step_then_path_count_two(context):
    assert context._sdc.dir_count == 2


@then("the cache should contain two distinct plans")
def step_then_two_plans(context):
    assert len(context._sdc._dirs) == 2


@then("the total tracked plan count should be 2")
def step_then_plan_count_two(context):
    assert context._sdc.plan_count == 2


@then('the cache should contain no paths for plan "{plan_id}"')
def step_then_no_paths_for_plan(context, plan_id):
    actual = len(context._sdc._dirs.get(plan_id, set()))
    assert actual == 0, f"Expected 0 paths for {plan_id}, got {actual}"


@then("the total tracked plan count should be 0")
def step_then_plan_count_zero(context):
    assert context._sdc.plan_count == 0


@then("the purged path count should be 0")
def step_then_purged_count_zero(context):
    assert len(context._purged) == 0


@then("no plans should be removed from tracking")
def step_then_no_plans_removed(context):
    assert context._sdc.plan_count == 0


@then("the dir membership result should be True")
def step_then_membership_true(context):
    assert context._check_result is True


@then("the dir membership result should be False")
def step_then_membership_false(context):
    assert context._check_result is False


@then("no plans should remain tracked")
def step_then_no_plans_remaining(context):
    assert context._sdc.plan_count == 0


@then("total tracked path count should be 0")
def step_then_dir_count_zero(context):
    assert context._sdc.dir_count == 0


@then('the cache should still contain exactly one path for plan "{plan_id}"')
def step_then_one_path_after_rerecord(context, plan_id):
    actual = len(context._sdc._dirs.get(plan_id, set()))
    assert actual == 1, f"Expected 1 (idempotent), got {actual}"
