"""
HTTP security tests for settings routes.

Existing unit tests cover corrupted value detection at the function level,
but not via HTTP endpoints. This file tests the save_all_settings endpoint
end-to-end.

Source: src/local_deep_research/web/routes/settings_routes.py
"""

from contextlib import contextmanager
from unittest.mock import Mock, patch

from flask import Flask, jsonify

from local_deep_research.web.auth.routes import auth_bp
from local_deep_research.web.routes.settings_routes import settings_bp


# ---------------------------------------------------------------------------
# Test Infrastructure
# ---------------------------------------------------------------------------


def _create_test_app():
    app = Flask(__name__)
    app.config["SECRET_KEY"] = "test-secret"
    app.config["WTF_CSRF_ENABLED"] = False
    app.register_blueprint(auth_bp)
    app.register_blueprint(settings_bp)

    @app.errorhandler(500)
    def _handle_500(error):
        return jsonify({"error": "Internal server error"}), 500

    return app


@contextmanager
def _authenticated_client(app, mock_settings=None):
    """Provide test client with mocked auth and DB session for settings routes."""
    mock_db = Mock()
    mock_db.connections = {"testuser": True}
    mock_db.has_encryption = False

    # Build mock db session with Setting query
    mock_setting_obj = Mock()
    mock_setting_obj.key = "llm.temperature"
    mock_setting_obj.value = "0.7"
    mock_setting_obj.editable = True
    mock_setting_obj.ui_element = "number"

    _mock_query = Mock()
    _mock_query.all.return_value = mock_settings or [mock_setting_obj]
    _mock_query.first.return_value = None
    _mock_query.filter_by.return_value = _mock_query
    _mock_query.filter.return_value = _mock_query

    _mock_db_session = Mock()
    _mock_db_session.query.return_value = _mock_query

    @contextmanager
    def _fake_session(*args, **kwargs):
        yield _mock_db_session

    _routes_mod = "local_deep_research.web.routes.settings_routes"
    _decorator_mod = "local_deep_research.web.utils.route_decorators"

    patches = [
        patch("local_deep_research.web.auth.decorators.db_manager", mock_db),
        patch(
            f"{_decorator_mod}.get_user_db_session", side_effect=_fake_session
        ),
        patch(
            f"{_routes_mod}.settings_limit", lambda f: f
        ),  # disable rate limit
    ]

    started = []
    try:
        for p in patches:
            started.append(p.start())
        with app.test_client() as client:
            with client.session_transaction() as sess:
                sess["username"] = "testuser"
                sess["session_id"] = "test-session-id"
            yield client, _mock_db_session
    finally:
        for p in patches:
            p.stop()


# ---------------------------------------------------------------------------
# Corrupted value auto-correction via HTTP
# ---------------------------------------------------------------------------


class TestSaveAllSettingsValidation:
    """Additional HTTP tests for save_all_settings endpoint."""

    def test_empty_json_body_returns_400(self):
        """POST with empty JSON object triggers 'No settings data provided'."""
        app = _create_test_app()
        with _authenticated_client(app) as (client, _):
            resp = client.post(
                "/settings/save_all_settings",
                json={},
                content_type="application/json",
            )
            # Empty dict is falsy, so save_all_settings returns 400
            assert resp.status_code == 400
            data = resp.get_json()
            assert data["status"] == "error"
            assert "No settings data" in data["message"]
