"""Single-page boundary test: datelines + rules -> article boxes, overlaid.
Usage: venv/bin/python3 _test_boundaries.py <run_dir> <page_num>
"""
import json
import sys
from pathlib import Path

import cv2
from PIL import Image

from _lines import detect_separator_lines
from _boundaries import construct_boundaries
from smart_extractor import find_article_starts_by_dateline


def paper_of_height(h):
    if 7040 <= h <= 7060:
        return "sakshi"
    if h in (6833, 6549):
        return "andhra_jyothi"
    if h == 6422:
        return "namaste_telangana"
    return "unknown"


def iou(a, b):
    ix = max(0, min(a[2], b[2]) - max(a[0], b[0]))
    iy = max(0, min(a[3], b[3]) - max(a[1], b[1]))
    inter = ix * iy
    if inter == 0:
        return 0.0
    ua = (a[2] - a[0]) * (a[3] - a[1]) + (b[2] - b[0]) * (b[3] - b[1]) - inter
    return inter / ua if ua else 0.0


def main(run_dir, page_num):
    run = Path(run_dir)
    png = run / "pages" / f"page_{page_num:03d}.png"
    regs = json.loads((run / "pages" / f"page_{page_num:03d}.regions.json").read_text())["regions"]
    rmap = {r["id"]: r for r in regs}
    paper = paper_of_height(Image.open(png).height)

    lines = detect_separator_lines(png)
    dls = find_article_starts_by_dateline(regs, str(png), paper)
    boxes = construct_boundaries(regs, dls, lines, lines["size"])

    print(f"\npaper={paper}  datelines={len(dls)}  boxes={len(boxes)}  "
          f"rules H={len(lines['h'])} V={len(lines['v'])}")

    # validation
    fails = []
    for bx in boxes:
        db = rmap[bx["region_id"]]["bbox"]
        bb = bx["bbox"]
        contains = bb[0] <= db[0] and bb[1] <= db[1] and bb[2] >= db[2] and bb[3] >= db[3]
        if not contains:
            fails.append(f"R{bx['region_id']} box does NOT contain its dateline body")
        if bb[2] - bb[0] < 50 or bb[3] - bb[1] < 50:
            fails.append(f"R{bx['region_id']} degenerate box {bb}")
    for i in range(len(boxes)):
        for j in range(i + 1, len(boxes)):
            ov = iou(boxes[i]["bbox"], boxes[j]["bbox"])
            if ov > 0.25:
                fails.append(f"R{boxes[i]['region_id']} & R{boxes[j]['region_id']} overlap iou={ov:.2f}")

    for bx in sorted(boxes, key=lambda z: z["bbox"][1]):
        print(f"  R{bx['region_id']:>3} hl=R{bx['headline_region']} {bx['dateline'][:22]!r:24} "
              f"bbox={bx['bbox']} walls={bx['walls']['ceil_rule']}/{bx['walls']['floor_rule']}")
    print(f"\nVALIDATION: {'PASS' if not fails else f'{len(fails)} ISSUE(S)'}")
    for f in fails:
        print("   ⚠", f)

    img = cv2.imread(str(png))
    for L in lines["h"]:
        cv2.line(img, (L["x1"], L["y1"]), (L["x2"], L["y2"]), (0, 0, 255), 4)
    for L in lines["v"]:
        cv2.line(img, (L["x1"], L["y1"]), (L["x2"], L["y2"]), (255, 0, 0), 4)
    for bx in boxes:
        b = bx["bbox"]
        cv2.rectangle(img, (b[0], b[1]), (b[2], b[3]), (0, 180, 0), 8)
    out = Path(f"/tmp/boundaries_{run.name}_p{page_num:03d}.png")
    cv2.imwrite(str(out), img)
    print("overlay:", out)


if __name__ == "__main__":
    main(sys.argv[1], int(sys.argv[2]))
