#/app/aroflo_connector_app/agent/det_cli.py
from __future__ import annotations

import json
from typing import Any, Dict, Optional

import click

import os
from dotenv import load_dotenv

from .parse_kv import parse_kv_items

load_dotenv(os.path.join(os.getcwd(), ".env"))


from .det_runner import execute_deterministic, list_operations, DeterministicError
from .det_policy import DeterministicPolicy


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


def _parse_kv(ctx, param, value) -> Dict[str, Any]:
    out = parse_kv_items(value or [], lowercase_keys=False)  # o True si quieres normalizar
    # si quieres mantener el mismo comportamiento de det_cli, deja lowercase_keys=False
    if not out and value:
        raise click.BadParameter("Each --param must be key=value")
    return out


def _looks_like_number(s: str) -> bool:
    try:
        float(s)
        return True
    except Exception:
        return False


@click.group()
def cli() -> None:
    """Deterministic agent CLI (zone + op execution with safe policies)."""
    pass


@cli.command("ops")
@click.option("--zone", "zone_code", required=True, help="Zone code (e.g., tasks, users, invoices).")
def ops_cmd(zone_code: str) -> None:
    try:
        _, ops = list_operations(zone_code)
        _echo(ops)
    except DeterministicError as e:
        raise SystemExit(f"❌ {e}")


@cli.command("run")
@click.option("--zone", "zone_code", required=True, help="Zone code (e.g., tasks).")
@click.option("--op", "op_code", required=True, help="Operation code (e.g., get_tasks_with_notes).")
@click.option("--param", "params_kv", multiple=True, callback=_parse_kv, help="Repeatable: key=value (JSON allowed).")
@click.option("--meta", "include_meta", is_flag=True, help="Include meta wrapper (policy + effective params).")
@click.option("--force-no-dryrun", is_flag=True, help="Allow writes to run without dry_run (NOT recommended).")
@click.option("--default-pagesize", type=int, default=10, show_default=True)
@click.option("--max-pagesize", type=int, default=50, show_default=True)
def run_cmd(
    zone_code: str,
    op_code: str,
    params_kv: Dict[str, Any],
    include_meta: bool,
    force_no_dryrun: bool,
    default_pagesize: int,
    max_pagesize: int,
) -> None:
    # Build policy
    policy = DeterministicPolicy(
        force_dry_run_for_writes=not force_no_dryrun,
        default_page_size=default_pagesize,
        max_page_size=max_pagesize,
    )

    try:
        result = execute_deterministic(
            zone_code=zone_code,
            op_code=op_code,
            params=params_kv,
            policy=policy,
            include_meta=include_meta,
        )
        _echo(result)
    except DeterministicError as e:
        raise SystemExit(f"❌ {e}")
    except Exception as e:
        import traceback
        traceback.print_exc()
        raise SystemExit(f"❌ Unexpected error: {e}")

if __name__ == "__main__":
    cli()
