"""Operator CLI for worker-local public dataset admission."""

from __future__ import annotations

import json
from pathlib import Path
from typing import Annotated

import typer

from k1link.datasets.goose_admission import GooseAdmissionError, admit_goose_validation
from k1link.datasets.goose_benchmark import (
    benchmark_goose_current_ground,
    benchmark_goose_patchwork_ground,
)
from k1link.datasets.goose_qualification import qualify_goose_ground
from k1link.datasets.goose_review import build_goose_ground_review_pack
from k1link.datasets.rellis_smoke import (
    RellisSmokeError,
    build_rellis_official_smoke_preview,
)

app = typer.Typer(
    add_completion=False,
    help="Admit public perception datasets without moving source data off worker D.",
)


@app.command("admit-goose-validation")
def admit_goose_validation_command(
    dataset_root: Annotated[
        Path,
        typer.Option("--dataset-root", exists=True, file_okay=False, resolve_path=True),
    ],
    archive: Annotated[
        Path | None,
        typer.Option("--archive", exists=True, dir_okay=False, resolve_path=True),
    ] = None,
    preview_points: Annotated[
        int,
        typer.Option("--preview-points", min=1, max=50_000),
    ] = 50_000,
) -> None:
    """Verify the pinned GOOSE validation archive and import one native scan."""

    try:
        manifest = admit_goose_validation(
            dataset_root,
            archive_path=archive,
            preview_points=preview_points,
        )
    except GooseAdmissionError as exc:
        typer.echo(str(exc), err=True)
        raise typer.Exit(code=2) from exc
    typer.echo(json.dumps(manifest, ensure_ascii=False, sort_keys=True))


@app.command("benchmark-goose-current-ground")
def benchmark_goose_current_ground_command(
    dataset_root: Annotated[
        Path,
        typer.Option("--dataset-root", exists=True, file_okay=False, resolve_path=True),
    ],
) -> None:
    """Score the existing Mission Core ground baseline against GOOSE labels."""

    try:
        report = benchmark_goose_current_ground(dataset_root)
    except GooseAdmissionError as exc:
        typer.echo(str(exc), err=True)
        raise typer.Exit(code=2) from exc
    typer.echo(json.dumps(report, ensure_ascii=False, sort_keys=True))


@app.command("benchmark-goose-patchwork-ground")
def benchmark_goose_patchwork_ground_command(
    dataset_root: Annotated[
        Path,
        typer.Option("--dataset-root", exists=True, file_okay=False, resolve_path=True),
    ],
) -> None:
    """Compare current and pinned Patchwork++ providers against GOOSE labels."""

    try:
        report = benchmark_goose_patchwork_ground(dataset_root)
    except (GooseAdmissionError, ValueError) as exc:
        typer.echo(str(exc), err=True)
        raise typer.Exit(code=2) from exc
    typer.echo(json.dumps(report, ensure_ascii=False, sort_keys=True))


@app.command("qualify-goose-ground")
def qualify_goose_ground_command(
    dataset_root: Annotated[
        Path,
        typer.Option("--dataset-root", exists=True, file_okay=False, resolve_path=True),
    ],
    runs_root: Annotated[
        Path,
        typer.Option("--runs-root", file_okay=False, resolve_path=True),
    ],
    mission_core_commit: Annotated[
        str,
        typer.Option("--mission-core-commit", min=7, max=64),
    ],
    workers: Annotated[
        int,
        typer.Option("--workers", min=1, max=32),
    ] = 8,
) -> None:
    """Run the immutable GOOSE validation-split ground qualification."""

    try:
        report = qualify_goose_ground(
            dataset_root,
            runs_root,
            mission_core_commit=mission_core_commit,
            parallel_workers=workers,
        )
    except (GooseAdmissionError, ValueError) as exc:
        typer.echo(str(exc), err=True)
        raise typer.Exit(code=2) from exc
    typer.echo(json.dumps(report, ensure_ascii=False, sort_keys=True))


@app.command("build-goose-ground-review")
def build_goose_ground_review_command(
    dataset_root: Annotated[
        Path,
        typer.Option("--dataset-root", exists=True, file_okay=False, resolve_path=True),
    ],
    runs_root: Annotated[
        Path,
        typer.Option("--runs-root", exists=True, file_okay=False, resolve_path=True),
    ],
    run_id: Annotated[
        str,
        typer.Option("--run-id", min=1, max=128),
    ],
    workers: Annotated[
        int,
        typer.Option("--workers", min=1, max=32),
    ] = 8,
    preview_points: Annotated[
        int,
        typer.Option("--preview-points", min=1, max=20_000),
    ] = 12_000,
) -> None:
    """Publish bounded visual playback for every frame of a completed run."""

    try:
        manifest = build_goose_ground_review_pack(
            dataset_root,
            runs_root,
            run_id=run_id,
            parallel_workers=workers,
            preview_points=preview_points,
        )
    except (GooseAdmissionError, ValueError) as exc:
        typer.echo(str(exc), err=True)
        raise typer.Exit(code=2) from exc
    typer.echo(json.dumps(manifest, ensure_ascii=False, sort_keys=True))


@app.command("build-rellis-smoke-preview")
def build_rellis_smoke_preview_command(
    points: Annotated[
        Path,
        typer.Option("--points", exists=True, dir_okay=False, resolve_path=True),
    ],
    labels: Annotated[
        Path,
        typer.Option("--labels", exists=True, dir_okay=False, resolve_path=True),
    ],
    out: Annotated[
        Path,
        typer.Option("--out", dir_okay=False, resolve_path=True),
    ],
    preview_points: Annotated[
        int,
        typer.Option("--preview-points", min=1, max=50_000),
    ] = 20_000,
) -> None:
    """Verify the pinned official RELLIS example and publish a bounded preview."""

    try:
        preview = build_rellis_official_smoke_preview(
            points,
            labels,
            out,
            preview_points=preview_points,
        )
    except RellisSmokeError as exc:
        typer.echo(str(exc), err=True)
        raise typer.Exit(code=2) from exc
    typer.echo(
        json.dumps(
            {
                "source_id": preview["source_id"],
                "frame_id": preview["frame_id"],
                "source_point_count": preview["source_point_count"],
                "preview_point_count": preview["point_count"],
            },
            ensure_ascii=False,
            sort_keys=True,
        )
    )


if __name__ == "__main__":
    app()
