"""SARIF 2.1.0 reporter for GitHub Security tab integration."""
from __future__ import annotations

from typing import Any

from pyguard.models import ScanResult, Severity

_SARIF_LEVEL: dict[Severity, str] = {
    Severity.CRITICAL: "error",
    Severity.HIGH: "error",
    Severity.MEDIUM: "warning",
    Severity.LOW: "note",
    Severity.INFO: "none",
}


def render_sarif(results: list[ScanResult]) -> dict[str, Any]:
    """Return a SARIF 2.1.0 log dict covering all scan results."""
    rules: dict[str, dict[str, Any]] = {}
    result_entries: list[dict[str, Any]] = []

    for scan in results:
        for finding in scan.findings:
            rule_id = _rule_id(finding)
            if rule_id not in rules:
                rules[rule_id] = {
                    "id": rule_id,
                    "name": _pascal(finding.title),
                    "shortDescription": {"text": finding.title},
                    "fullDescription": {"text": finding.description},
                    "defaultConfiguration": {
                        "level": _SARIF_LEVEL[finding.severity]
                    },
                    "properties": {
                        "tags": [finding.category, finding.layer],
                        "precision": _precision(finding.confidence),
                        "problem.severity": finding.severity.value,
                    },
                }

            location = _make_location(finding)
            result_entries.append(
                {
                    "ruleId": rule_id,
                    "level": _SARIF_LEVEL[finding.severity],
                    "message": {"text": finding.description},
                    "locations": [location],
                    "properties": {
                        "confidence": finding.confidence,
                        "package": finding.package,
                        "version": finding.version,
                        "layer": finding.layer,
                    },
                }
            )

    return {
        "$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json",
        "version": "2.1.0",
        "runs": [
            {
                "tool": {
                    "driver": {
                        "name": "pyguard",
                        "informationUri": "https://github.com/pyguard-dev/pyguard",
                        "rules": list(rules.values()),
                    }
                },
                "results": result_entries,
            }
        ],
    }


def _rule_id(finding: object) -> str:
    from pyguard.models import Finding  # noqa: PLC0415

    f = finding  # type: ignore[assignment]
    # e.g. PYGUARD-TYPOSQUATTING-001
    cat = getattr(f, "category", "general").upper().replace("_", "-")
    cve = getattr(f, "cve_id", None)
    if cve:
        return f"PYGUARD-CVE-{cve}"
    return f"PYGUARD-{cat}"


def _make_location(finding: object) -> dict[str, Any]:
    from pyguard.models import Finding  # noqa: PLC0415

    f = finding  # type: ignore[assignment]
    file_path = getattr(f, "file", None) or f"<package:{getattr(f, 'package', 'unknown')}>"
    line = getattr(f, "line", None) or 1
    return {
        "physicalLocation": {
            "artifactLocation": {"uri": file_path, "uriBaseId": "%SRCROOT%"},
            "region": {"startLine": line},
        }
    }


def _pascal(title: str) -> str:
    return "".join(w.capitalize() for w in title.split()[:6])


def _precision(confidence: float) -> str:
    if confidence >= 0.9:
        return "high"
    if confidence >= 0.7:
        return "medium"
    return "low"
