"""
Behavioral tests for error_handling/report_generator module.

Tests ErrorReportGenerator's pure logic: _make_error_user_friendly,
_format_partial_results, _get_technical_context.
"""


class TestMakeErrorUserFriendly:
    """Tests for ErrorReportGenerator._make_error_user_friendly() method."""

    def test_max_workers_error_replaced(self):
        from local_deep_research.error_handling.report_generator import (
            ErrorReportGenerator,
        )

        gen = ErrorReportGenerator()
        result = gen._make_error_user_friendly(
            "max_workers must be greater than 0"
        )
        assert "LLM failed to generate search questions" in result
        assert "Technical error:" in result

    def test_connection_refused_error_replaced(self):
        from local_deep_research.error_handling.report_generator import (
            ErrorReportGenerator,
        )

        gen = ErrorReportGenerator()
        result = gen._make_error_user_friendly("Connection refused [Errno 111]")
        assert "Cannot connect to the LLM service" in result

    def test_search_too_long_replaced(self):
        from local_deep_research.error_handling.report_generator import (
            ErrorReportGenerator,
        )

        gen = ErrorReportGenerator()
        result = gen._make_error_user_friendly(
            "The search is longer than 256 characters"
        )
        assert "too long for GitHub" in result

    def test_model_not_found_replaced(self):
        from local_deep_research.error_handling.report_generator import (
            ErrorReportGenerator,
        )

        gen = ErrorReportGenerator()
        result = gen._make_error_user_friendly(
            "Model 'llama3' not found in Ollama"
        )
        assert "model isn't available in Ollama" in result

    def test_no_auth_credentials_replaced(self):
        from local_deep_research.error_handling.report_generator import (
            ErrorReportGenerator,
        )

        gen = ErrorReportGenerator()
        result = gen._make_error_user_friendly("No auth credentials found")
        assert "API key is missing" in result

    def test_readonly_database_replaced(self):
        from local_deep_research.error_handling.report_generator import (
            ErrorReportGenerator,
        )

        gen = ErrorReportGenerator()
        result = gen._make_error_user_friendly(
            "Attempt to write readonly database"
        )
        assert "Permission issue" in result

    def test_no_module_error_replaced(self):
        from local_deep_research.error_handling.report_generator import (
            ErrorReportGenerator,
        )

        gen = ErrorReportGenerator()
        result = gen._make_error_user_friendly(
            "No module named 'local_deep_research'"
        )
        assert "Installation issue" in result

    def test_no_search_results_replaced(self):
        from local_deep_research.error_handling.report_generator import (
            ErrorReportGenerator,
        )

        gen = ErrorReportGenerator()
        result = gen._make_error_user_friendly("No search results found")
        assert "No search results were found" in result

    def test_unknown_error_returns_original(self):
        from local_deep_research.error_handling.report_generator import (
            ErrorReportGenerator,
        )

        gen = ErrorReportGenerator()
        msg = "Some completely unknown error xyz123"
        result = gen._make_error_user_friendly(msg)
        assert result == msg

    def test_case_insensitive_matching(self):
        from local_deep_research.error_handling.report_generator import (
            ErrorReportGenerator,
        )

        gen = ErrorReportGenerator()
        result = gen._make_error_user_friendly("CONNECTION REFUSED [ERRNO 111]")
        assert "Cannot connect" in result

    def test_docker_networking_error_replaced(self):
        from local_deep_research.error_handling.report_generator import (
            ErrorReportGenerator,
        )

        gen = ErrorReportGenerator()
        result = gen._make_error_user_friendly(
            "host localhost Docker container failed"
        )
        assert "Docker networking issue" in result

    def test_context_size_error_replaced(self):
        from local_deep_research.error_handling.report_generator import (
            ErrorReportGenerator,
        )

        gen = ErrorReportGenerator()
        result = gen._make_error_user_friendly(
            "TypeError: Context Size invalid"
        )
        assert "Model configuration issue" in result

    def test_searxng_config_error_replaced(self):
        from local_deep_research.error_handling.report_generator import (
            ErrorReportGenerator,
        )

        gen = ErrorReportGenerator()
        result = gen._make_error_user_friendly("database is locked")
        assert "SearXNG configuration" in result

    def test_replaced_message_includes_technical_error(self):
        """All replaced messages should include the original technical error."""
        from local_deep_research.error_handling.report_generator import (
            ErrorReportGenerator,
        )

        gen = ErrorReportGenerator()
        original = "max_workers must be greater than 0"
        result = gen._make_error_user_friendly(original)
        assert original in result

    def test_model_dump_pattern_replaced(self):
        # Issue #3897: surface a multi-cause "Try this" hint when the agent
        # crashes with `'str' object has no attribute 'model_dump'`. The hint
        # must name proxy/shim, server, and model as possible causes.
        from local_deep_research.error_handling.report_generator import (
            ErrorReportGenerator,
        )

        gen = ErrorReportGenerator()
        result = gen._make_error_user_friendly(
            "Agent error: AttributeError: 'str' object has no attribute 'model_dump'"
        )

        assert "LangChain could not parse" in result
        assert "proxy/shim" in result
        assert "Try this" in result
        assert "issue #3897" in result
        assert "Technical error:" in result

    def test_unrelated_attribute_error_passes_through(self):
        from local_deep_research.error_handling.report_generator import (
            ErrorReportGenerator,
        )

        gen = ErrorReportGenerator()
        msg = "AttributeError: 'NoneType' object has no attribute 'foo'"
        result = gen._make_error_user_friendly(msg)

        # No model_dump match → original message returned verbatim, no hint.
        assert result == msg


