"""Infiere schema de un JSON deserializado localizando el primer array de objetos."""


def _type(value) -> str:
    if value is None:
        return "null"
    if isinstance(value, bool):
        return "bool"
    if isinstance(value, int):
        return "int"
    if isinstance(value, float):
        return "float"
    if isinstance(value, str):
        return "string"
    if isinstance(value, list):
        return "array"
    if isinstance(value, dict):
        return "object"
    return "string"


def _truncate(value, max_chars: int = 80) -> str:
    s = str(value)
    return s[:max_chars] if len(s) > max_chars else s


_PREFERRED_KEYS = ("results", "items", "data", "records", "rows", "entries")


def _find_array_of_dicts(obj, path: str = "$"):
    """DFS buscando el primer array de dicts con >=1 elementos."""
    if isinstance(obj, list) and len(obj) >= 1 and isinstance(obj[0], dict):
        return path, obj
    if isinstance(obj, dict):
        # Primero probar claves preferidas en orden
        for key in _PREFERRED_KEYS:
            if key in obj:
                result = _find_array_of_dicts(obj[key], f"{path}.{key}")
                if result is not None:
                    return result
        # Luego resto de claves
        for key, val in obj.items():
            if key in _PREFERRED_KEYS:
                continue
            result = _find_array_of_dicts(val, f"{path}.{key}")
            if result is not None:
                return result
    return None


def infer_json_rows_schema(data: object) -> dict:
    """Dado un JSON deserializado, localiza el primer array de objetos con >=1 elementos.

    Args:
        data: JSON deserializado (dict, list, u otro valor Python).

    Returns:
        Schema con root_path, fields y count. Si no encuentra array, devuelve
        root_path vacío y fields vacío.
    """
    result = _find_array_of_dicts(data)
    if result is None:
        return {"root_path": "", "fields": [], "count": 0}

    root_path, rows = result
    first_row = rows[0]
    fields = []
    for name, value in first_row.items():
        fields.append({
            "name": name,
            "type": _type(value),
            "sample": _truncate(value),
        })

    return {
        "root_path": root_path,
        "fields": fields,
        "count": len(rows),
    }
