"""
Extended tests for news/flask_api.py

Tests cover:
- safe_error_message() helper
- get_user_id() helper
- Flask route handlers with mocking
- Error handling and response codes
- Request validation
"""

import pytest
from unittest.mock import patch
from flask import Flask


@pytest.fixture
def flask_app():
    """Create a Flask app for testing."""
    app = Flask(__name__)
    app.config["TESTING"] = True
    return app


class TestSafeErrorMessage:
    """Tests for safe_error_message() helper."""

    def test_returns_string(self):
        """Returns a string."""
        from local_deep_research.news.flask_api import safe_error_message

        result = safe_error_message(Exception("test"))

        assert isinstance(result, str)

    def test_handles_value_error(self):
        """Returns 'Invalid input provided' for ValueError."""
        from local_deep_research.news.flask_api import safe_error_message

        result = safe_error_message(ValueError("bad value"))

        assert result == "Invalid input provided"

    def test_handles_key_error(self):
        """Returns 'Required data missing' for KeyError."""
        from local_deep_research.news.flask_api import safe_error_message

        result = safe_error_message(KeyError("missing_key"))

        assert result == "Required data missing"

    def test_handles_type_error(self):
        """Returns 'Invalid data format' for TypeError."""
        from local_deep_research.news.flask_api import safe_error_message

        result = safe_error_message(TypeError("wrong type"))

        assert result == "Invalid data format"

    def test_handles_generic_exception(self):
        """Returns generic message for other exceptions."""
        from local_deep_research.news.flask_api import safe_error_message

        result = safe_error_message(Exception("unknown error"))

        assert "error occurred" in result.lower()

    def test_includes_context_in_message(self):
        """Includes context in error message."""
        from local_deep_research.news.flask_api import safe_error_message

        result = safe_error_message(Exception("error"), context="testing")

        assert "testing" in result

    def test_handles_none_exception(self):
        """Handles None-like exception gracefully."""
        from local_deep_research.news.flask_api import safe_error_message

        result = safe_error_message(Exception(""))

        assert isinstance(result, str)

    def test_empty_context(self):
        """Handles empty context string."""
        from local_deep_research.news.flask_api import safe_error_message

        result = safe_error_message(Exception("error"), context="")

        assert isinstance(result, str)


class TestGetUserId:
    """Tests for get_user_id() helper."""

    def test_function_exists(self):
        """get_user_id function exists."""
        from local_deep_research.news.flask_api import get_user_id

        assert callable(get_user_id)

    def test_returns_none_when_no_current_user(self):
        """Returns None when current_user returns None."""
        # Create app context for the import inside get_user_id
        app = Flask(__name__)
        with app.app_context():
            with patch(
                "local_deep_research.web.auth.decorators.current_user"
            ) as mock_current:
                mock_current.return_value = None

                from local_deep_research.news.flask_api import get_user_id

                result = get_user_id()

                assert result is None

    def test_returns_username_when_user_exists(self):
        """Returns username when current_user returns a username."""
        app = Flask(__name__)
        with app.app_context():
            with patch(
                "local_deep_research.web.auth.decorators.current_user"
            ) as mock_current:
                mock_current.return_value = "testuser"

                from local_deep_research.news.flask_api import get_user_id

                result = get_user_id()

                assert result == "testuser"


class TestNewsBlueprintExists:
    """Tests for news_api_bp Blueprint."""

    def test_blueprint_name(self):
        """Blueprint name is 'news_api'."""
        from local_deep_research.news.flask_api import news_api_bp

        assert news_api_bp.name == "news_api"

    def test_blueprint_url_prefix(self):
        """Blueprint has /api url_prefix."""
        from local_deep_research.news.flask_api import news_api_bp

        assert news_api_bp.url_prefix == "/api"


class TestFeedRouteValidation:
    """Tests for /feed route validation."""

    def test_feed_route_function_exists(self):
        """get_news_feed function exists."""
        from local_deep_research.news.flask_api import get_news_feed

        assert callable(get_news_feed)


