"""
Integration tests for Middleware module
Tests middleware functionality and registration

Auto-generated by RapidKit - Middleware Module
Framework: {{ framework }}
"""

import pytest
from unittest.mock import MagicMock

try:
    from fastapi import FastAPI, status
    from fastapi.testclient import TestClient
except (RuntimeError, ModuleNotFoundError) as exc:  # pragma: no cover - optional dependency
    message = str(exc).lower()
    missing_name = getattr(exc, "name", "")
    if "httpx" in message or missing_name == "httpx":
        pytest.skip("httpx is required for FastAPI TestClient", allow_module_level=True)
    raise


pytestmark = [pytest.mark.integration, pytest.mark.template_integration]


def test_imports():
    """Test that middleware module imports work"""
    from src.modules.free.essentials.middleware.middleware import (
        ProcessTimeMiddleware,
        ServiceHeaderMiddleware,
        build_default_config,
        register_middleware,
        register_middleware_factory,
    )

    assert ProcessTimeMiddleware is not None
    assert ServiceHeaderMiddleware is not None
    assert register_middleware is not None
    assert build_default_config() is not None
    assert callable(register_middleware_factory)


def test_process_time_middleware_exists():
    """Test ProcessTimeMiddleware class is available"""
    from src.modules.free.essentials.middleware.middleware import ProcessTimeMiddleware
    from starlette.middleware.base import BaseHTTPMiddleware

    assert issubclass(ProcessTimeMiddleware, BaseHTTPMiddleware)


def test_service_header_middleware_exists():
    """Test ServiceHeaderMiddleware class is available"""
    from src.modules.free.essentials.middleware.middleware import ServiceHeaderMiddleware
    from starlette.middleware.base import BaseHTTPMiddleware

    assert issubclass(ServiceHeaderMiddleware, BaseHTTPMiddleware)


@pytest.mark.asyncio
async def test_process_time_middleware_adds_header():
    """Test that ProcessTimeMiddleware adds X-Process-Time header"""
    from src.modules.free.essentials.middleware.middleware import ProcessTimeMiddleware
    from starlette.requests import Request
    from starlette.responses import Response

    # Create mock app and request
    app = MagicMock()
    middleware = ProcessTimeMiddleware(app)

    # Mock request and response
    request = MagicMock(spec=Request)
    response = Response(content="test", status_code=status.HTTP_200_OK)

    # Mock call_next to return our response
    async def mock_call_next(req):
        return response

    # Execute middleware
    result = await middleware.dispatch(request, mock_call_next)

    # Verify X-Process-Time header was added
    assert "X-Process-Time" in result.headers
    assert isinstance(float(result.headers["X-Process-Time"]), float)


@pytest.mark.asyncio
async def test_service_header_middleware_adds_header():
    """Test that ServiceHeaderMiddleware adds X-Service header"""
    from src.modules.free.essentials.middleware.middleware import ServiceHeaderMiddleware
    from starlette.requests import Request
    from starlette.responses import Response
    from fastapi import FastAPI

    # Create app with title
    app = FastAPI(title="Test Service")
    middleware = ServiceHeaderMiddleware(app, service_name="Test Service")

    # Mock request and response
    request = MagicMock(spec=Request)
    response = Response(content="test", status_code=status.HTTP_200_OK)

    # Mock call_next
    async def mock_call_next(req):
        return response

    # Execute middleware
    result = await middleware.dispatch(request, mock_call_next)

    # Verify X-Service header was added
    assert "X-Service" in result.headers
    assert result.headers["X-Service"] == "Test Service"


def test_register_middleware_function():
    """Test register_middleware function exists and is callable"""
    from src.modules.free.essentials.middleware.middleware import register_middleware
    from fastapi import FastAPI

    app = FastAPI(title="Test App")

    # Should not raise any errors
    register_middleware(app)

    # Verify middleware was added
    assert len(app.user_middleware) > 0


def test_middleware_registration_order():
    """Test that middleware is registered in correct order"""
    from src.modules.free.essentials.middleware.middleware import register_middleware
    from fastapi import FastAPI

    app = FastAPI(title="Test App")
    initial_middleware_count = len(app.user_middleware)

    register_middleware(app)

    # At least 2 middleware should be added (ProcessTime + ServiceHeader)
    assert len(app.user_middleware) >= initial_middleware_count + 2


