"""Tests für Impressum-Agent v2 (BaseSpecialistAgent)."""

from __future__ import annotations

import asyncio

import pytest

from compliance.services.specialist_agents import (
    REGISTRY,
    AgentInput,
    AgentOutput,
    ImpressumAgent,
    Severity,
)
from compliance.services.specialist_agents._base import (
    FORBIDDEN_OUTPUT_TERMS,
    lint_output,
    stable_recommendation_id,
)
from compliance.services.specialist_agents._rollup import rollup


TESLA_IMPRESSUM = (
    "Tesla Germany GmbH\n"
    "Ludwig-Prandtl-Strasse 25-29\n"
    "12526 Berlin\n"
    "Deutschland\n\n"
    "Email: kontakt@tesla.com\n"
    "Telefon: +49 89 1250 16 800\n\n"
    "Management:\n"
    "Elon Musk\n\n"
    "Handelsregister: HRB 218904 B, Amtsgericht Charlottenburg\n"
)

FULL_IMPRESSUM = (
    TESLA_IMPRESSUM
    + "\nUSt-IdNr: DE123456789\nGeschäftsführer: Max Mustermann\n"
)


def _run(coro):
    return asyncio.get_event_loop().run_until_complete(coro)


def test_agent_is_registered():
    agent = REGISTRY.get("impressum")
    assert agent is not None
    assert agent.doc_type == "impressum"
    assert len(agent.owned_mc_ids) >= 10


def test_short_text_skipped():
    agent = ImpressumAgent()
    out = _run(agent.evaluate(AgentInput(doc_type="impressum", text="x")))
    assert out.mc_total > 0
    assert all(c.status == "skipped" for c in out.mc_coverage)
    assert not out.findings


def test_tesla_missing_german_label(monkeypatch):
    # Skip LLM escalation for unit test (no Ollama in CI)
    async def _no_cascade(*a, **kw):
        return None, []
    monkeypatch.setattr(
        "compliance.services.specialist_agents.impressum.agent.cascade",
        _no_cascade,
    )
    agent = ImpressumAgent()
    out = _run(agent.evaluate(AgentInput(
        doc_type="impressum", text=TESLA_IMPRESSUM,
    )))
    field_ids = {f.field_id for f in out.findings}
    # Tesla pattern: "Management:" matches IMP-MC-006 → present
    # But IMP-MC-007 (deutsches Label) MUSS fehlen
    assert "vertretungsberechtigte_label_korrekt" in field_ids
    # USt fehlt
    assert "ust_id" in field_ids


def test_safetykon_geschaeftsfuehrung_passes(monkeypatch):
    """Geschäftsführung (statt -führer) muss als deutsches Label akzeptiert
    werden — sonst False-Positive bei SafetyKon GmbH und ähnlichen."""
    async def _no_cascade(*a, **kw): return None, []
    monkeypatch.setattr(
        "compliance.services.specialist_agents.impressum.agent.cascade",
        _no_cascade,
    )
    txt = (
        "SafetyKon GmbH\nMerzhauser Str. 144\n79100 Freiburg\n"
        "Telefon: 0761/48 98 09 01\nE-Mail: info@safetykon.de\n"
        "Geschäftsführung: Dr. Oliver Kirchwehm\n"
        "Handelsregister AG Freiburg HRB 709859\n"
        "USt-Id: DE288952921\n"
    )
    agent = ImpressumAgent()
    out = _run(agent.evaluate(AgentInput(doc_type="impressum", text=txt)))
    field_ids = {f.field_id for f in out.findings}
    assert "vertretungsberechtigte" not in field_ids
    assert "vertretungsberechtigte_label_korrekt" not in field_ids


def test_full_impressum_has_no_basic_findings(monkeypatch):
    async def _no_cascade(*a, **kw):
        return None, []
    monkeypatch.setattr(
        "compliance.services.specialist_agents.impressum.agent.cascade",
        _no_cascade,
    )
    agent = ImpressumAgent()
    out = _run(agent.evaluate(AgentInput(
        doc_type="impressum", text=FULL_IMPRESSUM,
    )))
    # nur scope-dependent fields fehlen (vsbg, odr, redaktion)
    high = [f for f in out.findings if f.severity == Severity.HIGH.value]
    assert not high, f"unexpected HIGH findings: {[f.field_id for f in high]}"


