#/apps/aroflo_connector_app/zones/businessunits/cli.py
from __future__ import annotations

import json
from typing import Any, Dict, List, Optional, Callable

import click


def _echo(result: Any) -> None:
    if isinstance(result, (dict, list)):
        click.echo(json.dumps(result, indent=2, ensure_ascii=False))
    else:
        click.echo(str(result))


def _available_ops(zone: Any) -> List[str]:
    ops = getattr(zone, "operations", [])
    return sorted([o.code for o in ops])


def _run(zone: Any, op_code: str, params: Dict[str, Any]) -> Any:
    available = set(_available_ops(zone))
    if op_code not in available:
        click.echo(f"❌ Operación '{op_code}' no existe en zona '{zone.code}'.")
        click.echo("Operaciones disponibles:")
        for c in _available_ops(zone):
            click.echo(f"  - {c}")
        raise SystemExit(2)
    return zone.execute(op_code, params=params)


def _add_optional(params: Dict[str, Any], *, pagesize: Optional[int]) -> Dict[str, Any]:
    if pagesize is not None:
        params["pageSize"] = pagesize
    return params


def _common_list_options(fn: Callable[..., Any]) -> Callable[..., Any]:
    fn = click.option("--page", default=1, type=int, show_default=True)(fn)
    fn = click.option("--where", default=None, show_default=True, help="Cláusula WHERE estilo AroFlo.")(fn)
    fn = click.option(
        "--pagesize",
        type=int,
        default=None,
        show_default=True,
        help="Cantidad de registros por página (AroFlo pageSize). Ej: 5, 20, 50.",
    )(fn)
    fn = click.option("--raw", is_flag=True, help="Devuelve respuesta cruda + meta debug.")(fn)
    return fn


def register_cli(root: click.Group, zone: Any) -> None:
    @root.group(name=zone.code)
    def businessunits_group():
        """Operaciones de la zona businessunits (READ ONLY)."""

    # BASE
    @businessunits_group.command("list")
    @_common_list_options
    def list_cmd(page: int, where: Optional[str], pagesize: Optional[int], raw: bool):
        params = _add_optional({"page": page, "where": where, "raw": raw}, pagesize=pagesize)
        _echo(_run(zone, "list_businessunits", params))

    @businessunits_group.command("archived")
    @_common_list_options
    def archived_cmd(page: int, where: Optional[str], pagesize: Optional[int], raw: bool):
        # si where no viene, el backend pone archived=true por defecto
        params = _add_optional({"page": page, "where": where, "raw": raw}, pagesize=pagesize)
        _echo(_run(zone, "list_archived_businessunits", params))

    # JOINS
    def add_join_command(cmd_name: str, op_code: str, help_text: str) -> None:
        @businessunits_group.command(cmd_name, help=help_text)
        @_common_list_options
        def _cmd(page: int, where: Optional[str], pagesize: Optional[int], raw: bool):
            params = _add_optional({"page": page, "where": where, "raw": raw}, pagesize=pagesize)
            _echo(_run(zone, op_code, params))

    add_join_command("locations", "get_businessunits_with_locations", "BusinessUnits + join=locations")
    add_join_command("priorities", "get_businessunits_with_priorities", "BusinessUnits + join=priorities")
