"""Argument parsing for blender_render.py.

Parses positional and named CLI arguments passed after the '--' separator
when Blender is invoked as:
  blender --background --python blender_render.py -- <glb_path> ...
"""
import json as _json
import os
import sys
from types import SimpleNamespace


def parse_args() -> SimpleNamespace:
    """Parse CLI arguments and return a SimpleNamespace of all render options."""
    argv = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
    if len(argv) < 4:
        print("Usage: blender --background --python blender_render.py -- "
              "<glb_path> <output_path> <width> <height> ...")
        sys.exit(1)

    def _arg(n, default="", transform=str):
        return transform(argv[n]) if len(argv) > n and argv[n] else default

    glb_path               = argv[0]
    output_path            = argv[1]
    width                  = int(argv[2])
    height                 = int(argv[3])
    engine                 = _arg(4, "cycles", str.lower)
    samples                = _arg(5, None, int)
    smooth_angle           = _arg(6, 30, int)
    cycles_device          = _arg(7, "auto", str.lower)
    transparent_bg         = argv[8] == "1" if len(argv) > 8 else False
    template_path          = _arg(9, "")
    target_collection      = _arg(10, "Product")
    material_library_path  = _arg(11, "")
    material_map           = _json.loads(_arg(12, "{}")) if _arg(12, "{}") else {}
    part_names_ordered     = _json.loads(_arg(13, "[]")) if _arg(13, "[]") else []
    lighting_only          = argv[14] == "1" if len(argv) > 14 else False
    shadow_catcher         = argv[15] == "1" if len(argv) > 15 else False
    rotation_x             = _arg(16, 0.0, float)
    rotation_y             = _arg(17, 0.0, float)
    rotation_z             = _arg(18, 0.0, float)
    noise_threshold        = _arg(19, "")
    denoiser               = _arg(20, "")
    denoising_input_passes = _arg(21, "")
    denoising_prefilter    = _arg(22, "")
    denoising_quality      = _arg(23, "")
    denoising_use_gpu      = _arg(24, "")

    if samples is None:
        samples = 64 if engine == "eevee" else 256

    mesh_attributes: dict = {}
    if "--mesh-attributes" in sys.argv:
        _idx = sys.argv.index("--mesh-attributes")
        try:
            mesh_attributes = _json.loads(sys.argv[_idx + 1])
        except Exception:
            pass

    usd_path = ""
    if "--usd-path" in sys.argv:
        _usd_idx = sys.argv.index("--usd-path")
        usd_path = sys.argv[_usd_idx + 1] if _usd_idx + 1 < len(sys.argv) else ""

    focal_length_mm = None
    if "--focal-length" in sys.argv:
        _fl_idx = sys.argv.index("--focal-length")
        focal_length_mm = float(sys.argv[_fl_idx + 1]) if _fl_idx + 1 < len(sys.argv) else None

    sensor_width_mm_override = None
    if "--sensor-width" in sys.argv:
        _sw_idx = sys.argv.index("--sensor-width")
        sensor_width_mm_override = float(sys.argv[_sw_idx + 1]) if _sw_idx + 1 < len(sys.argv) else None

    material_override = None
    if "--material-override" in sys.argv:
        _mo_idx = sys.argv.index("--material-override")
        material_override = sys.argv[_mo_idx + 1] if _mo_idx + 1 < len(sys.argv) else None

    if template_path and not os.path.isfile(template_path):
        print(f"[blender_render] ERROR: template not found: {template_path}")
        sys.exit(1)

    return SimpleNamespace(
        glb_path=glb_path,
        output_path=output_path,
        width=width,
        height=height,
        engine=engine,
        samples=samples,
        smooth_angle=smooth_angle,
        cycles_device=cycles_device,
        transparent_bg=transparent_bg,
        template_path=template_path,
        target_collection=target_collection,
        material_library_path=material_library_path,
        material_map=material_map,
        part_names_ordered=part_names_ordered,
        lighting_only=lighting_only,
        shadow_catcher=shadow_catcher,
        rotation_x=rotation_x,
        rotation_y=rotation_y,
        rotation_z=rotation_z,
        noise_threshold=noise_threshold,
        denoiser=denoiser,
        denoising_input_passes=denoising_input_passes,
        denoising_prefilter=denoising_prefilter,
        denoising_quality=denoising_quality,
        denoising_use_gpu=denoising_use_gpu,
        mesh_attributes=mesh_attributes,
        usd_path=usd_path,
        use_template=bool(template_path),
        focal_length_mm=focal_length_mm,
        sensor_width_mm=sensor_width_mm_override,
        material_override=material_override,
    )