def test_b2c_scope_adds_vsbg(monkeypatch):
    async def _no_cascade(*a, **kw):
        return None, []
    monkeypatch.setattr(
        "compliance.services.specialist_agents.impressum.agent.cascade",
        _no_cascade,
    )
    agent = ImpressumAgent()
    out = _run(agent.evaluate(AgentInput(
        doc_type="impressum", text=TESLA_IMPRESSUM,
        business_scope=["b2c", "ecommerce"],
    )))
    field_ids = {f.field_id for f in out.findings}
    assert "verbraucher_streitbeilegung" in field_ids
    assert "odr_link" in field_ids


def test_automotive_scope_auto_detected(monkeypatch):
    async def _no_cascade(*a, **kw):
        return None, []
    monkeypatch.setattr(
        "compliance.services.specialist_agents.impressum.agent.cascade",
        _no_cascade,
    )
    agent = ImpressumAgent()
    out = _run(agent.evaluate(AgentInput(
        doc_type="impressum", text=TESLA_IMPRESSUM,
    )))
    field_ids = {f.field_id for f in out.findings}
    assert "aufsichtsbehoerde" in field_ids
    # Action MUSS KBA-Hint enthalten
    aufsicht = next(f for f in out.findings
                    if f.field_id == "aufsichtsbehoerde")
    assert "KBA" in aufsicht.action or "Kraftfahrt" in aufsicht.action


def test_disclaimer_linter_scrubs_forbidden():
    from compliance.services.specialist_agents._base import Finding
    from datetime import datetime, timezone
    f = Finding(
        check_id="X", agent="t", agent_version="1",
        severity=Severity.HIGH,
        title="Diese Lösung ist rechtssicher und garantiert konform",
        action="Voll konform machen",
    )
    out = AgentOutput(
        agent="t", agent_version="1",
        started_at=datetime.now(timezone.utc),
        finished_at=datetime.now(timezone.utc),
        duration_ms=0, findings=[f],
    )
    cleaned = lint_output(out)
    assert "rechtssicher" not in cleaned.findings[0].title.lower()
    assert "garantiert" not in cleaned.findings[0].title.lower()
    assert "linter scrubbed" in cleaned.notes.lower()


def test_rollup_bundles_same_action():
    from compliance.services.specialist_agents._base import Finding
    fs = [
        Finding(check_id="A", agent="t", agent_version="1",
                severity=Severity.HIGH,
                title="Lücke 1", action="AVV mit Anbieter X abschließen"),
        Finding(check_id="B", agent="t", agent_version="1",
                severity=Severity.MEDIUM,
                title="Lücke 2", action="AVV mit Anbieter X abschließen."),
        Finding(check_id="C", agent="t", agent_version="1",
                severity=Severity.LOW,
                title="Lücke 3", action="Etwas anderes machen"),
    ]
    recs = rollup(fs)
    assert len(recs) == 2
    bundled = next(r for r in recs if len(r.related_finding_ids) == 2)
    assert bundled.severity == Severity.HIGH.value
    assert set(bundled.related_finding_ids) == {"A", "B"}


def test_stable_recommendation_id_is_deterministic():
    a = stable_recommendation_id("AVV mit Anbieter X abschließen")
    b = stable_recommendation_id("avv mit anbieter x abschliessen")
    # case insensitive aber Diakritika strict (deutsch ß ≠ ss)
    assert len(a) == 16
    assert len(b) == 16


def test_forbidden_terms_complete():
    """Sanity-Test, dass alle wichtigen Wörter im Linter sind."""
    for term in ("rechtssicher", "garantiert", "gesetzeskonform"):
        assert any(term in t for t in FORBIDDEN_OUTPUT_TERMS)
