import cv2
import numpy as np

from .config import ROI

VIVID_COLORS = ("turquoise", "yellow", "dark_green", "dark_red", "light_green", "light_red", "gray")


def detect_strips(
    full_dot_crop: np.ndarray,
    palette: dict[str, tuple[tuple[int, int, int], float]],
    min_gap_px: int,
    min_strip_px: int,
) -> list[ROI]:
    """Return list of sub-ROIs (relative to full_dot_crop) sorted left-to-right.
    Empty list if no vivid pixels found."""
    h, w = full_dot_crop.shape[:2]
    mask = np.zeros((h, w), dtype=np.uint8)
    img_f = full_dot_crop.astype(np.float32)
    for name in VIVID_COLORS:
        if name not in palette:
            continue
        rgb, tol = palette[name]
        bgr = np.array([rgb[2], rgb[1], rgb[0]], dtype=np.float32)
        diff = np.linalg.norm(img_f - bgr, axis=2)
        mask |= (diff < tol).astype(np.uint8)
    kw = max(3, min_gap_px // 2)
    kernel = np.ones((1, kw), dtype=np.uint8)
    closed = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)
    n_labels, _labels, stats, _centroids = cv2.connectedComponentsWithStats(closed, connectivity=8)
    strips: list[tuple[int, int]] = []
    for i in range(1, n_labels):
        x = int(stats[i, cv2.CC_STAT_LEFT])
        ww = int(stats[i, cv2.CC_STAT_WIDTH])
        if ww < min_strip_px:
            continue
        strips.append((x, x + ww))
    strips.sort()
    return [ROI(x=xs, y=0, w=xe - xs, h=h) for (xs, xe) in strips]


def _strips_match(a: list[ROI], b: list[ROI], tol: int = 10) -> bool:
    if len(a) != len(b):
        return False
    return all(
        abs(ra.x - rb.x) <= tol and abs((ra.x + ra.w) - (rb.x + rb.w)) <= tol
        for ra, rb in zip(a, b)
    )
