from __future__ import annotations

import argparse
import json
import sys

from .live_coach import LiveCoachConfig, run_live_coach
from .service import AssettoCoachService


def _print_json(value: object) -> None:
    print(json.dumps(value, indent=2))


def build_parser() -> argparse.ArgumentParser:
    parser = argparse.ArgumentParser(prog="ac-coach-mcp")
    subparsers = parser.add_subparsers(dest="command", required=True)

    subparsers.add_parser("health")
    subparsers.add_parser("snapshot")
    subparsers.add_parser("library")
    subparsers.add_parser("verify-moza-plugin")
    install_moza = subparsers.add_parser("install-moza-plugin")
    install_moza.add_argument("--disable", action="store_true")
    install_bridge = subparsers.add_parser("install-bridge-app")
    install_bridge.add_argument("--disable", action="store_true")

    list_sessions = subparsers.add_parser("list-sessions")
    list_sessions.add_argument("--limit", type=int, default=10)

    capture_run = subparsers.add_parser("capture-run")
    capture_run.add_argument("--seconds", type=float, default=120.0)
    capture_run.add_argument("--hz", type=float, default=50.0)
    capture_run.add_argument("--label", type=str, default=None)

    capture_laps = subparsers.add_parser("capture-laps")
    capture_laps.add_argument("--laps", type=int, default=3)
    capture_laps.add_argument("--hz", type=float, default=50.0)
    capture_laps.add_argument("--max-seconds", type=float, default=1800.0)
    capture_laps.add_argument("--label", type=str, default=None)

    analyze = subparsers.add_parser("analyze")
    analyze.add_argument("--session-id", type=str, default=None)

    compare_laps = subparsers.add_parser("compare-laps")
    compare_laps.add_argument("--session-id", type=str, default=None)
    compare_laps.add_argument("--slower-lap", type=int, default=None)
    compare_laps.add_argument("--reference-lap", type=int, default=None)

    recommend = subparsers.add_parser("recommend-training")
    recommend.add_argument("--no-setups", action="store_true")

    write_setup = subparsers.add_parser("write-training-setup")
    write_setup.add_argument("--car-model", required=True)
    write_setup.add_argument("--track", default=None)
    write_setup.add_argument("--track-layout", default=None)
    write_setup.add_argument("--profile", required=True)
    write_setup.add_argument("--setup-name", default=None)

    prepare_launch = subparsers.add_parser("prepare-training-launch")
    prepare_launch.add_argument("--stage", default="smooth_inputs")
    prepare_launch.add_argument("--launch-surface", default="content_manager")
    prepare_launch.add_argument("--apply-setup-as-last", action="store_true")
    prepare_launch.add_argument("--no-dry-run", action="store_true")

    direct_launch = subparsers.add_parser("prepare-direct-training-launch")
    direct_launch.add_argument("--car-model", required=True)
    direct_launch.add_argument("--track", required=True)
    direct_launch.add_argument("--track-layout", default=None)
    direct_launch.add_argument("--profile", required=True)
    direct_launch.add_argument("--live-mode", default="consistency")
    direct_launch.add_argument("--title", default="Custom Training Run")
    direct_launch.add_argument("--launch-surface", default="content_manager")
    direct_launch.add_argument("--apply-setup-as-last", action="store_true")
    direct_launch.add_argument("--no-dry-run", action="store_true")

    install_app = subparsers.add_parser("install-ac-app")
    install_app.add_argument("--disable", action="store_true")

    live_status = subparsers.add_parser("live-coach-status")

    start_live = subparsers.add_parser("start-live-coach")
    start_live.add_argument("--mode", default="consistency")
    start_live.add_argument("--reference-session-id", default=None)
    start_live.add_argument("--car-model", default=None)
    start_live.add_argument("--track", default=None)
    start_live.add_argument("--track-layout", default=None)
    start_live.add_argument("--mute", action="store_true")
    start_live.add_argument("--no-tts", action="store_true")
    start_live.add_argument("--max-callouts-per-lap", type=int, default=3)
    start_live.add_argument("--hz", type=float, default=20.0)
    start_live.add_argument("--zone-count", type=int, default=4)
    start_live.add_argument("--setup-profile", default=None)
    start_live.add_argument("--plan-label", default=None)

    subparsers.add_parser("stop-live-coach")

    run_live = subparsers.add_parser("run-live-coach")
    run_live.add_argument("--config", required=True)

    return parser


