# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

"""CLI argument parsing for JSONL benchmark generation."""

import argparse
import sys
from pathlib import Path

DEFAULT_IMAGES_PER_REQUEST = 3
USER_TEXT_TOKENS = 300
COCO_ANNOTATIONS = Path(__file__).parent / "annotations" / "image_info_test2017.json"


def _positive_int(value: str) -> int:
    iv = int(value)
    if iv <= 0:
        raise argparse.ArgumentTypeError(f"must be a positive integer, got {iv}")
    return iv


def _common_parser() -> argparse.ArgumentParser:
    """Args shared across all strategies."""
    p = argparse.ArgumentParser(add_help=False)
    p.add_argument(
        "-o",
        "--output",
        type=Path,
        default=None,
        help="Output .jsonl path (default: auto-generated from parameters)",
    )
    p.add_argument(
        "--user-text-tokens",
        type=int,
        default=USER_TEXT_TOKENS,
        help=f"Target user text tokens per request (default: {USER_TEXT_TOKENS})",
    )
    p.add_argument(
        "--seed",
        type=int,
        default=None,
        help="Random seed for reproducible generation (default: time-based)",
    )
    return p


def _image_parser() -> argparse.ArgumentParser:
    """Args for image generation (reusable for future video/audio parsers)."""
    p = argparse.ArgumentParser(add_help=False)
    p.add_argument(
        "--image-size",
        type=int,
        nargs=2,
        default=[512, 512],
        metavar=("WIDTH", "HEIGHT"),
        help="Size of generated PNG images in pixels (default: 512 512)",
    )
    p.add_argument(
        "--image-dir",
        type=Path,
        default=Path("/tmp/bench_images"),
        help="Directory to save generated PNG images (default: /tmp/bench_images)",
    )
    p.add_argument(
        "--image-mode",
        choices=["base64", "http"],
        default="base64",
        help="'base64' generates local PNGs (default); 'http' uses COCO URLs",
    )
    p.add_argument(
        "--coco-annotations",
        type=Path,
        default=COCO_ANNOTATIONS,
        help=f"Path to COCO image_info JSON for --image-mode http (default: {COCO_ANNOTATIONS})",
    )
    return p


def parse_args(description: str = "") -> argparse.Namespace:
    common = _common_parser()
    image = _image_parser()

    parser = argparse.ArgumentParser(
        description=description,
        formatter_class=argparse.RawDescriptionHelpFormatter,
    )
    sub = parser.add_subparsers(dest="strategy")

    # --- single-turn (default) ---
    st = sub.add_parser(
        "single-turn",
        parents=[common, image],
        help="Independent requests with random image sampling (default)",
    )
    st.add_argument(
        "-n",
        "--num-requests",
        type=int,
        default=500,
        help="Number of requests to generate (default: 500)",
    )
    st.add_argument(
        "--images-per-request",
        type=int,
        default=DEFAULT_IMAGES_PER_REQUEST,
        help=f"Number of images per request (default: {DEFAULT_IMAGES_PER_REQUEST})",
    )
    st.add_argument(
        "--images-pool",
        type=int,
        default=None,
        help="Unique images in pool. Smaller pool = more cross-request reuse. "
        "Default: num_requests * images_per_request (all unique).",
    )

    # --- sliding-window ---
    sw = sub.add_parser(
        "sliding-window",
        parents=[common, image],
        help="Causal sessions with sliding-window image overlap",
    )
    sw.add_argument(
        "--num-users",
        type=_positive_int,
        default=10,
        help="Number of concurrent user sessions (default: 10)",
    )
    sw.add_argument(
        "--turns-per-user",
        type=_positive_int,
        default=20,
        help="Number of requests per user (default: 20)",
    )
    sw.add_argument(
        "--window-size",
        type=_positive_int,
        default=5,
        help="Sliding window width — each turn sees this many images, "
        "with window_size-1 overlap between consecutive turns (default: 5)",
    )

    # Default to single-turn when no subcommand given, but let top-level
    # `-h`/`--help` flow through the main parser so users see both
    # subcommands and the module description.
    known_strategies = {"single-turn", "sliding-window"}
    argv = sys.argv[1:]
    help_requested = bool(argv) and argv[0] in {"-h", "--help"}
    if not help_requested and (not argv or argv[0] not in known_strategies):
        argv = ["single-turn", *argv]

    return parser.parse_args(argv)
