"""Tests for the EU AI Act assessment API."""

from __future__ import annotations

import pytest


@pytest.fixture()
def client():
    """Create a test client for the assessment API."""
    import httpx
    from httpx import ASGITransport

    from acgs_lite.assess_api import create_assess_app

    app = create_assess_app()
    transport = ASGITransport(app=app)
    return httpx.AsyncClient(transport=transport, base_url="http://test")


VALID_PAYLOAD = {
    "system_type": "chatbot",
    "deployment_region": "eu",
    "system_description": "A customer support chatbot that answers questions about product returns.",
    "data_categories": ["personal_data"],
    "human_oversight_level": "partial",
    "employment": False,
    "law_enforcement": False,
    "biometric_processing": False,
    "social_scoring": False,
    "education": False,
}


@pytest.mark.asyncio
async def test_health(client):
    """Health endpoint returns ok."""
    async with client as c:
        resp = await c.get("/api/health")
    assert resp.status_code == 200
    data = resp.json()
    assert data["status"] == "ok"
    assert "version" in data


@pytest.mark.asyncio
async def test_valid_assessment(client):
    """Valid input produces a complete assessment response."""
    async with client as c:
        resp = await c.post("/api/assess", json=VALID_PAYLOAD)
    assert resp.status_code == 200
    data = resp.json()
    assert "risk_level" in data
    assert "top_gaps" in data
    assert isinstance(data["top_gaps"], list)
    assert "compliance_score" in data
    assert 0.0 <= data["compliance_score"] <= 1.0
    assert "framework_scores" in data
    assert isinstance(data["framework_scores"], dict)
    assert "pdf_base64" in data
    assert len(data["pdf_base64"]) > 100  # non-trivial PDF
    assert "disclaimer" in data


@pytest.mark.asyncio
async def test_missing_required_fields(client):
    """Missing required fields return 422."""
    async with client as c:
        resp = await c.post("/api/assess", json={})
    assert resp.status_code == 422


@pytest.mark.asyncio
async def test_oversized_description(client):
    """Description over 10K characters returns 422."""
    payload = {**VALID_PAYLOAD, "system_description": "x" * 10_001}
    async with client as c:
        resp = await c.post("/api/assess", json=payload)
    assert resp.status_code == 422


@pytest.mark.asyncio
async def test_invalid_system_type(client):
    """Invalid system_type returns 422."""
    payload = {**VALID_PAYLOAD, "system_type": "invalid_type"}
    async with client as c:
        resp = await c.post("/api/assess", json=payload)
    assert resp.status_code == 422


@pytest.mark.asyncio
async def test_eu_only_frameworks(client):
    """Assessment with EU jurisdiction uses EU-relevant frameworks."""
    async with client as c:
        resp = await c.post("/api/assess", json=VALID_PAYLOAD)
    assert resp.status_code == 200
    data = resp.json()
    fw_keys = set(data["framework_scores"].keys())
    # Should include EU-relevant frameworks, not US-only ones
    us_only = {"us_fair_lending", "nyc_ll144", "ccpa_cpra"}
    assert not fw_keys.intersection(us_only), f"US-only frameworks found: {fw_keys & us_only}"


@pytest.mark.asyncio
async def test_high_risk_flags(client):
    """Employment flag triggers high-risk classification."""
    payload = {**VALID_PAYLOAD, "system_type": "hiring_hr", "employment": True}
    async with client as c:
        resp = await c.post("/api/assess", json=payload)
    assert resp.status_code == 200
    data = resp.json()
    assert "high" in data["risk_level"].lower()


@pytest.mark.asyncio
async def test_rate_limit(client):
    """Rate limiting kicks in after 5 requests."""
    from acgs_lite.assess_api import _request_log

    # Clear any existing rate limit state
    _request_log.clear()

    async with client as c:
        for i in range(5):
            resp = await c.post("/api/assess", json=VALID_PAYLOAD)
            assert resp.status_code == 200, f"Request {i + 1} failed: {resp.status_code}"

        # 6th request should be rate-limited
        resp = await c.post("/api/assess", json=VALID_PAYLOAD)
        assert resp.status_code == 429
