"""Scene manifest — single source of truth for all benchmark scenes.

Two pipelines:
  TRAIN_SCENES — V5 PPO models on new 2000x600 config (uniform, free-slip).
  REPRODUCE_SCENES — legacy PPO models on old 1280x512 config (parabolic, bounce-back).

Usage:
    from eval.scene_manifest import TRAIN_SCENES, REPRODUCE_SCENES

Each scene dict contains:
    scene_id, config_path, calibration_path, si, num_steps, scene_type
    seeds: list of (seed_label, model_dir) tuples
"""
from __future__ import annotations

import os
from pathlib import Path
from typing import Any, Dict, List

_REPO = Path(__file__).resolve().parents[3]
_TRAIN_DIR = _REPO / "src" / "drl_pinball" / "train"
_CONFIGS_DIR = _REPO / "configs"

KARMAN_CFG = str(_CONFIGS_DIR / "config_lbm_karman_2000x600.json")
KARMAN_CFG_RE60 = str(_CONFIGS_DIR / "config_lbm_karman_2000x600_re60.json")
KARMAN_CFG_RE200 = str(_CONFIGS_DIR / "config_lbm_karman_2000x600_re200.json")
KARMAN_CFG_RE400 = str(_CONFIGS_DIR / "config_lbm_karman_2000x600_re400.json")
PINBALL_CFG = str(_CONFIGS_DIR / "config_lbm_pinball.json")


def _model_dir(case_name: str, seed: int) -> str:
    """Path to model output directory for a trained case."""
    return str(_TRAIN_DIR / "output" / f"{case_name}_seed{seed}" / "models")


def _cal_path(name: str) -> str:
    return str(_TRAIN_DIR / "calibrations" / name / "calibration.json")


# =============================================================================
# TRAIN SCENES (V5 PPO, 2000x600)
#
# Cloud naming: {kar|ill}_{case}_{sc|tr}_seed{N}
#   sc = scratch, tr = transfer
# =============================================================================
TRAIN_SCENES: List[Dict[str, Any]] = [
    # -- Karman Cloak Re100 scratch (5 seeds, best model) --
    {
        "scene_id": "kar_re100_sc",
        "config_path": KARMAN_CFG,
        "calibration_path": _cal_path("kar_re100"),
        "si": 800,
        "num_steps": 360,
        "scene_type": "karman",
        "seeds": [
            ("41", _model_dir("kar_re100_sc", 41)),
            ("42", _model_dir("kar_re100_sc", 42)),
            ("43", _model_dir("kar_re100_sc", 43)),
            ("44", _model_dir("kar_re100_sc", 44)),
            ("45", _model_dir("kar_re100_sc", 45)),
        ],
    },
    # -- Cross-Re Re60 scratch + transfer --
    {
        "scene_id": "kar_re60_tr",
        "config_path": KARMAN_CFG_RE60,
        "calibration_path": _cal_path("kar_re60"),
        "si": 800,
        "num_steps": 360,
        "scene_type": "karman",
        "seeds": [
            ("43", _model_dir("kar_re60_tr", 43)),
        ],
    },
    # -- Cross-Re Re200 scratch + transfer --
    {
        "scene_id": "kar_re200_tr",
        "config_path": KARMAN_CFG_RE200,
        "calibration_path": _cal_path("kar_re200"),
        "si": 500,
        "num_steps": 360,
        "scene_type": "karman",
        "seeds": [
            ("43", _model_dir("kar_re200_tr", 43)),
        ],
    },
    # -- Cross-Re Re400 scratch + transfer --
    {
        "scene_id": "kar_re400_tr",
        "config_path": KARMAN_CFG_RE400,
        "calibration_path": _cal_path("kar_re400"),
        "si": 400,
        "num_steps": 360,
        "scene_type": "karman",
        "seeds": [
            ("43", _model_dir("kar_re400_tr", 43)),
        ],
    },
    # -- VarDist d075 scratch --
    {
        "scene_id": "kar_d075_sc",
        "config_path": KARMAN_CFG,
        "calibration_path": _cal_path("kar_d075_sc"),
        "si": 800,
        "num_steps": 360,
        "scene_type": "karman",
        "seeds": [
            ("44", _model_dir("kar_d075_sc", 44)),
        ],
    },
    # -- VarDist d15 scratch --
    {
        "scene_id": "kar_d15_sc",
        "config_path": KARMAN_CFG,
        "calibration_path": _cal_path("kar_d15_sc"),
        "si": 800,
        "num_steps": 360,
        "scene_type": "karman",
        "seeds": [
            ("45", _model_dir("kar_d15_sc", 45)),
        ],
    },
    # -- VarDist d2 scratch --
    {
        "scene_id": "kar_d2_sc",
        "config_path": KARMAN_CFG,
        "calibration_path": _cal_path("kar_d2_sc"),
        "si": 800,
        "num_steps": 360,
        "scene_type": "karman",
        "seeds": [
            ("45", _model_dir("kar_d2_sc", 45)),
        ],
    },
    # -- Illusion 0.75L scratch --
    {
        "scene_id": "ill_075L_sc",
        "config_path": KARMAN_CFG,
        "calibration_path": _cal_path("ill_075L"),
        "si": 400,
        "num_steps": 360,
        "scene_type": "illusion",
        "target_diam": 0.75,
        "seeds": [
            ("43", _model_dir("ill_075L_sc", 43)),
        ],
    },
    # -- Illusion 1.0L scratch --
    {
        "scene_id": "ill_1L_sc",
        "config_path": KARMAN_CFG,
        "calibration_path": _cal_path("ill_1L"),
        "si": 600,
        "num_steps": 360,
        "scene_type": "illusion",
        "target_diam": 1.0,
        "seeds": [
            ("43", _model_dir("ill_1L_sc", 43)),
        ],
    },
    # -- Illusion 1.5L scratch --
    {
        "scene_id": "ill_15L_sc",
        "config_path": KARMAN_CFG,
        "calibration_path": _cal_path("ill_15L"),
        "si": 800,
        "num_steps": 360,
        "scene_type": "illusion",
        "target_diam": 1.5,
        "seeds": [
            ("43", _model_dir("ill_15L_sc", 43)),
        ],
    },
    # -- Illusion 2.0L scratch (new!) --
    {
        "scene_id": "ill_2L_sc",
        "config_path": KARMAN_CFG,
        "calibration_path": _cal_path("ill_2L"),
        "si": 800,
        "num_steps": 360,
        "scene_type": "illusion",
        "target_diam": 2.0,
        "seeds": [
            ("43", _model_dir("ill_2L_sc", 43)),
        ],
    },
]

