from __future__ import annotations

from dataclasses import dataclass

from contract_attestation.gate import GatePolicy, check_contract, evaluate
from contract_attestation.models import AttestationStatus, EvidenceLevel, Finding, ReviewResult, Severity


def _make_finding(severity: Severity) -> Finding:
    return Finding(
        severity=severity,
        category="test",
        line=1,
        function="f",
        description="d",
        recommendation="r",
        references=[],
        sources=["unit-test"],
        confidence=0.9,
    )


def _make_review(
    *,
    score: int,
    confidence: float | None,
    evidence: EvidenceLevel,
    findings: list[Finding] | None = None,
) -> ReviewResult:
    return ReviewResult(
        score=score,
        confidence=confidence,
        evidence_level=evidence,
        findings=findings or [],
        recommendations=[],
        attestation={},
        attestation_status=AttestationStatus.FREE,
    )


def _check_map(result) -> dict[str, bool]:
    return {check.name: check.passed for check in result.checks}


def test_evaluate_pass_clean_contract() -> None:
    response = _make_review(score=95, confidence=0.9, evidence=EvidenceLevel.FULL)
    result = evaluate(response)

    assert result.passed is True
    assert all(check.passed for check in result.checks)


def test_evaluate_fail_low_score() -> None:
    response = _make_review(score=40, confidence=0.9, evidence=EvidenceLevel.FULL)
    result = evaluate(response)

    assert result.passed is False
    assert _check_map(result)["score"] is False


def test_evaluate_fail_insufficient_evidence() -> None:
    response = _make_review(score=90, confidence=0.9, evidence=EvidenceLevel.INSUFFICIENT)
    result = evaluate(response)

    assert result.passed is False
    assert _check_map(result)["evidence_level"] is False


def test_evaluate_fail_too_many_critical_findings() -> None:
    response = _make_review(
        score=90,
        confidence=0.9,
        evidence=EvidenceLevel.FULL,
        findings=[_make_finding(Severity.CRITICAL)],
    )
    result = evaluate(response, GatePolicy(max_critical=0))

    assert result.passed is False
    assert _check_map(result)["critical_findings"] is False


def test_evaluate_null_confidence_treated_as_zero() -> None:
    response = _make_review(score=90, confidence=None, evidence=EvidenceLevel.FULL)
    result = evaluate(response)

    assert result.normalized_confidence == 0.0
    assert _check_map(result)["confidence"] is False


def test_check_contract_uses_sync_client(monkeypatch) -> None:
    review = _make_review(score=88, confidence=0.8, evidence=EvidenceLevel.FULL)

    @dataclass
    class _FakeClient:
        base_url: str
        api_key: str | None
        timeout: float

        def __enter__(self):
            return self

        def __exit__(self, exc_type, exc, tb):
            return None

        def review(self, code: str) -> ReviewResult:
            assert code == "contract C {}"
            return review

    monkeypatch.setattr("contract_attestation.gate.SyncClient", _FakeClient)

    result = check_contract(
        "contract C {}",
        base_url="https://example.test",
        api_key="k",
        timeout=30.0,
    )

    assert result.passed is True