def test_register_middleware_health_route():
    """Test that middleware health route registers and responds."""
    from src.health.middleware import register_middleware_health
    from fastapi import FastAPI
    from fastapi.testclient import TestClient

    app = FastAPI(title="Health Test")
    register_middleware_health(app)

    client = TestClient(app)
    response = client.get("/api/health/module/middleware")

    assert response.status_code == status.HTTP_200_OK
    payload = response.json()
    assert payload.get("status") == "ok"
    assert payload.get("module") == "{{ rapidkit_vendor_module }}"


@pytest.mark.asyncio
async def test_middleware_chain_execution():
    """Test that multiple middleware execute in correct order"""
    from src.modules.free.essentials.middleware.middleware import register_middleware
    from fastapi import FastAPI
    from fastapi.testclient import TestClient

    app = FastAPI(title="Middleware Test")

    @app.get("/test")
    def test_endpoint():
        return {"status": "ok"}

    # Register middleware
    register_middleware(app)

    # Create test client
    client = TestClient(app)

    # Make request
    response = client.get("/test")

    # Verify response
    assert response.status_code == status.HTTP_200_OK

    # Verify headers from middleware
    assert "X-Process-Time" in response.headers
    assert "X-Service" in response.headers
    assert "X-Custom-Header" in response.headers


def test_service_header_middleware_custom_name():
    """Test ServiceHeaderMiddleware with custom service name"""
    from src.modules.free.essentials.middleware.middleware import ServiceHeaderMiddleware
    from fastapi import FastAPI

    app = FastAPI(title="Default Title")
    middleware = ServiceHeaderMiddleware(app, service_name="Custom Service")

    assert middleware.service_name == "Custom Service"


def test_service_header_middleware_default_name():
    """Test ServiceHeaderMiddleware with default service name from app"""
    from src.modules.free.essentials.middleware.middleware import ServiceHeaderMiddleware
    from fastapi import FastAPI

    app = FastAPI(title="App Title")
    middleware = ServiceHeaderMiddleware(app)

    assert middleware.service_name == "App Title"


@pytest.mark.asyncio
async def test_middleware_error_handling():
    """Test middleware behavior when endpoint raises error"""
    from src.modules.free.essentials.middleware.middleware import ProcessTimeMiddleware
    from starlette.requests import Request
    from starlette.responses import Response

    app = MagicMock()
    middleware = ProcessTimeMiddleware(app)

    request = MagicMock(spec=Request)

    # Mock call_next that raises error
    async def mock_call_next_error(req):
        raise ValueError("Test error")

    # Middleware should propagate the error
    with pytest.raises(ValueError, match="Test error"):
        await middleware.dispatch(request, mock_call_next_error)


def test_cors_middleware_optional_toggle():
    """CORS middleware should activate when the configuration enables it."""
    from src.modules.free.essentials.middleware.middleware import build_default_config, register_middleware
    from fastapi import FastAPI
    from starlette.middleware.cors import CORSMiddleware

    app = FastAPI(title="CORS Test")
    config = build_default_config()
    config.cors_enabled = True
    config.cors_allow_origins = ["https://example.com"]

    register_middleware(app, config)

    cors_middlewares = [m for m in app.user_middleware if m.cls is CORSMiddleware]
    assert cors_middlewares, "Expected CORSMiddleware to be registered when enabled"


@pytest.mark.asyncio
async def test_custom_header_middleware():
    """Test custom header middleware decorator"""
    from src.modules.free.essentials.middleware.middleware import register_middleware
    from fastapi import FastAPI
    from fastapi.testclient import TestClient

    app = FastAPI(title="Custom Header Test")

    @app.get("/custom")
    def custom_endpoint():
        return {"data": "test"}

    register_middleware(app)

    client = TestClient(app)
    response = client.get("/custom")

    assert "X-Custom-Header" in response.headers
    assert response.headers["X-Custom-Header"] == "RapidKit"


def test_register_middleware_factory_hook():
    from src.modules.free.essentials.middleware.middleware import (
        MiddlewareFactory,
        register_middleware,
        register_middleware_factory,
    )
    from fastapi import FastAPI

    calls: list[str] = []

    def sample_factory(app: FastAPI, config):
        calls.append(app.title)

    register_middleware_factory(sample_factory)

    app = FastAPI(title="Factory Hook Test")
    register_middleware(app)

    assert calls == ["Factory Hook Test"]
