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

import json
from typing import Any, Dict, List

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 _with_optional(params: Dict[str, Any], *, maxpageresults: int | None) -> Dict[str, Any]:
    if maxpageresults is not None:
        params["maxpageresults"] = maxpageresults
    return params


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

    # -------------------------
    # GET base
    # -------------------------
    @invoices_group.command("list")
    @click.option("--page", default=1, type=int, show_default=True)
    @click.option(
        "--where",
        default="and|createdutc|>|2001-01-01",
        show_default=True,
        help="Cláusula WHERE estilo AroFlo.",
    )
    @click.option("--maxpageresults", type=int, default=None, show_default=True, help="Ej: 5, 20, 50.")
    @click.option("--raw", is_flag=True, help="Devuelve respuesta cruda + meta debug.")
    def list_cmd(page: int, where: str, maxpageresults: int | None, raw: bool):
        params = _with_optional({"page": page, "where": where, "raw": raw}, maxpageresults=maxpageresults)
        result = _run(zone, "list_invoices", params)
        _echo(result)

    @invoices_group.command("get")
    @click.option("--invoiceid", required=True, help="ID codificado de la invoice en AroFlo.")
    @click.option("--raw", is_flag=True, help="Devuelve respuesta cruda + meta debug.")
    def get_cmd(invoiceid: str, raw: bool):
        result = _run(zone, "get_invoice", {"invoiceid": invoiceid, "raw": raw})
        _echo(result)

    @invoices_group.command("approved-unprocessed")
    @click.option("--page", default=1, type=int, show_default=True)
    @click.option("--maxpageresults", type=int, default=None, show_default=True, help="Ej: 5, 20, 50.")
    @click.option("--raw", is_flag=True)
    def approved_unprocessed_cmd(page: int, maxpageresults: int | None, raw: bool):
        params = _with_optional({"page": page, "raw": raw}, maxpageresults=maxpageresults)
        result = _run(zone, "get_approved_unprocessed_invoices", params)
        _echo(result)

    @invoices_group.command("approved-unprocessed-updated-after")
    @click.option("--updated-after", required=True, help="Formato: YYYY-MM-DD HH:mm:ss (UTC).")
    @click.option("--page", default=1, type=int, show_default=True)
    @click.option("--maxpageresults", type=int, default=None, show_default=True, help="Ej: 5, 20, 50.")
    @click.option("--raw", is_flag=True)
    def approved_unprocessed_updated_after_cmd(updated_after: str, page: int, maxpageresults: int | None, raw: bool):
        params = _with_optional(
            {"updated_after": updated_after, "page": page, "raw": raw},
            maxpageresults=maxpageresults,
        )
        result = _run(zone, "get_approved_unprocessed_invoices_updated_after", params)
        _echo(result)

    @invoices_group.command("by-task")
    @click.option("--taskid", required=True, help="TaskID codificado (AroFlo).")
    @click.option("--page", default=1, type=int, show_default=True)
    @click.option("--maxpageresults", type=int, default=None, show_default=True, help="Ej: 5, 20, 50.")
    @click.option("--raw", is_flag=True)
    def by_task_cmd(taskid: str, page: int, maxpageresults: int | None, raw: bool):
        params = _with_optional({"taskid": taskid, "page": page, "raw": raw}, maxpageresults=maxpageresults)
        result = _run(zone, "get_invoices_for_task", params)
        _echo(result)

    # -------------------------
    # JOINs (op_codes reales detectados en tu output)
    # -------------------------
    @invoices_group.command("lineitems")
    @click.option("--page", default=1, type=int, show_default=True)
    @click.option(
        "--where",
        default="and|linkprocessed|=|false",
        show_default=True,
        help="Cláusula WHERE estilo AroFlo (recomendado filtrar).",
    )
    @click.option("--maxpageresults", type=int, default=None, show_default=True, help="Ej: 5, 20, 50.")
    @click.option("--raw", is_flag=True)
    def lineitems_cmd(page: int, where: str, maxpageresults: int | None, raw: bool):
        params = _with_optional({"page": page, "where": where, "raw": raw}, maxpageresults=maxpageresults)
        result = _run(zone, "get_invoices_with_lineitems", params)
        _echo(result)

    @invoices_group.command("task")
    @click.option("--page", default=1, type=int, show_default=True)
    @click.option(
        "--where",
        default="and|linkprocessed|=|false",
        show_default=True,
        help="Cláusula WHERE estilo AroFlo (recomendado filtrar).",
    )
    @click.option("--maxpageresults", type=int, default=None, show_default=True, help="Ej: 5, 20, 50.")
    @click.option("--raw", is_flag=True)
    def task_cmd(page: int, where: str, maxpageresults: int | None, raw: bool):
        params = _with_optional({"page": page, "where": where, "raw": raw}, maxpageresults=maxpageresults)
        result = _run(zone, "get_invoices_with_task", params)
        _echo(result)

    @invoices_group.command("project")
    @click.option("--page", default=1, type=int, show_default=True)
    @click.option(
        "--where",
        default="and|linkprocessed|=|false",
        show_default=True,
        help="Cláusula WHERE estilo AroFlo (recomendado filtrar).",
    )
    @click.option("--maxpageresults", type=int, default=None, show_default=True, help="Ej: 5, 20, 50.")
    @click.option("--raw", is_flag=True)
    def project_cmd(page: int, where: str, maxpageresults: int | None, raw: bool):
        params = _with_optional({"page": page, "where": where, "raw": raw}, maxpageresults=maxpageresults)
        result = _run(zone, "get_invoices_with_project", params)
        _echo(result)

    @invoices_group.command("trackingcentres")
    @click.option("--page", default=1, type=int, show_default=True)
    @click.option(
        "--where",
        default="and|linkprocessed|=|false",
        show_default=True,
        help="Cláusula WHERE estilo AroFlo (recomendado filtrar).",
    )
    @click.option("--maxpageresults", type=int, default=None, show_default=True, help="Ej: 5, 20, 50.")
    @click.option("--raw", is_flag=True)
    def trackingcentres_cmd(page: int, where: str, maxpageresults: int | None, raw: bool):
        params = _with_optional({"page": page, "where": where, "raw": raw}, maxpageresults=maxpageresults)
        result = _run(zone, "get_invoices_with_trackingcentres", params)
        _echo(result)

    # -------------------------
    # POST
    # -------------------------
    @invoices_group.command("process")
    @click.option("--invoiceid", required=True, help="InvoiceID codificado a procesar.")
    @click.option("--status", default="processed", show_default=True)
    @click.option("--raw", is_flag=True)
    def process_cmd(invoiceid: str, status: str, raw: bool):
        result = _run(zone, "process_invoice", {"invoiceid": invoiceid, "status": status, "raw": raw})
        _echo(result)
