# #region Test.AppModule.Handlers [C:3] [TYPE Module] [SEMANTICS test,app,handlers,exceptions]
# @BRIEF Tests for app.py — global_exception_handler, network_error_handler.
# @RELATION BINDS_TO -> [AppModule]
# @TEST_EDGE: unhandled_exception -> returns 500 JSON with path
# @TEST_EDGE: network_error -> returns 503
# @TEST_INVARIANT: every_500_logged -> VERIFIED_BY: test_global_exception_handler_logs_and_returns_500

from pathlib import Path
import sys
import json

sys.path.insert(0, str(Path(__file__).parent.parent / "src"))

import pytest
from unittest.mock import MagicMock
from fastapi import Request, HTTPException
from fastapi.responses import JSONResponse


# #region _make_mock_request [C:1] [TYPE Function]
def _make_mock_request(method="GET", path="/api/test", client_host="127.0.0.1"):
    req = MagicMock(spec=Request)
    req.method = method
    req.url = MagicMock()
    req.url.path = path
    req.client = MagicMock()
    req.client.host = client_host
    req.query_params = {}
    return req
# #endregion _make_mock_request


class TestExceptionHandlers:
    """global_exception_handler and network_error_handler."""

    # #region test_global_handler_500 [C:2] [TYPE Function]
    @pytest.mark.asyncio
    async def test_global_handler_500(self):
        from src.app import global_exception_handler
        request = _make_mock_request(method="POST", path="/api/break")
        response = await global_exception_handler(request, ValueError("broke"))
        assert isinstance(response, JSONResponse)
        assert response.status_code == 500
        body = json.loads(response.body)
        assert body["detail"] == "Internal server error"
        assert body["path"] == "/api/break"
    # #endregion test_global_handler_500

    # #region test_global_handler_unknown_client [C:2] [TYPE Function]
    @pytest.mark.asyncio
    async def test_global_handler_unknown_client(self):
        from src.app import global_exception_handler
        req = _make_mock_request()
        req.client = None
        response = await global_exception_handler(req, RuntimeError("no client"))
        assert response.status_code == 500
    # #endregion test_global_handler_unknown_client

    # #region test_network_error_handler [C:2] [TYPE Function]
    @pytest.mark.asyncio
    async def test_network_error_handler(self):
        from src.app import network_error_handler
        from src.core.utils.network import NetworkError
        request = _make_mock_request()
        response = await network_error_handler(request, NetworkError("down"))
        assert isinstance(response, HTTPException)
        assert response.status_code == 503
        assert "Environment unavailable" in response.detail
    # #endregion test_network_error_handler

    # #region test_global_handler_with_query_params [C:2] [TYPE Function]
    @pytest.mark.asyncio
    async def test_global_handler_with_query_params(self):
        from src.app import global_exception_handler
        req = _make_mock_request()
        req.query_params = {"env_id": "prod"}
        response = await global_exception_handler(req, Exception("test"))
        assert response.status_code == 500
    # #endregion test_global_handler_with_query_params

    # #region test_internal_server_error_returns_json [C:2] [TYPE Function]
    @pytest.mark.asyncio
    async def test_internal_server_error_returns_json(self):
        from src.app import global_exception_handler
        request = _make_mock_request(method="POST", path="/api/crash")
        response = await global_exception_handler(request, RuntimeError("crash"))
        assert response.status_code == 500
        body = json.loads(response.body)
        assert body["path"] == "/api/crash"
    # #endregion test_internal_server_error_returns_json
# #endregion Test.AppModule.Handlers
