# apps/aroflo_connector_app/zones/users/_join_utils.py
from __future__ import annotations

from typing import Any, Dict, List, Tuple
from urllib.parse import urlencode


def request(client: Any, method: str, params_list: List[Tuple[str, str]]) -> Any:
    """
    Ejecuta request al client AroFlo usando lista de params para permitir repetidos.

    GET  -> AroFlo lee querystring (params=lista de tuplas).
    POST -> AroFlo espera application/x-www-form-urlencoded en el BODY (data=string).
            Importante: el HMAC normalmente depende de var_string; debe coincidir con el BODY.
    """
    var_string = urlencode(params_list)
    method_u = (method or "GET").upper()

    if method_u == "POST":
        return client.request(
            "",
            method="POST",
            params=None,
            data=var_string,  # BODY form-encoded (str)
            var_string=var_string,
            headers={"Content-Type": "application/x-www-form-urlencoded"},
        )

    return client.request("", method=method_u, params=params_list, var_string=var_string)


def raw_wrap(resp: Any, params_list: List[Tuple[str, str]]) -> Dict[str, Any]:
    return {
        "data": resp,
        "meta": {
            "params": params_list,
            "var_string": urlencode(params_list),
        },
    }


def coerce_page_size(params: Dict[str, Any]) -> str | None:
    v = params.get("pageSize", None)
    if v is None:
        v = params.get("pagesize", None)

    if v is None or v == "":
        return None

    try:
        iv = int(v)
    except Exception:
        raise ValueError("pageSize debe ser un entero.")

    if iv <= 0:
        raise ValueError("pageSize debe ser > 0.")

    return str(iv)


def coerce_order(params: Dict[str, Any]) -> str | None:
    v = params.get("order")
    if v is None:
        return None

    v = str(v).strip()
    if not v:
        return None

    if "|" not in v:
        raise ValueError("order debe tener formato 'campo|asc' o 'campo|desc'.")

    field, direction = v.split("|", 1)
    field = field.strip()
    direction = direction.strip().lower()

    if not field:
        raise ValueError("order: el campo no puede estar vacío.")

    if direction not in ("asc", "desc"):
        raise ValueError("order: la dirección debe ser 'asc' o 'desc'.")

    return f"{field}|{direction}"


def build_list_params(
    *,
    zone: str,
    where: str,
    join: str | None,
    page: int,
    pageSize: str | None,
    order: str | None = None,
) -> List[Tuple[str, str]]:
    """
    Builder estándar para listados con WHERE + JOIN opcional + ORDER opcional + paginación.
    """
    params_list: List[Tuple[str, str]] = [("zone", zone), ("where", where)]

    if join:
        params_list.append(("join", join))

    if order:
        params_list.append(("order", order))

    if pageSize:
        params_list.append(("pageSize", pageSize))

    params_list.append(("page", str(page)))
    return params_list
