from __future__ import annotations

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

from ..base import ZoneOperation, ParamSpec
from .base import _raw_wrap, _compact_clients_response


def _request(client: Any, method: str, params_list: List[Tuple[str, str]]) -> Any:
    var_string = urlencode(params_list)
    return client.request("", method=method, params=params_list, var_string=var_string)


def _add_opt(params_list: List[Tuple[str, str]], key: str, value: Optional[Any]) -> None:
    if value is None:
        return
    s = str(value).strip()
    if s:
        params_list.append((key, s))


def get_operations() -> List[ZoneOperation]:
    return [
        ZoneOperation(
            code="get_clients_join_contacts",
            label="Get Clients (join=contacts)",
            description="Lista clients con join=contacts. WHERE opcional. Soporta paginación.",
            http_method="GET",
            side_effect="read",
            idempotent=True,
            default_params={"where": None, "page": 1, "page_size": None, "compact": True, "max_items": 20, "raw": False},
            params=[
                ParamSpec("where", "string", False, "Cláusula WHERE estilo AroFlo (opcional)."),
                ParamSpec("page", "integer", False, "Número de página (1..N)."),
                ParamSpec("page_size", "integer", False, "maxpageresults (opcional)."),
                ParamSpec("compact", "boolean", False, "Compacta y recorta localmente."),
                ParamSpec("max_items", "integer", False, "Recorte local cuando compact=true."),
                ParamSpec("raw", "boolean", False, "Respuesta cruda + meta."),
            ],
            category="clients",
            use_cases=["Traer clients con contactos para reportes/CRM"],
            risk_level="low",
            requires_confirmation=False,
        ),
    ]


def supports(operation_code: str) -> bool:
    return any(op.code == operation_code for op in get_operations())


def execute(operation_code: str, client: Any, params: Dict[str, Any]) -> Any:
    raw = bool(params.get("raw", False))
    compact = bool(params.get("compact", True))
    max_items = int(params.get("max_items", 20) or 20)

    page_size = params.get("page_size", None)
    page_size_str = str(int(page_size)) if page_size is not None else None

    if operation_code == "get_clients_join_contacts":
        where = params.get("where", None)
        page = str(params.get("page", 1))

        params_list: List[Tuple[str, str]] = [("zone", "clients"), ("join", "contacts"), ("page", page)]
        if where:
            params_list.append(("where", str(where)))
        _add_opt(params_list, "maxpageresults", page_size_str)

        resp = _request(client, "GET", params_list)
        if raw:
            return _raw_wrap(resp, params_list)
        return _compact_clients_response(resp, max_items=max_items) if compact else resp

    raise ValueError(f"[Clients.join_contacts] Operación no soportada: {operation_code}")
