"""Tests for Interpretation-in-Map (step 5).

Acceptance: a customer interpretation is judged against the existing map, using
only assess_interpretation; affected regulations/obligations are referenced from
the map; unsupported domains (wastewater/chemicals) are flagged
future_corpus_needed, not pseudo-evaluated; output is customer-readable.
"""

from __future__ import annotations

import pytest
from fastapi import FastAPI
from fastapi.testclient import TestClient

from compliance.interpretation_map import interpret_in_map
from compliance.profile.canonical import (
    CanonicalLifecyclePhase,
    CanonicalProductRegulatoryProfile,
    CanonicalProductType,
    EconomicOperatorRole,
    EnvironmentalImpact,
)
from compliance.reasoning.enums import InterpretationVerdict
from compliance.reasoning.interpretation_engine import assess_interpretation
from compliance.regulatory_map import render_regulatory_map


def ready_profile(**ov) -> CanonicalProductRegulatoryProfile:
    base = dict(
        name="Industriespülmaschine",
        product_type=CanonicalProductType.MACHINERY,
        markets=["EU", "DE"],
        economic_operator_role=EconomicOperatorRole.MANUFACTURER,
        lifecycle_phase=CanonicalLifecyclePhase.PLACING_ON_MARKET,
        is_machine=True,
        is_component=False,
        has_software_updates=True,
        has_embedded_software=True,
        has_remote_access=True,
        technologies=["cloud", "ota_updates"],
    )
    base.update(ov)
    return CanonicalProductRegulatoryProfile(**base)


def _map(**ov):
    return render_regulatory_map(ready_profile(**ov))


# 1 + 2. evaluated against the map, using ONLY assess_interpretation.
def test_uses_assess_interpretation_verdict():
    text = "Wir glauben, der CRA gilt nur für neue Produkte."
    result = interpret_in_map(_map(), text)
    assert result.assessment == assess_interpretation(text).assessment == InterpretationVerdict.TOO_NARROW
    assert "CRA" in result.affected_regulations  # CRA is in the map
    assert result.in_scope_of_map is True


# 3. the six verdict values pass through unchanged.
def test_verdict_values():
    m = _map()
    assert interpret_in_map(m, "CRA gilt nur für neue Produkte.").assessment == InterpretationVerdict.TOO_NARROW
    assert interpret_in_map(m, "Open Source ist ausgenommen, also betrifft uns der CRA nicht.").assessment == InterpretationVerdict.PARTIALLY_CORRECT
    assert interpret_in_map(m, "Der Mond beeinflusst unsere Updatezyklen.").assessment == InterpretationVerdict.UNCERTAIN


# 4. affected regulations/obligations are referenced FROM the map.
def test_affected_refs_from_map():
    m = _map()
    result = interpret_in_map(m, "Eine SBOM reicht, dann sind wir fertig.")
    map_ob_ids = {o.obligation_id for v in m.applicable_regulations for o in v.obligations}
    map_reg_ids = {v.regulation_id for v in m.applicable_regulations} | {v.regulation_id for v in m.uncertain_regulations}
    assert "sbom_creation" in result.affected_obligations
    assert set(result.affected_obligations) <= map_ob_ids
    assert set(result.affected_regulations) <= map_reg_ids


# 5. environmental aspects are NOT pseudo-evaluated.
def test_environmental_not_pseudo_evaluated():
    m = _map(environmental=EnvironmentalImpact(discharges_to_wastewater=True))
    result = interpret_in_map(m, "Beim Abwasser sind wir nicht betroffen, das spielt für uns keine Rolle.")
    domains = {d.domain for d in result.future_corpus_domains}
    assert "environment_water" in domains
    assert "future_corpus_needed" in result.explanation


# 6. output is customer-readable.
def test_customer_readable():
    result = interpret_in_map(_map(), "Der CRA gilt nur für neue Produkte.")
    assert "zu eng" in result.explanation
    assert result.explanation.startswith("Ihre Interpretation ist wahrscheinlich")


# affected refs never leave the map (no abstract legal questions).
def test_affected_regs_never_outside_map():
    m = _map()
    map_reg_ids = (
        {v.regulation_id for v in m.applicable_regulations}
        | {v.regulation_id for v in m.uncertain_regulations}
        | {v.regulation_id for v in m.excluded_regulations}
    )
    for text in ["CRA gilt nur für neue Produkte.", "Ohne Funkmodul keine Cyber-Pflichten.", "SBOM reicht."]:
        result = interpret_in_map(m, text)
        assert set(result.affected_regulations) <= map_reg_ids


# endpoint smoke.
@pytest.fixture(scope="module")
def client():
    from compliance.api.reasoning_routes import router

    app = FastAPI()
    app.include_router(router)
    return TestClient(app)


def test_endpoint_interpretation_in_map(client):
    r = client.post(
        "/reasoning/interpretation-in-map",
        json={
            "product_profile": {
                "name": "M",
                "product_type": "machinery",
                "markets": ["EU"],
                "economic_operator_role": "manufacturer",
                "lifecycle_phase": "placing_on_market",
                "is_machine": True,
                "is_component": False,
                "has_software_updates": True,
                "has_embedded_software": True,
                "has_remote_access": True,
                "technologies": ["cloud"],
            },
            "customer_interpretation": "Der CRA gilt nur für neue Produkte.",
        },
    )
    assert r.status_code == 200
    body = r.json()
    assert body["assessment"] == "too_narrow"
    assert "CRA" in body["affected_regulations"]
    assert "zu eng" in body["explanation"]