# =============================================================================
# REPRODUCE SCENES (legacy PPO, 1280x512)
# =============================================================================
REPRODUCE_SCENES: List[Dict[str, Any]] = [
    {
        "scene_id": "karman_cloak",
        "config_path": PINBALL_CFG,
        "si": 800,
        "num_steps": 200,
        "scene_type": "karman",
        "model_name": "d1a3o12_re100",
        "action_scale": 8.0,
        "action_bias": (0.0, -4.0, 4.0),
    },
    {
        "scene_id": "steady_cloak",
        "config_path": PINBALL_CFG,
        "si": 800,
        "num_steps": 200,
        "scene_type": "steady",
        "model_name": None,  # open-loop [0, -5.1, 5.1]*U0
        "action_scale": 8.0,
        "action_bias": (0.0, -4.0, 4.0),
        "open_loop_surf_vel": (0.0, -5.1, 5.1),
    },
    {
        "scene_id": "illusion_075L",
        "config_path": PINBALL_CFG,
        "si": 400,
        "num_steps": 200,
        "scene_type": "illusion",
        "model_name": "d1a3o14_250525_imit_075L_2U_400S",
        "action_scale": 8.0,
        "action_bias": (0.0, -2.0, 2.0),
        "target_diam": 0.75,
    },
    {
        "scene_id": "illusion_1L",
        "config_path": PINBALL_CFG,
        "si": 600,
        "num_steps": 200,
        "scene_type": "illusion",
        "model_name": "d1a3o14_250525_imit_1L_2U_600S",
        "action_scale": 8.0,
        "action_bias": (0.0, -2.0, 2.0),
        "target_diam": 1.0,
    },
    {
        "scene_id": "illusion_15L",
        "config_path": PINBALL_CFG,
        "si": 800,
        "num_steps": 200,
        "scene_type": "illusion",
        "model_name": "d1a3o14_250525_imit_15L_2U",
        "action_scale": 8.0,
        "action_bias": (0.0, -2.0, 2.0),
        "target_diam": 1.5,
    },
    {
        "scene_id": "vortex_lamb",
        "config_path": PINBALL_CFG,
        "si": 800,
        "num_steps": 150,
        "scene_type": "vortex",
        "model_name": "vortex_lamb",
        "action_scale": 4.0,
        "action_bias": (0.0, -4.0, 4.0),
        "vortex_type": "lamb",
        "vortex_strength_factor": 0.5,
    },
    {
        "scene_id": "vortex_taylor",
        "config_path": PINBALL_CFG,
        "si": 800,
        "num_steps": 150,
        "scene_type": "vortex",
        "model_name": "vortex_taylor",
        "action_scale": 4.0,
        "action_bias": (0.0, -4.0, 4.0),
        "vortex_type": "taylor",
        "vortex_strength_factor": 0.03,
    },
]
