# rftools/_cli.py
"""
rftools CLI — run RF calculations from the terminal.

Usage:
    rftools calc vswr-return-loss --vswr 2.5
    rftools calc free-space-path-loss --frequency 2400 --distance 100
    rftools list
    rftools list --category rf
    rftools info vswr-return-loss
    rftools version
"""
from __future__ import annotations

import json
import os
import sys

import click

from rftools import __version__
from rftools.client import Client
from rftools.exceptions import RFToolsError


def _make_client(api_key: str | None) -> Client:
    key = api_key or os.environ.get("RFTOOLS_API_KEY")
    return Client(api_key=key)


@click.group()
def cli() -> None:
    """rftools — 203 RF & electronics calculators from the command line."""
    pass


@cli.command("calc", context_settings={"allow_extra_args": True, "ignore_unknown_options": True})
@click.argument("slug")
@click.option("--api-key", envvar="RFTOOLS_API_KEY", default=None, help="API key (rfc_...)")
@click.option("--json", "output_json", is_flag=True, help="Output raw JSON")
@click.pass_context
def calc_cmd(ctx: click.Context, slug: str, api_key: str | None, output_json: bool) -> None:
    """Run a calculator. Pass inputs as --key value pairs.

    Example: rftools calc vswr-return-loss --vswr 2.5
    """
    # Parse --key value pairs from extra args (unknown options)
    inputs: dict[str, float] = {}
    extra = ctx.args
    it = iter(extra)
    for token in it:
        if token.startswith("--"):
            key = token[2:]
            try:
                val_str = next(it)
                inputs[key] = float(val_str)
            except StopIteration:
                click.echo(f"Error: --{key} requires a value", err=True)
                sys.exit(1)
            except ValueError:
                click.echo(f"Error: value for --{key} must be a number", err=True)
                sys.exit(1)
        else:
            click.echo(f"Error: unexpected argument {token!r}", err=True)
            sys.exit(1)

    client = _make_client(api_key)
    try:
        result = client.calculate(slug, inputs)
    except RFToolsError as e:
        click.echo(f"Error: {e}", err=True)
        sys.exit(1)

    if output_json:
        click.echo(json.dumps({
            "slug": result.slug,
            "values": result.values,
            "warnings": result.warnings,
            "errors": result.errors,
        }))
        return

    if result.errors:
        click.echo(f"Calculation errors:", err=True)
        for e in result.errors:
            click.echo(f"  {e}", err=True)
        sys.exit(1)

    # Get output metadata for units
    try:
        from rftools._catalog import CALCULATORS
        info = CALCULATORS.get(slug)
        units = {o.key: o.unit for o in info.outputs} if info else {}
    except Exception:
        units = {}

    click.echo(f"\nOUTPUTS")
    for key, value in result.values.items():
        unit = units.get(key, "")
        unit_str = f"   {unit}" if unit else ""
        click.echo(f"  {key:<24} {value!r}{unit_str}")

    if result.warnings:
        click.echo("\nWARNINGS")
        for w in result.warnings:
            click.echo(f"  {w}")


@cli.command("list")
@click.option("--category", default=None, help="Filter by category (e.g. rf, pcb, antenna)")
def list_cmd(category: str | None) -> None:
    """List all available calculators."""
    from rftools._catalog import CALCULATORS

    calcs = list(CALCULATORS.values())
    if category:
        calcs = [c for c in calcs if c.category == category]

    if not calcs:
        click.echo(f"No calculators found for category '{category}'")
        return

    # Header
    click.echo(f"{'SLUG':<40} {'CATEGORY':<18} TITLE")
    click.echo("-" * 80)
    for c in sorted(calcs, key=lambda x: (x.category, x.slug)):
        click.echo(f"{c.slug:<40} {c.category:<18} {c.title}")
    click.echo(f"\n({len(calcs)} calculators)")


@cli.command("info")
@click.argument("slug")
def info_cmd(slug: str) -> None:
    """Show detailed info for a calculator."""
    from rftools._catalog import CALCULATORS
    from rftools.exceptions import NotFoundError

    info = CALCULATORS.get(slug)
    if not info:
        click.echo(f"Error: Calculator '{slug}' not found.", err=True)
        click.echo("Run 'rftools list' to see all available calculators.", err=True)
        sys.exit(1)

    click.echo(f"\n{info.slug} — {info.title} ({info.category})")
    if info.description:
        click.echo(f"\n{info.description}\n")

    click.echo("INPUTS")
    for inp in info.inputs:
        unit_str = f" ({inp.unit})" if inp.unit else ""
        extras = []
        if inp.min is not None:
            extras.append(f"min: {inp.min}")
        if inp.max is not None:
            extras.append(f"max: {inp.max}")
        extras_str = f"  [{', '.join(extras)}]" if extras else ""
        click.echo(f"  {inp.key:<24} {inp.label}{unit_str}  (default: {inp.default}){extras_str}")

    click.echo("\nOUTPUTS")
    for out in info.outputs:
        unit_str = f"  {out.unit}" if out.unit else ""
        click.echo(f"  {out.key:<24} {out.label}{unit_str}")


@cli.command("version")
def version_cmd() -> None:
    """Show rftools library version."""
    click.echo(f"rftools {__version__}")