class TestFormatPartialResults:
    """Tests for ErrorReportGenerator._format_partial_results() method."""

    def test_none_returns_empty(self):
        from local_deep_research.error_handling.report_generator import (
            ErrorReportGenerator,
        )

        gen = ErrorReportGenerator()
        assert gen._format_partial_results(None) == ""

    def test_empty_dict_returns_empty(self):
        from local_deep_research.error_handling.report_generator import (
            ErrorReportGenerator,
        )

        gen = ErrorReportGenerator()
        assert gen._format_partial_results({}) == ""

    def test_current_knowledge_included(self):
        from local_deep_research.error_handling.report_generator import (
            ErrorReportGenerator,
        )

        gen = ErrorReportGenerator()
        partial = {"current_knowledge": "A" * 100}
        result = gen._format_partial_results(partial)
        assert "Research Summary" in result

    def test_short_knowledge_excluded(self):
        from local_deep_research.error_handling.report_generator import (
            ErrorReportGenerator,
        )

        gen = ErrorReportGenerator()
        partial = {"current_knowledge": "short"}
        result = gen._format_partial_results(partial)
        assert "Research Summary" not in result

    def test_search_results_included(self):
        from local_deep_research.error_handling.report_generator import (
            ErrorReportGenerator,
        )

        gen = ErrorReportGenerator()
        partial = {
            "search_results": [
                {"title": "Result 1", "url": "http://example.com"},
                {"title": "Result 2"},
            ]
        }
        result = gen._format_partial_results(partial)
        assert "Search Results Found" in result
        assert "Result 1" in result

    def test_findings_included(self):
        from local_deep_research.error_handling.report_generator import (
            ErrorReportGenerator,
        )

        gen = ErrorReportGenerator()
        partial = {
            "findings": [
                {"phase": "Phase 1", "content": "Found something important"}
            ]
        }
        result = gen._format_partial_results(partial)
        assert "Research Findings" in result
        assert "Phase 1" in result

    def test_error_findings_excluded(self):
        from local_deep_research.error_handling.report_generator import (
            ErrorReportGenerator,
        )

        gen = ErrorReportGenerator()
        partial = {
            "findings": [
                {"phase": "Phase 1", "content": "Error: something failed"}
            ]
        }
        result = gen._format_partial_results(partial)
        assert "Error: something failed" not in result

    def test_knowledge_truncated_at_1000(self):
        from local_deep_research.error_handling.report_generator import (
            ErrorReportGenerator,
        )

        gen = ErrorReportGenerator()
        partial = {"current_knowledge": "A" * 2000}
        result = gen._format_partial_results(partial)
        assert "..." in result

    def test_max_5_search_results(self):
        from local_deep_research.error_handling.report_generator import (
            ErrorReportGenerator,
        )

        gen = ErrorReportGenerator()
        partial = {
            "search_results": [{"title": f"Result {i}"} for i in range(10)]
        }
        result = gen._format_partial_results(partial)
        assert "Result 4" in result
        assert "Result 5" not in result

    def test_includes_note_about_partial_results(self):
        from local_deep_research.error_handling.report_generator import (
            ErrorReportGenerator,
        )

        gen = ErrorReportGenerator()
        partial = {"current_knowledge": "A" * 100}
        result = gen._format_partial_results(partial)
        assert "before the error occurred" in result


