"""
abstract_cv.column_utils
------------------------
Tools for detecting and validating multi-column layouts in scanned pages or PDF images.
Includes:
- detect_columns(): finds vertical divider between text columns
- validate_reading_order(): decides if a page is truly two-column
- visualize_columns(): saves quick visual check of divider placement
- slice_columns(): extracts left/right column image crops
"""
"""
abstract_cv.column_utils
"""

from ..imports import *
from .layered_ocr import *


# -------------------------------------------------------
# Column divider detection
# -------------------------------------------------------

def detect_columns(image_path: Path) -> Tuple[int | None, int | None]:

    img = cv2.imread(str(image_path), cv2.IMREAD_GRAYSCALE)

    if img is None:
        logger.warning(f"⚠️ Could not read image: {image_path}")
        return None, None

    _, binary = cv2.threshold(
        img, 0, 255,
        cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU
    )

    h, w = binary.shape

    vert = np.sum(binary, axis=0)

    m0 = w // 4
    m1 = 3 * w // 4

    divider = int(np.argmin(vert[m0:m1]) + m0)

    logger.info(f"📏 Detected divider at x={divider} of width={w}")

    return divider, w


# -------------------------------------------------------
# Visualization helper
# -------------------------------------------------------

def visualize_columns(image_path: Path, divider: int) -> Path | None:

    img = cv2.imread(str(image_path))

    if img is None:
        logger.warning(f"⚠️ Could not read image {image_path}")
        return None

    h, w, _ = img.shape

    divider = max(0, min(divider, w - 1))

    cv2.line(img, (divider, 0), (divider, h), (0, 0, 255), 2)

    out_path = str(image_path).replace(".png", "_divider_vis.png")

    cv2.imwrite(out_path, img)

    logger.info(f"🧩 Divider visualization saved to: {out_path}")

    return Path(out_path)


# -------------------------------------------------------
# Column layout validation
# -------------------------------------------------------

def validate_reading_order(
    image_path: Path,
    divider: int,
    debug: bool = True,
    visualize: bool = False,
) -> bool:

    img = cv2.imread(str(image_path), cv2.IMREAD_GRAYSCALE)

    if img is None:
        logger.warning(f"⚠️ Could not read image {image_path}")
        return False

    _, bin_img = cv2.threshold(
        img, 0, 255,
        cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU
    )

    h, w = bin_img.shape

    divider = max(int(w * 0.2), min(divider, int(w * 0.8)))

    left = bin_img[:, :divider]
    right = bin_img[:, divider:]

    left_density = np.mean(left > 0)
    right_density = np.mean(right > 0)

    band_width = max(5, min(40, w // 60))

    band = bin_img[:, divider-band_width:divider+band_width]
    band_density = np.mean(band > 0)

    balance = (
        min(left_density, right_density) /
        max(left_density, right_density)
        if max(left_density, right_density)
        else 0
    )

    median_density = np.median([left_density, right_density])

    is_two_col = (
        left_density > 0.02
        and right_density > 0.02
        and band_density < (median_density * 0.3)
        and balance > 0.25
    )

    if debug:
        logger.info(
            f"[validate_reading_order] {os.path.basename(str(image_path))}: "
            f"L={left_density:.3f}, R={right_density:.3f}, "
            f"Band={band_density:.3f}, Balance={balance:.3f} "
            f"→ {'TWO COLUMNS ✅' if is_two_col else 'ONE COLUMN ❌'}"
        )

    if visualize:
        visualize_columns(image_path, divider)

    return is_two_col


# -------------------------------------------------------
# Save sliced column images
# -------------------------------------------------------

def save_column_img(out_dir: str, columns_js: Dict) -> Dict:

    make_dirs(out_dir)

    filename = columns_js.get("page", {}).get("filename", "page")

    base_dir = os.path.join(out_dir, filename)

    make_dirs(base_dir)

    for column in ("left", "right"):

        values = columns_js.get(column)

        if not values:
            continue

        img = values.get("image", {}).get("img")

        if img is None:
            continue

        col_filename = f"{filename}_{column}"

        img_path = os.path.join(base_dir, f"{col_filename}.png")

        cv2.imwrite(img_path, img)

        columns_js[column]["filename"] = col_filename
        columns_js[column]["image"]["path"] = img_path

        logger.info(f"✂️ Columns sliced → {column}: {img_path}")

    return columns_js


# -------------------------------------------------------
# Column slicing
# -------------------------------------------------------

def slice_columns(
    image_path: str,
    divider: int | None = None,
    out_dir: str | None = None,
    columns_js: Dict | None = None,
    left_overlap: float = 0.02,
    right_gap: float = 0.005
):

    img = cv2.imread(str(image_path))

    if img is None:
        logger.warning(f"⚠️ Could not read image {image_path}")
        return columns_js or {}

    h, w, _ = img.shape

    if divider is None:
        divider, _ = detect_columns(image_path)

    divider = max(0, min(divider, w))

    left_end = int(divider + w * left_overlap)
    right_start = int(divider + w * right_gap)

    left = img[:, :left_end]
    right = img[:, right_start:]

    if columns_js:

        columns_js.setdefault("left", {}).setdefault("image", {})["img"] = left
        columns_js.setdefault("right", {}).setdefault("image", {})["img"] = right

        return save_column_img(out_dir or os.getcwd(), columns_js)

    return {"left": left, "right": right}
