"""
CLI for yoro-maps.

Usage::

    yoromaps download ML --output mali.yoromaps
    yoromaps download ML --output mali.yoromaps --tiles --zoom-max 14
    yoromaps route mali.yoromaps ML-ABC ML-XYZ
    yoromaps info mali.yoromaps
"""

from __future__ import annotations

import argparse
import json
import sys

from yoromaps.countries import COUNTRIES


def _progress(msg, current, total):
    if total > 0:
        pct = current / total * 100
        print(f"\r  {msg}: {pct:.0f}% ({current}/{total})", end="", flush=True)
    else:
        print(f"\r  {msg}", end="", flush=True)


def _download(args):
    from yoromaps.download import build

    code = args.country.upper()
    if code not in COUNTRIES:
        print(f"Unknown country: {code}. Available: {', '.join(sorted(COUNTRIES))}", file=sys.stderr)
        sys.exit(1)

    output = args.output or f"{code.lower()}.yoromaps"
    print(f"Building {output} for {COUNTRIES[code].name}...")

    build(
        code,
        output=output,
        pbf_path=args.pbf,
        include_tiles=args.tiles,
        zoom_min=args.zoom_min,
        zoom_max=args.zoom_max,
        progress=_progress,
    )
    print(f"\nDone: {output}")


def _route(args):
    from yoromaps.db import open_db
    from yoromaps.routing import route_from_codes

    conn = open_db(args.db)
    legs = route_from_codes(conn, args.codes)
    conn.close()

    total_km = sum(leg.distance_km for leg in legs)
    total_min = sum(leg.duration_min for leg in legs)

    result = {
        "total_distance_km": total_km,
        "total_duration_min": total_min,
        "legs": [
            {
                "distance_km": leg.distance_km,
                "duration_min": leg.duration_min,
                "found": leg.found,
                "steps": leg.steps,
            }
            for leg in legs
        ],
    }
    print(json.dumps(result, indent=2))


def _update(args):
    from yoromaps.download import update

    print(f"Updating {args.db}...")
    result = update(args.db, progress=_progress)
    print()

    if result["updated"]:
        print(f"Updated: {result['nodes']:,} nodes, {result['edges']:,} edges")
        if result["previous_date"]:
            print(f"Previous: {result['previous_date']}")
        print(f"New:      {result['new_date']}")
    else:
        print(f"Already up to date (last update: {result['previous_date'] or 'unknown'})")
        print(f"Graph: {result['nodes']:,} nodes, {result['edges']:,} edges")


def _info(args):
    from yoromaps.db import open_db, get_metadata
    from yoromaps.tiles import tile_count

    conn = open_db(args.db)
    print(f"Database: {args.db}")
    for key in ("country", "country_name", "bbox", "graph_nodes", "graph_edges", "tiles_count"):
        val = get_metadata(conn, key)
        if val:
            print(f"  {key}: {val}")
    tc = tile_count(conn)
    if tc:
        print(f"  tiles_in_db: {tc}")
    conn.close()


def _countries(args):
    for code, c in sorted(COUNTRIES.items()):
        print(f"  {code}  {c.name}")


def main():
    parser = argparse.ArgumentParser(prog="yoromaps", description="Offline maps & routing for Africa")
    sub = parser.add_subparsers(dest="command")

    # download
    dl = sub.add_parser("download", help="Download and build a .yoromaps file")
    dl.add_argument("country", help="ISO country code (e.g. ML, BF, CI)")
    dl.add_argument("--output", "-o", help="Output file path")
    dl.add_argument("--pbf", help="Use existing PBF file instead of downloading")
    dl.add_argument("--tiles", action="store_true", help="Also download map tiles")
    dl.add_argument("--zoom-min", type=int, default=6)
    dl.add_argument("--zoom-max", type=int, default=12)

    # update
    up = sub.add_parser("update", help="Update an existing .yoromaps with latest OSM data")
    up.add_argument("db", help="Path to existing .yoromaps file")
    up.add_argument("--cache-dir", help="Directory to cache PBF files")

    # route
    rt = sub.add_parser("route", help="Calculate route between Yoro codes")
    rt.add_argument("db", help="Path to .yoromaps file")
    rt.add_argument("codes", nargs="+", help="Yoro codes (e.g. ML-ABC ML-XYZ)")

    # info
    nf = sub.add_parser("info", help="Show database info")
    nf.add_argument("db", help="Path to .yoromaps file")

    # countries
    sub.add_parser("countries", help="List available countries")

    args = parser.parse_args()
    if args.command == "download":
        _download(args)
    elif args.command == "update":
        _update(args)
    elif args.command == "route":
        _route(args)
    elif args.command == "info":
        _info(args)
    elif args.command == "countries":
        _countries(args)
    else:
        parser.print_help()


if __name__ == "__main__":
    main()
