"""Deployment gate helpers for CI/CD policies."""

from __future__ import annotations

from collections import Counter
from dataclasses import dataclass

from .client import SyncClient
from .models import EvidenceLevel, ReviewResult, Severity


@dataclass(frozen=True)
class GatePolicy:
    min_score: int = 70
    min_confidence: float = 0.7
    require_evidence: EvidenceLevel = EvidenceLevel.FULL
    max_critical: int = 0
    max_high: int = 2


@dataclass(frozen=True)
class GateCheck:
    name: str
    passed: bool
    actual: str
    threshold: str


@dataclass(frozen=True)
class GateResult:
    passed: bool
    checks: list[GateCheck]
    severity_counts: dict[Severity, int]
    normalized_confidence: float


_EVIDENCE_ORDER: dict[EvidenceLevel, int] = {
    EvidenceLevel.INSUFFICIENT: 0,
    EvidenceLevel.PARTIAL: 1,
    EvidenceLevel.FULL: 2,
}

_SEVERITY_ORDER: tuple[Severity, ...] = (
    Severity.CRITICAL,
    Severity.HIGH,
    Severity.MEDIUM,
    Severity.LOW,
    Severity.INFO,
)


def _evidence_meets_threshold(actual: EvidenceLevel, required: EvidenceLevel) -> bool:
    return _EVIDENCE_ORDER[actual] >= _EVIDENCE_ORDER[required]


def _count_severity(response: ReviewResult) -> dict[Severity, int]:
    counts = Counter(finding.severity for finding in response.findings)
    return {severity: counts.get(severity, 0) for severity in _SEVERITY_ORDER}


def evaluate(response: ReviewResult, policy: GatePolicy | None = None) -> GateResult:
    """Evaluate a review response against gating policy thresholds."""
    effective_policy = policy or GatePolicy()
    normalized_confidence = response.confidence if response.confidence is not None else 0.0
    severity_counts = _count_severity(response)

    checks = [
        GateCheck(
            name="score",
            passed=response.score >= effective_policy.min_score,
            actual=str(response.score),
            threshold=f">= {effective_policy.min_score}",
        ),
        GateCheck(
            name="confidence",
            passed=normalized_confidence >= effective_policy.min_confidence,
            actual=f"{normalized_confidence:.2f}",
            threshold=f">= {effective_policy.min_confidence:.2f}",
        ),
        GateCheck(
            name="evidence_level",
            passed=_evidence_meets_threshold(response.evidence_level, effective_policy.require_evidence),
            actual=response.evidence_level.value,
            threshold=f">= {effective_policy.require_evidence.value}",
        ),
        GateCheck(
            name="critical_findings",
            passed=severity_counts[Severity.CRITICAL] <= effective_policy.max_critical,
            actual=str(severity_counts[Severity.CRITICAL]),
            threshold=f"<= {effective_policy.max_critical}",
        ),
        GateCheck(
            name="high_findings",
            passed=severity_counts[Severity.HIGH] <= effective_policy.max_high,
            actual=str(severity_counts[Severity.HIGH]),
            threshold=f"<= {effective_policy.max_high}",
        ),
    ]

    return GateResult(
        passed=all(check.passed for check in checks),
        checks=checks,
        severity_counts=severity_counts,
        normalized_confidence=normalized_confidence,
    )


def check_contract(
    code: str,
    *,
    base_url: str = "https://code-review-validator.fly.dev",
    api_key: str | None = None,
    policy: GatePolicy | None = None,
    timeout: float = 120.0,
) -> GateResult:
    """Submit contract code and evaluate gate policy in one call."""
    with SyncClient(base_url=base_url, api_key=api_key, timeout=timeout) as client:
        review = client.review(code)
    return evaluate(review, policy)
