"""Tests for library/download_management/retry_manager.py."""

from datetime import timedelta
from unittest.mock import Mock, patch


class TestRetryDecision:
    """Tests for RetryDecision dataclass."""

    def test_create_can_retry_true(self):
        """Test creating RetryDecision with can_retry=True."""
        from local_deep_research.library.download_management.retry_manager import (
            RetryDecision,
        )

        decision = RetryDecision(can_retry=True)
        assert decision.can_retry is True
        assert decision.reason is None
        assert decision.estimated_wait_time is None

    def test_create_can_retry_false_with_reason(self):
        """Test creating RetryDecision with reason."""
        from local_deep_research.library.download_management.retry_manager import (
            RetryDecision,
        )

        decision = RetryDecision(can_retry=False, reason="Rate limited")
        assert decision.can_retry is False
        assert decision.reason == "Rate limited"

    def test_create_with_estimated_wait_time(self):
        """Test creating RetryDecision with estimated wait time."""
        from local_deep_research.library.download_management.retry_manager import (
            RetryDecision,
        )

        wait = timedelta(hours=1)
        decision = RetryDecision(can_retry=False, estimated_wait_time=wait)
        assert decision.estimated_wait_time == wait


class TestResourceFilterResult:
    """Tests for ResourceFilterResult class."""

    def test_create_with_all_parameters(self):
        """Test creating ResourceFilterResult with all parameters."""
        from local_deep_research.library.download_management.retry_manager import (
            ResourceFilterResult,
        )

        result = ResourceFilterResult(
            resource_id=123,
            can_retry=True,
            status="available",
            reason="",
            estimated_wait=None,
        )

        assert result.resource_id == 123
        assert result.can_retry is True
        assert result.status == "available"
        assert result.reason == ""
        assert result.estimated_wait is None

    def test_create_with_failed_status(self):
        """Test creating ResourceFilterResult with failed status."""
        from local_deep_research.library.download_management.retry_manager import (
            ResourceFilterResult,
        )

        result = ResourceFilterResult(
            resource_id=456,
            can_retry=False,
            status="permanently_failed",
            reason="Resource not found",
            estimated_wait=None,
        )

        assert result.resource_id == 456
        assert result.can_retry is False
        assert result.status == "permanently_failed"
        assert result.reason == "Resource not found"


class TestFilterSummary:
    """Tests for FilterSummary class."""

    def test_init_with_zeros(self):
        """Test that FilterSummary initializes with zeros."""
        from local_deep_research.library.download_management.retry_manager import (
            FilterSummary,
        )

        summary = FilterSummary()
        assert summary.total_count == 0
        assert summary.downloadable_count == 0
        assert summary.permanently_failed_count == 0
        assert summary.temporarily_failed_count == 0
        assert summary.available_count == 0

    def test_add_result_increments_total(self):
        """Test that add_result increments total count."""
        from local_deep_research.library.download_management.retry_manager import (
            FilterSummary,
            ResourceFilterResult,
        )

        summary = FilterSummary()
        result = ResourceFilterResult(1, True, "available")

        summary.add_result(result)
        assert summary.total_count == 1

    def test_add_result_increments_downloadable_for_can_retry(self):
        """Test that downloadable count is incremented when can_retry is True."""
        from local_deep_research.library.download_management.retry_manager import (
            FilterSummary,
            ResourceFilterResult,
        )

        summary = FilterSummary()
        result = ResourceFilterResult(1, can_retry=True, status="available")

        summary.add_result(result)
        assert summary.downloadable_count == 1

    def test_add_result_increments_permanently_failed(self):
        """Test that permanently_failed count is incremented correctly."""
        from local_deep_research.library.download_management.retry_manager import (
            FilterSummary,
            ResourceFilterResult,
        )

        summary = FilterSummary()
        result = ResourceFilterResult(
            1, can_retry=False, status="permanently_failed"
        )

        summary.add_result(result)
        assert summary.permanently_failed_count == 1

    def test_add_result_increments_temporarily_failed(self):
        """Test that temporarily_failed count is incremented correctly."""
        from local_deep_research.library.download_management.retry_manager import (
            FilterSummary,
            ResourceFilterResult,
        )

        summary = FilterSummary()
        result = ResourceFilterResult(
            1, can_retry=False, status="temporarily_failed"
        )

        summary.add_result(result)
        assert summary.temporarily_failed_count == 1

    def test_to_dict_returns_expected_keys(self):
        """Test that to_dict returns all expected keys."""
        from local_deep_research.library.download_management.retry_manager import (
            FilterSummary,
        )

        summary = FilterSummary()
        result = summary.to_dict()

        assert "total_count" in result
        assert "downloadable_count" in result
        assert "permanently_failed_count" in result
        assert "temporarily_failed_count" in result
        assert "available_count" in result
        assert "failure_type_counts" in result

    def test_to_dict_values_match(self):
        """Test that to_dict values match summary state."""
        from local_deep_research.library.download_management.retry_manager import (
            FilterSummary,
            ResourceFilterResult,
        )

        summary = FilterSummary()
        summary.add_result(ResourceFilterResult(1, True, "available"))
        summary.add_result(ResourceFilterResult(2, False, "permanently_failed"))

        result = summary.to_dict()

        assert result["total_count"] == 2
        assert result["downloadable_count"] == 1
        assert result["permanently_failed_count"] == 1


