"""
scan_service.py — detección de QR en un fotograma de cámara (base64), en servidor.

Mismo comportamiento que `/api/scan/frame` de hec-photo-app: el navegador intenta primero con jsQR
(gratis, en local) y, si no acierta tras unos fotogramas, manda el fotograma aquí, donde se aplica la
cascada completa de OpenCV (`qr_detect`) y, si no hay QR legible, el OCR del código impreso.
"""
import base64
import logging
from typing import Optional

import cv2
import numpy as np

from services import qr_detect

logger = logging.getLogger(__name__)


def b64_to_cv2(b64_data: str) -> Optional[np.ndarray]:
    """Data-URL (o base64 a secas) → imagen BGR de OpenCV. None si no se puede decodificar."""
    if "," in b64_data:
        b64_data = b64_data.split(",", 1)[1]
    try:
        arr = np.frombuffer(base64.b64decode(b64_data), dtype=np.uint8)
        return cv2.imdecode(arr, cv2.IMREAD_COLOR)
    except Exception as exc:
        logger.debug("b64 decode error: %s", exc)
        return None


def scan_frame(b64_image: str, prefixes: "set[str] | None" = None) -> dict:
    """{"code": str|None, "method": "qr"|"text"|None}. `code` ya normalizado (URL → código)."""
    img = b64_to_cv2(b64_image)
    if img is None:
        return {"code": None, "method": None}

    raw = qr_detect.detect_qr(img, prefixes=prefixes, use_ocr=False)
    code = qr_detect.extract_code(raw) if raw else None
    if code:
        return {"code": code, "method": "qr"}

    if prefixes:
        text = qr_detect.ocr_code(img, prefixes)
        code = qr_detect.extract_code(text) if text else None
        if code:
            return {"code": code, "method": "text"}
    return {"code": None, "method": None}
