"""Inspect the PyMuPDF text layer of BHE_991 to ground a deterministic
table-region detector. Prints, per page, the y-clustered lines and the
horizontal "cells" within each line (split on large inter-word gaps), with
a numeric flag. This is read-only analysis — no detection yet."""

from __future__ import annotations

import sys
from pathlib import Path

import fitz

NUM_CHARS = set("0123456789")


def is_numeric_cell(text: str) -> bool:
    """A cell that is a financial number: has digits and only number-ish chars."""
    t = text.strip()
    if not any(c in NUM_CHARS for c in t):
        return False
    allowed = set("0123456789.,()%-$ —–")
    return all(c in allowed for c in t)


def cluster_lines(words, y_tol=3.0):
    """Group words into visual lines by y-center proximity."""
    ws = sorted(words, key=lambda w: ((w[1] + w[3]) / 2, w[0]))
    lines = []
    cur = []
    cur_yc = None
    for w in ws:
        yc = (w[1] + w[3]) / 2
        if cur_yc is None or abs(yc - cur_yc) <= y_tol:
            cur.append(w)
            cur_yc = yc if cur_yc is None else (cur_yc * (len(cur) - 1) + yc) / len(cur)
        else:
            lines.append(sorted(cur, key=lambda w: w[0]))
            cur = [w]
            cur_yc = yc
    if cur:
        lines.append(sorted(cur, key=lambda w: w[0]))
    return lines


def split_cells(line, gap_factor=2.5, min_gap_pts=8.0):
    """Split a line into cells where the gap to the next word is large."""
    if not line:
        return []
    # median char width estimate from words
    widths = [(w[2] - w[0]) / max(1, len(w[4])) for w in line if w[4].strip()]
    cw = sorted(widths)[len(widths) // 2] if widths else 5.0
    gap_thresh = max(min_gap_pts, gap_factor * cw)
    cells = []
    cur = [line[0]]
    for prev, w in zip(line, line[1:]):
        gap = w[0] - prev[2]
        if gap > gap_thresh:
            cells.append(cur)
            cur = [w]
        else:
            cur.append(w)
    cells.append(cur)
    out = []
    for c in cells:
        txt = " ".join(x[4] for x in c)
        x0 = min(x[0] for x in c)
        x1 = max(x[2] for x in c)
        out.append((x0, x1, txt))
    return out


def main():
    pages = [int(a) for a in sys.argv[1:]] or list(range(1, 9))
    d = fitz.open("documents/BHE_991.pdf")
    for pno in pages:
        page = d[pno - 1]
        words = page.get_text("words")
        lines = cluster_lines(words)
        print(f"\n{'='*90}\nPAGE {pno}  ({len(words)} words, {len(lines)} lines)\n{'='*90}")
        for li, line in enumerate(lines):
            cells = split_cells(line)
            ncells = len(cells)
            nnum = sum(1 for c in cells if is_numeric_cell(c[2]))
            yc = (line[0][1] + line[0][3]) / 2
            tag = ""
            if nnum >= 1 and ncells >= 2:
                tag = f" <-- DATA? cells={ncells} num={nnum} rightedges={[round(c[1],1) for c in cells if is_numeric_cell(c[2])]}"
            txt = " | ".join(c[2] for c in cells)
            print(f"  y={yc:6.1f} n={ncells} num={nnum} | {txt[:95]}{tag}")


if __name__ == "__main__":
    main()
