from __future__ import annotations

import json

from oncecheck.benchmark.metrics import (
    evaluate_thresholds,
    filter_keys_by_prefixes,
    load_predictions,
    load_truth,
    score,
    truth_template,
)


def test_score_metrics_basic():
    pred = {("A", "src/a.ts", 1), ("B", "src/b.ts", 2)}
    truth = {("A", "src/a.ts", 1), ("C", "src/c.ts", 3)}
    result = score(pred, truth)
    assert result["tp"] == 1
    assert result["fp"] == 1
    assert result["fn"] == 1
    assert 0 < result["precision"] < 1
    assert 0 < result["recall"] < 1
    assert 0 < result["f1"] < 1


def test_load_predictions_and_truth(tmp_path):
    pred_file = tmp_path / "pred.json"
    truth_file = tmp_path / "truth.json"

    pred_file.write_text(json.dumps({
        "scans": [{"findings": [{"id": "WEB-OWASP-003", "file_path": "src/x.ts", "line": 9}]}]
    }))
    truth_file.write_text(json.dumps({
        "truth": [{"id": "WEB-OWASP-003", "file_path": "src/x.ts", "line": 9}]
    }))

    pred = load_predictions(pred_file)
    truth = load_truth(truth_file)
    assert ("WEB-OWASP-003", "src/x.ts", 9) in pred
    assert ("WEB-OWASP-003", "src/x.ts", 9) in truth


def test_truth_template():
    payload = truth_template("owasp-benchmark")
    assert payload["suite"] == "owasp-benchmark"
    assert "truth" in payload
    assert isinstance(payload["truth"], list)


def test_evaluate_thresholds():
    result = {
        "tp": 10.0,
        "fp": 2.0,
        "fn": 1.0,
        "precision": 0.8333,
        "recall": 0.9090,
        "f1": 0.8695,
    }
    gate_ok = evaluate_thresholds(
        result, min_precision=0.80, min_recall=0.80, min_f1=0.80, min_tp=5
    )
    assert gate_ok["ok"] is True
    assert gate_ok["failed"] == []

    gate_bad = evaluate_thresholds(
        result, min_precision=0.90, min_recall=0.95, min_f1=0.90, min_tp=20
    )
    assert gate_bad["ok"] is False
    assert set(gate_bad["failed"]) == {"precision", "recall", "f1", "tp"}


def test_filter_keys_by_prefixes():
    keys = {
        ("WEB-OWASP-003", "src/x.ts", 1),
        ("AND-SEC-001", "app/src/main/AndroidManifest.xml", 2),
        ("IOS-SEC-001", "Info.plist", 3),
    }
    web = filter_keys_by_prefixes(keys, ["WEB-"])
    mobile = filter_keys_by_prefixes(keys, ["AND-", "IOS-"])
    assert len(web) == 1
    assert len(mobile) == 2
