"""
Minimal CLI for Yoro.

Usage::

    yoro encode 6.8 -5.3 --domain CI --precision 12
    yoro decode CI-4H7A3B
    yoro serve --port 8000
"""

from __future__ import annotations

import argparse
import json
import sys

from yoro import __version__
from yoro.codec import decode, domain_for_country, encode, neighbors, precision_levels, resolution


def _encode(args: argparse.Namespace) -> None:
    code = encode(args.lat, args.lon, precision=args.precision, domain=args.domain)
    decoded = decode(code)
    res = resolution(decoded["precision"], domain=args.domain)
    print(json.dumps({
        "code": code,
        "lat": decoded["lat"],
        "lon": decoded["lon"],
        "precision": decoded["precision"],
        "resolution_m": round(res, 2),
        "bounds": decoded["bounds"],
    }, indent=2))


def _decode(args: argparse.Namespace) -> None:
    decoded = decode(args.code)
    res = resolution(decoded["precision"], domain=decoded["domain"])
    nbrs = neighbors(args.code)
    print(json.dumps({
        "code": args.code.upper(),
        "lat": decoded["lat"],
        "lon": decoded["lon"],
        "precision": decoded["precision"],
        "domain": decoded["domain"],
        "resolution_m": round(res, 2),
        "bounds": decoded["bounds"],
        "neighbors": nbrs,
    }, indent=2))


def _precisions(args: argparse.Namespace) -> None:
    domain = domain_for_country(args.domain)
    levels = precision_levels(domain=domain, max_code_length=args.max_length)
    print(f"{'p':>4}  {'k (chars)':>9}  {'grid':>12}  {'total cells':>14}  {'resolution':>12}")
    print("-" * 57)
    for lv in levels:
        grid = f"{lv['grid_size']}x{lv['grid_size']}"
        print(
            f"{lv['precision']:>4}  {lv['code_length']:>9}  {grid:>12}  "
            f"{lv['total_cells']:>14,}  {lv['resolution_m']:>10.2f} m"
        )


def _serve(args: argparse.Namespace) -> None:
    try:
        import uvicorn
    except ImportError:
        print("Install FastAPI extras: pip install yoro[fastapi]", file=sys.stderr)
        sys.exit(1)

    from yoro.fastapi import create_app
    app = create_app()
    uvicorn.run(app, host=args.host, port=args.port)


def main() -> None:
    parser = argparse.ArgumentParser(
        prog="yoro",
        description="Yoro — Geographic addressing via Hilbert curves",
    )
    parser.add_argument("--version", action="version", version=f"%(prog)s {__version__}")
    sub = parser.add_subparsers(dest="command")

    # encode
    enc = sub.add_parser("encode", help="Encode GPS to Yoro")
    enc.add_argument("lat", type=float)
    enc.add_argument("lon", type=float)
    enc.add_argument("--domain", default="CI")
    enc.add_argument("--precision", type=int, default=12)

    # decode
    dec = sub.add_parser("decode", help="Decode Yoro to GPS")
    dec.add_argument("code", type=str)

    # precisions
    prec = sub.add_parser("precisions", help="Show canonical precision levels")
    prec.add_argument("--domain", default="CI")
    prec.add_argument("--max-length", type=int, default=10)

    # serve
    srv = sub.add_parser("serve", help="Start FastAPI server")
    srv.add_argument("--host", default="0.0.0.0")
    srv.add_argument("--port", type=int, default=8000)

    args = parser.parse_args()
    if args.command == "encode":
        _encode(args)
    elif args.command == "decode":
        _decode(args)
    elif args.command == "precisions":
        _precisions(args)
    elif args.command == "serve":
        _serve(args)
    else:
        parser.print_help()


if __name__ == "__main__":
    main()