class TestGetTechnicalContext:
    """Tests for ErrorReportGenerator._get_technical_context() method."""

    def test_empty_context(self):
        from local_deep_research.error_handling.report_generator import (
            ErrorReportGenerator,
        )

        gen = ErrorReportGenerator()
        result = gen._get_technical_context({}, None)
        assert result == ""

    def test_includes_start_time(self):
        from local_deep_research.error_handling.report_generator import (
            ErrorReportGenerator,
        )

        gen = ErrorReportGenerator()
        partial = {"start_time": "2024-01-01T00:00:00"}
        result = gen._get_technical_context({}, partial)
        assert "Start Time" in result

    def test_includes_model_info(self):
        from local_deep_research.error_handling.report_generator import (
            ErrorReportGenerator,
        )

        gen = ErrorReportGenerator()
        partial = {
            "model_config": {"model_name": "llama3", "provider": "ollama"}
        }
        result = gen._get_technical_context({}, partial)
        assert "llama3" in result
        assert "ollama" in result

    def test_includes_search_config(self):
        from local_deep_research.error_handling.report_generator import (
            ErrorReportGenerator,
        )

        gen = ErrorReportGenerator()
        partial = {"search_config": {"engine": "searxng", "max_results": 10}}
        result = gen._get_technical_context({}, partial)
        assert "searxng" in result

    def test_includes_status_code(self):
        from local_deep_research.error_handling.report_generator import (
            ErrorReportGenerator,
        )

        gen = ErrorReportGenerator()
        partial = {"status_code": 500}
        result = gen._get_technical_context({}, partial)
        assert "500" in result

    def test_connection_error_category_adds_network_note(self):
        from local_deep_research.error_handling.error_reporter import (
            ErrorCategory,
        )
        from local_deep_research.error_handling.report_generator import (
            ErrorReportGenerator,
        )

        gen = ErrorReportGenerator()
        analysis = {"category": ErrorCategory.CONNECTION_ERROR}
        result = gen._get_technical_context(analysis, None)
        assert "Network Error" in result

    def test_model_error_category_adds_model_note(self):
        from local_deep_research.error_handling.error_reporter import (
            ErrorCategory,
        )
        from local_deep_research.error_handling.report_generator import (
            ErrorReportGenerator,
        )

        gen = ErrorReportGenerator()
        analysis = {"category": ErrorCategory.MODEL_ERROR}
        result = gen._get_technical_context(analysis, None)
        assert "Model Error" in result


class TestGenerateErrorReport:
    """Tests for ErrorReportGenerator.generate_error_report() method."""

    def test_returns_markdown(self):
        from local_deep_research.error_handling.report_generator import (
            ErrorReportGenerator,
        )

        gen = ErrorReportGenerator()
        result = gen.generate_error_report("some error", "test query")
        assert "# " in result

    def test_includes_error_type(self):
        from local_deep_research.error_handling.report_generator import (
            ErrorReportGenerator,
        )

        gen = ErrorReportGenerator()
        result = gen.generate_error_report("Connection refused", "test query")
        assert "Error Type" in result

    def test_includes_what_happened(self):
        from local_deep_research.error_handling.report_generator import (
            ErrorReportGenerator,
        )

        gen = ErrorReportGenerator()
        result = gen.generate_error_report("some error", "test query")
        assert "What happened" in result

    def test_includes_help_section(self):
        from local_deep_research.error_handling.report_generator import (
            ErrorReportGenerator,
        )

        gen = ErrorReportGenerator()
        result = gen.generate_error_report("some error", "test query")
        assert "Get Help" in result
        assert "Discord" in result
        assert "GitHub Issues" in result