class TestErrorHandlers:
    """Tests for error handler functions."""

    def test_bad_request_handler_exists(self):
        """400 error handler is defined."""
        app = Flask(__name__)
        with app.app_context():
            from local_deep_research.news.flask_api import bad_request

            result = bad_request(Exception("test"))

            assert result[1] == 400

    def test_not_found_handler_exists(self):
        """404 error handler is defined."""
        app = Flask(__name__)
        with app.app_context():
            from local_deep_research.news.flask_api import not_found

            result = not_found(Exception("test"))

            assert result[1] == 404

    def test_internal_error_handler_exists(self):
        """500 error handler is defined."""
        app = Flask(__name__)
        with app.app_context():
            from local_deep_research.news.flask_api import internal_error

            result = internal_error(Exception("test"))

            assert result[1] == 500

    def test_bad_request_returns_json(self):
        """400 error handler returns JSON."""
        app = Flask(__name__)
        with app.app_context():
            from local_deep_research.news.flask_api import bad_request

            result = bad_request(Exception("test"))

            # Result is tuple (response, status_code)
            assert "error" in result[0].get_json()

    def test_not_found_returns_json(self):
        """404 error handler returns JSON."""
        app = Flask(__name__)
        with app.app_context():
            from local_deep_research.news.flask_api import not_found

            result = not_found(Exception("test"))

            assert "error" in result[0].get_json()

    def test_internal_error_returns_json(self):
        """500 error handler returns JSON."""
        app = Flask(__name__)
        with app.app_context():
            from local_deep_research.news.flask_api import internal_error

            result = internal_error(Exception("test"))

            assert "error" in result[0].get_json()


class TestSafeErrorMessageExtended:
    """Extended tests for safe_error_message() helper."""

    def test_attribute_error_returns_generic(self):
        """Returns generic message for AttributeError."""
        from local_deep_research.news.flask_api import safe_error_message

        result = safe_error_message(AttributeError("missing attr"))

        assert "error occurred" in result.lower()

    def test_index_error_returns_generic(self):
        """Returns generic message for IndexError."""
        from local_deep_research.news.flask_api import safe_error_message

        result = safe_error_message(IndexError("list index out of range"))

        assert "error occurred" in result.lower()

    def test_runtime_error_returns_generic(self):
        """Returns generic message for RuntimeError."""
        from local_deep_research.news.flask_api import safe_error_message

        result = safe_error_message(RuntimeError("runtime issue"))

        assert "error occurred" in result.lower()

    def test_context_with_special_characters(self):
        """Handles context with special characters."""
        from local_deep_research.news.flask_api import safe_error_message

        result = safe_error_message(Exception("error"), context="test <>&\"'")

        assert isinstance(result, str)

    def test_long_context_string(self):
        """Handles long context string."""
        from local_deep_research.news.flask_api import safe_error_message

        long_context = "x" * 1000
        result = safe_error_message(Exception("error"), context=long_context)

        assert isinstance(result, str)

    def test_unicode_context(self):
        """Handles unicode in context."""
        from local_deep_research.news.flask_api import safe_error_message

        result = safe_error_message(Exception("error"), context="日本語")

        assert isinstance(result, str)


class TestBlueprintConfiguration:
    """Tests for Blueprint configuration."""

    def test_blueprint_has_routes_registered(self):
        """Blueprint has routes registered."""
        from local_deep_research.news.flask_api import news_api_bp

        # Blueprint should have deferred functions
        assert len(news_api_bp.deferred_functions) > 0

    def test_blueprint_is_flask_blueprint(self):
        """Blueprint is a Flask Blueprint instance."""
        from local_deep_research.news.flask_api import news_api_bp
        from flask import Blueprint

        assert isinstance(news_api_bp, Blueprint)


class TestErrorHandlerMessages:
    """Tests for error handler message content."""

    def test_bad_request_message_content(self):
        """400 handler returns 'Bad request' message."""
        app = Flask(__name__)
        with app.app_context():
            from local_deep_research.news.flask_api import bad_request

            result = bad_request(Exception("test"))
            json_data = result[0].get_json()

            assert json_data["error"] == "Bad request"

    def test_not_found_message_content(self):
        """404 handler returns 'Resource not found' message."""
        app = Flask(__name__)
        with app.app_context():
            from local_deep_research.news.flask_api import not_found

            result = not_found(Exception("test"))
            json_data = result[0].get_json()

            assert json_data["error"] == "Resource not found"

    def test_internal_error_message_content(self):
        """500 handler returns 'Internal server error' message."""
        app = Flask(__name__)
        with app.app_context():
            from local_deep_research.news.flask_api import internal_error

            result = internal_error(Exception("test"))
            json_data = result[0].get_json()

            assert json_data["error"] == "Internal server error"
