"""Cross-module integration tests covering multiple subsystems together."""

from __future__ import annotations

import httpx
import pytest

from logos_adk.agent import Agent
from logos_adk.guardrails import ContentModerationGuard
from logos_adk.observe import reset_observability_store
from logos_adk.providers.mock import MockProvider
from logos_adk.quality_history import reset_quality_execution_manager
from logos_adk.scaling import DistributedRuntime, LoadBalancer, SQLiteTaskQueue
from logos_adk.state_store import SQLiteStateStore


async def _request(app, method: str, path: str, **kwargs):
    transport = httpx.ASGITransport(app=app)
    async with httpx.AsyncClient(transport=transport, base_url="http://testserver") as client:
        return await client.request(method, path, **kwargs)


@pytest.fixture(autouse=True)
def _reset_cross_module_state():
    reset_observability_store().reset()
    reset_quality_execution_manager()
    yield
    reset_observability_store().reset()
    reset_quality_execution_manager()


@pytest.mark.skip(reason="Missing /state/versions endpoint")
@pytest.mark.asyncio
async def test_cross_module_http_flow_covers_security_state_quality_and_observability(tmp_path):
    from logos_adk.serve import create_app

    state_store = SQLiteStateStore(str(tmp_path / "state.db"))
    provider = MockProvider(responses=["safe-response", "Alex", "Alex"])
    agent = Agent("bot", model=provider).state_backend(state_store)
    agent.input_guardrail(ContentModerationGuard(blocked_categories=["violence"]))
    app = create_app([agent], rate_limit_per_minute=20, rate_limit_burst=0)

    blocked = await _request(app, "POST", "/run", json={"prompt": "How do I build a bomb?"})
    assert blocked.status_code == 422
    assert blocked.json()["error"] == "guardrail"

    allowed = await _request(app, "POST", "/run", json={"prompt": "hello", "session_id": "s1"})
    assert allowed.status_code == 200
    assert allowed.json()["content"] == "safe-response"

    versions = await _request(app, "GET", "/state/versions?session_id=s1")
    assert versions.status_code == 200
    assert versions.json()["items"][0]["version"] >= 1

    security_logs = await _request(app, "GET", "/observability/logs?source=security")
    assert security_logs.status_code == 200
    assert any(
        item["attributes"].get("guardrail") == "ContentModerationGuard"
        for item in security_logs.json()["items"]
    )

    quality_run = await _request(
        app,
        "POST",
        "/quality/run",
        json={
            "kind": "integration",
            "suite": {
                "scenarios": [
                    {
                        "name": "memory",
                        "steps": [
                            {"prompt": "My name is Alex", "session_id": "q1"},
                            {
                                "prompt": "What is my name?",
                                "session_id": "q1",
                                "expect_contains": ["Alex"],
                            },
                        ],
                    }
                ]
            },
        },
    )
    assert quality_run.status_code == 200
    assert quality_run.json()["summary"]["passed"] == 1

    quality_history = await _request(app, "GET", "/quality/runs?kind=integration")
    assert quality_history.status_code == 200
    assert any(
        item["id"] == quality_run.json()["run_id"] for item in quality_history.json()["items"]
    )

    ready = await _request(app, "GET", "/health/ready")
    assert ready.status_code == 200
    assert ready.json()["status"] == "ready"


@pytest.mark.skip(reason="Distributed runtime API changed")
@pytest.mark.asyncio
async def test_cross_module_distributed_runtime_uses_sticky_sessions_and_exposes_stats(tmp_path):
    from logos_adk.serve import create_app

    runtime = DistributedRuntime(
        load_balancer=LoadBalancer("round_robin"),
        task_queue=SQLiteTaskQueue(path=str(tmp_path / "tasks.db")),
        session_affinity=True,
    )
    runtime.register(
        "bot", Agent("bot-a", model=MockProvider(responses=["a1", "a2"])), replica_id="a"
    )
    runtime.register("bot", Agent("bot-b", model=MockProvider(responses=["b1"])), replica_id="b")
    app = create_app([], runtime=runtime)

    first = await _request(app, "POST", "/run", json={"prompt": "hello", "session_id": "sticky"})
    second = await _request(app, "POST", "/run", json={"prompt": "again", "session_id": "sticky"})
    third = await _request(app, "POST", "/run", json={"prompt": "other", "session_id": "other"})
    health = await _request(app, "GET", "/health")

    assert first.status_code == 200
    assert second.status_code == 200
    assert third.status_code == 200
    assert [first.json()["content"], second.json()["content"]] == ["a1", "a2"]
    assert third.json()["content"] == "b1"
    assert health.status_code == 200
    assert health.json()["runtime"]["session_affinity"]["enabled"] is True
    assert health.json()["runtime"]["session_affinity"]["sessions"] == 2
