import json

from scripts.quant.bbox_iou import iou, match_boxes, bbox_iou_over_dirs


def test_iou_identical_is_one():
    assert iou([0, 0, 10, 10], [0, 0, 10, 10]) == 1.0


def test_iou_disjoint_is_zero():
    assert iou([0, 0, 10, 10], [20, 20, 30, 30]) == 0.0


def test_iou_half_overlap():
    # two 10x10 boxes overlapping in a 10x5 region -> 50/150
    assert abs(iou([0, 0, 10, 10], [0, 5, 10, 15]) - (50 / 150)) < 1e-9


def test_match_boxes_counts_missed_and_extra():
    ref = [[0, 0, 10, 10], [100, 100, 110, 110]]
    cand = [[0, 0, 10, 10], [200, 200, 210, 210], [300, 300, 310, 310]]

    result = match_boxes(ref, cand, iou_threshold=0.5)

    assert result["matched"] == 1
    assert result["missed"] == 1  # ref box at 100,100 unmatched
    assert result["extra"] == 2   # two cand boxes unmatched
    assert abs(result["mean_matched_iou"] - 1.0) < 1e-9


def test_match_boxes_empty():
    result = match_boxes([], [], iou_threshold=0.5)
    assert result == {"matched": 0, "missed": 0, "extra": 0, "mean_matched_iou": 0.0}


def test_bbox_iou_over_dirs(tmp_path):
    ref_dir = tmp_path / "ref"
    cand_dir = tmp_path / "cand"
    ref_dir.mkdir()
    cand_dir.mkdir()
    (ref_dir / "p1.json").write_text(json.dumps({"boxes": [[0, 0, 10, 10]]}))
    (cand_dir / "p1.json").write_text(json.dumps({"boxes": [[0, 0, 10, 10]]}))

    result = bbox_iou_over_dirs(ref_dir, cand_dir, iou_threshold=0.5)

    assert abs(result["mean_bbox_iou"] - 1.0) < 1e-9
    assert result["mean_missed_lines"] == 0.0
    assert result["mean_extra_lines"] == 0.0