class TestRetryManagerGetResourceStatus:
    """Tests for RetryManager._get_resource_status method."""

    def test_returns_permanently_failed(self):
        """Test that permanently_failed status is returned correctly."""
        from local_deep_research.library.download_management.retry_manager import (
            RetryManager,
        )

        with patch(
            "local_deep_research.library.download_management.retry_manager.ResourceStatusTracker"
        ):
            with patch(
                "local_deep_research.library.download_management.retry_manager.FailureClassifier"
            ):
                manager = RetryManager.__new__(RetryManager)
                manager.failure_classifier = Mock()
                manager.status_tracker = Mock()

                result = manager._get_resource_status(
                    can_retry=False, reason="permanently failed: not found"
                )

                assert result == "permanently_failed"

    def test_returns_temporarily_failed(self):
        """Test that temporarily_failed status is returned correctly."""
        from local_deep_research.library.download_management.retry_manager import (
            RetryManager,
        )

        with patch(
            "local_deep_research.library.download_management.retry_manager.ResourceStatusTracker"
        ):
            with patch(
                "local_deep_research.library.download_management.retry_manager.FailureClassifier"
            ):
                manager = RetryManager.__new__(RetryManager)
                manager.failure_classifier = Mock()
                manager.status_tracker = Mock()

                result = manager._get_resource_status(
                    can_retry=False, reason="cooldown active"
                )

                assert result == "temporarily_failed"

    def test_returns_available_when_can_retry(self):
        """Test that available status is returned when can_retry is True."""
        from local_deep_research.library.download_management.retry_manager import (
            RetryManager,
        )

        with patch(
            "local_deep_research.library.download_management.retry_manager.ResourceStatusTracker"
        ):
            with patch(
                "local_deep_research.library.download_management.retry_manager.FailureClassifier"
            ):
                manager = RetryManager.__new__(RetryManager)
                manager.failure_classifier = Mock()
                manager.status_tracker = Mock()

                result = manager._get_resource_status(
                    can_retry=True, reason=None
                )

                assert result == "available"

    def test_returns_unavailable_for_unknown_reason(self):
        """Test that unavailable status is returned for unknown reasons."""
        from local_deep_research.library.download_management.retry_manager import (
            RetryManager,
        )

        with patch(
            "local_deep_research.library.download_management.retry_manager.ResourceStatusTracker"
        ):
            with patch(
                "local_deep_research.library.download_management.retry_manager.FailureClassifier"
            ):
                manager = RetryManager.__new__(RetryManager)
                manager.failure_classifier = Mock()
                manager.status_tracker = Mock()

                result = manager._get_resource_status(
                    can_retry=False, reason="some other reason"
                )

                assert result == "unavailable"


class TestRetryManagerShouldRetry:
    """Tests for RetryManager.should_retry_resource method."""

    def test_delegates_to_status_tracker(self):
        """Test that should_retry_resource delegates to status tracker."""
        from local_deep_research.library.download_management.retry_manager import (
            RetryManager,
            RetryDecision,
        )

        with patch(
            "local_deep_research.library.download_management.retry_manager.ResourceStatusTracker"
        ) as MockTracker:
            with patch(
                "local_deep_research.library.download_management.retry_manager.FailureClassifier"
            ):
                mock_tracker = Mock()
                mock_tracker.can_retry.return_value = (True, None)
                MockTracker.return_value = mock_tracker

                manager = RetryManager.__new__(RetryManager)
                manager.failure_classifier = Mock()
                manager.status_tracker = mock_tracker

                result = manager.should_retry_resource(123)

                mock_tracker.can_retry.assert_called_once_with(123)
                assert isinstance(result, RetryDecision)
                assert result.can_retry is True


class TestRetryManagerGetFilterSummary:
    """Tests for RetryManager.get_filter_summary method."""

    def test_returns_filter_summary(self):
        """Test that get_filter_summary returns a FilterSummary."""
        from local_deep_research.library.download_management.retry_manager import (
            RetryManager,
            FilterSummary,
            ResourceFilterResult,
        )

        with patch(
            "local_deep_research.library.download_management.retry_manager.ResourceStatusTracker"
        ):
            with patch(
                "local_deep_research.library.download_management.retry_manager.FailureClassifier"
            ):
                manager = RetryManager.__new__(RetryManager)
                manager.failure_classifier = Mock()
                manager.status_tracker = Mock()

                results = [
                    ResourceFilterResult(1, True, "available"),
                    ResourceFilterResult(2, False, "permanently_failed"),
                ]

                summary = manager.get_filter_summary(results)

                assert isinstance(summary, FilterSummary)
                assert summary.total_count == 2
                assert summary.downloadable_count == 1
                assert summary.permanently_failed_count == 1