def main(argv: list[str] | None = None) -> int:
    parser = build_parser()
    args = parser.parse_args(argv)
    service = AssettoCoachService()
    try:
        if args.command == "health":
            _print_json(service.health())
        elif args.command == "snapshot":
            _print_json(service.snapshot())
        elif args.command == "library":
            _print_json(service.library_summary())
        elif args.command == "verify-moza-plugin":
            _print_json(service.verify_moza_plugin())
        elif args.command == "install-moza-plugin":
            _print_json(service.install_moza_plugin(enable=not args.disable))
        elif args.command == "install-bridge-app":
            _print_json(service.install_bridge_app(enable=not args.disable))
        elif args.command == "list-sessions":
            _print_json(service.list_sessions(limit=args.limit))
        elif args.command == "capture-run":
            _print_json(
                service.capture_run(
                    duration_s=args.seconds,
                    sample_hz=args.hz,
                    label=args.label,
                )
            )
        elif args.command == "capture-laps":
            _print_json(
                service.capture_laps(
                    lap_count=args.laps,
                    sample_hz=args.hz,
                    max_duration_s=args.max_seconds,
                    label=args.label,
                )
            )
        elif args.command == "analyze":
            _print_json(service.analyze_session(session_id=args.session_id))
        elif args.command == "compare-laps":
            _print_json(
                service.compare_laps(
                    session_id=args.session_id,
                    slower_lap_number=args.slower_lap,
                    reference_lap_number=args.reference_lap,
                )
            )
        elif args.command == "recommend-training":
            _print_json(service.recommend_training(materialize_setups=not args.no_setups))
        elif args.command == "write-training-setup":
            _print_json(
                service.materialize_training_setup(
                    car_model=args.car_model,
                    track=args.track,
                    track_layout=args.track_layout,
                    profile_id=args.profile,
                    setup_name=args.setup_name,
                )
            )
        elif args.command == "prepare-training-launch":
            _print_json(
                service.prepare_training_launch(
                    stage=args.stage,
                    apply_setup_as_last=args.apply_setup_as_last,
                    launch_surface=args.launch_surface,
                    dry_run=not args.no_dry_run,
                )
            )
        elif args.command == "prepare-direct-training-launch":
            _print_json(
                service.prepare_direct_training_launch(
                    car_model=args.car_model,
                    track=args.track,
                    track_layout=args.track_layout,
                    profile_id=args.profile,
                    live_mode=args.live_mode,
                    title=args.title,
                    apply_setup_as_last=args.apply_setup_as_last,
                    launch_surface=args.launch_surface,
                    dry_run=not args.no_dry_run,
                )
            )
        elif args.command == "install-ac-app":
            _print_json(service.install_ac_app(enable=not args.disable))
        elif args.command == "live-coach-status":
            _print_json(service.live_coach_status())
        elif args.command == "start-live-coach":
            _print_json(
                service.start_live_coach(
                    mode=args.mode,
                    reference_session_id=args.reference_session_id,
                    car_model=args.car_model,
                    track=args.track,
                    track_layout=args.track_layout,
                    tts_enabled=not args.no_tts,
                    muted=args.mute,
                    max_callouts_per_lap=args.max_callouts_per_lap,
                    sample_hz=args.hz,
                    zone_count=args.zone_count,
                    setup_profile=args.setup_profile,
                    plan_label=args.plan_label,
                )
            )
        elif args.command == "stop-live-coach":
            _print_json(service.stop_live_coach())
        elif args.command == "run-live-coach":
            config_payload = json.loads(open(args.config, "r", encoding="utf-8").read())
            run_live_coach(service.paths, LiveCoachConfig(**config_payload))
    except Exception as exc:  # pragma: no cover
        print(str(exc), file=sys.stderr)
        return 1
    return 0


if __name__ == "__main__":  # pragma: no cover
    raise SystemExit(main())
