"""Tests for the error recovery system."""

import pytest

from agent_scout.recovery import (
    ErrorCategory,
    RecoveryEngine,
    RecoveryLevel,
    classify_error,
)


def test_classify_rate_limit():
    assert classify_error("429 Too Many Requests") == ErrorCategory.RATE_LIMIT
    assert classify_error("Rate limit exceeded") == ErrorCategory.RATE_LIMIT


def test_classify_timeout():
    assert classify_error("Connection timed out") == ErrorCategory.TIMEOUT
    assert classify_error("Request timeout after 30s") == ErrorCategory.TIMEOUT


def test_classify_blocked():
    assert classify_error("403 Forbidden") == ErrorCategory.BLOCKED
    assert classify_error("Blocked by Cloudflare") == ErrorCategory.BLOCKED


def test_classify_auth():
    assert classify_error("401 Unauthorized") == ErrorCategory.AUTH
    assert classify_error("Invalid API key") == ErrorCategory.AUTH


def test_classify_network():
    assert classify_error("Connection refused") == ErrorCategory.NETWORK
    assert classify_error("DNS resolution failed") == ErrorCategory.NETWORK


def test_classify_not_found():
    assert classify_error("404 Not Found") == ErrorCategory.NOT_FOUND


def test_classify_parse():
    assert classify_error("JSON parse error") == ErrorCategory.PARSE


def test_classify_llm():
    assert classify_error("Model context length exceeded") == ErrorCategory.LLM_ERROR


def test_classify_unknown():
    assert classify_error("Something weird happened") == ErrorCategory.UNKNOWN


@pytest.fixture
def engine():
    return RecoveryEngine(max_retries=3)


def test_create_context(engine):
    ctx = engine.create_context(
        "429 Too Many Requests",
        tool_name="web_search",
        tool_input={"query": "test"},
    )
    assert ctx.error_category == ErrorCategory.RATE_LIMIT
    assert ctx.tool_name == "web_search"
    assert len(ctx.attempts) == 0


def test_get_recovery_strategies(engine):
    ctx = engine.create_context("Rate limit exceeded")
    strategies = engine.get_recovery_strategies(ctx)
    assert len(strategies) > 0
    assert any(s["strategy"] == "backoff" for s in strategies)


def test_strategies_filter_attempted(engine):
    ctx = engine.create_context("Rate limit exceeded")
    strategies_before = engine.get_recovery_strategies(ctx)
    engine.record_attempt(ctx, "backoff", "Waited 5 seconds", succeeded=False)
    strategies_after = engine.get_recovery_strategies(ctx)
    assert len(strategies_after) < len(strategies_before)


def test_current_level_escalation(engine):
    ctx = engine.create_context("Error")
    assert engine.get_current_level(ctx) == RecoveryLevel.SMART_RETRY
    engine.record_attempt(ctx, "retry", "First attempt", succeeded=False)
    assert engine.get_current_level(ctx) == RecoveryLevel.FALLBACK
    engine.record_attempt(ctx, "alt_provider", "Second attempt", succeeded=False)
    assert engine.get_current_level(ctx) == RecoveryLevel.FALLBACK
    engine.record_attempt(ctx, "queue", "Third attempt", succeeded=False)
    assert engine.get_current_level(ctx) == RecoveryLevel.ASK_USER


def test_record_successful_attempt(engine):
    ctx = engine.create_context("Error")
    engine.record_attempt(ctx, "retry", "Worked on retry", succeeded=True)
    assert ctx.resolved is True
    assert ctx.resolution == "Worked on retry"


def test_should_ask_user(engine):
    ctx = engine.create_context("Error")
    assert engine.should_ask_user(ctx) is False
    for i in range(3):
        engine.record_attempt(ctx, f"try_{i}", f"Attempt {i}", succeeded=False)
    assert engine.should_ask_user(ctx) is True


def test_build_user_message(engine):
    ctx = engine.create_context(
        "403 Forbidden",
        tool_name="browse_page",
    )
    engine.record_attempt(ctx, "alt_user_agent", "Changed UA", succeeded=False, error="Still 403")
    msg = engine.build_user_message(ctx)
    assert "403 Forbidden" in msg
    assert "browse_page" in msg
    assert "Changed UA" in msg
    assert "failed" in msg


def test_get_fallback_tools(engine):
    fallbacks = engine.get_fallback_tools("web_search")
    assert len(fallbacks) > 0
    assert "web_search_brave" in fallbacks


def test_get_fallback_tools_unknown(engine):
    fallbacks = engine.get_fallback_tools("totally_unknown_tool")
    assert fallbacks == []


def test_history(engine):
    engine.create_context("Error 1")
    engine.create_context("Error 2")
    assert len(engine.history) == 2
