"""Read raw GPX, generate separate datasets, or compare with preserved outputs."""

from __future__ import annotations

import argparse
import json
from pathlib import Path
from typing import Sequence

from mountain_twin.trails.comparison import compare_datasets, format_report
from mountain_twin.trails.gpx import ingest_routes
from mountain_twin.trails.outputs import generate


def main(argv: Sequence[str] | None = None) -> int:
    """CLI: 0 success, 1 comparison needs review, 2 invalid input or I/O error."""
    parser = argparse.ArgumentParser(description=__doc__)
    subparsers = parser.add_subparsers(dest="command", required=True)
    for command in ("ingest", "generate"):
        sub = subparsers.add_parser(
            command,
            help="Validate raw input only"
            if command == "ingest"
            else "Generate CSV/GeoJSON into a new or empty directory",
        )
        sub.add_argument("--registry", type=Path, default=Path("data/route_registry.json"))
        sub.add_argument("--raw-dir", type=Path, default=Path("data/raw/gpx"))
        if command == "generate":
            sub.add_argument("--output", type=Path, default=Path("data/generated"))
    validate = subparsers.add_parser(
        "validate", help="Compare generated route data with preserved baseline"
    )
    validate.add_argument("--generated", type=Path, default=Path("data/generated"))
    validate.add_argument("--preserved", type=Path, default=Path("data/processed"))
    validate.add_argument("--json", action="store_true", help="Print machine-readable report")
    args = parser.parse_args(argv)
    try:
        if args.command == "validate":
            report = compare_datasets(args.generated, args.preserved)
            print(
                json.dumps(report, indent=2, sort_keys=True, allow_nan=False)
                if args.json
                else format_report(report)
            )
            return 0 if report["within_tolerance"] else 1
        routes = ingest_routes(args.registry, args.raw_dir)
        print(
            f"Parsed {len(routes)} routes, {sum(len(r.points) for r in routes)} points; raw files unchanged."
        )
        if args.command == "generate":
            # Protect both checkout inputs and locations implied by custom inputs.
            target = args.output.resolve()
            for source in (
                args.raw_dir.resolve(),
                args.registry.resolve(),
                Path("data/processed").resolve(),
                Path("data/geojson").resolve(),
            ):
                if target == source or source in target.parents or target in source.parents:
                    raise ValueError(f"output overlaps input: {source}")
            generate(routes, args.output, args.registry.resolve().parent)
            print(f"Generated separate outputs in {args.output}; no solar outputs generated.")
        return 0
    except (OSError, ValueError, KeyError, TypeError) as exc:
        print(f"ERROR: {exc}")
        return 2


if __name__ == "__main__":
    raise SystemExit(main())
