#!/usr/bin/env python3
"""验证运控标定现场数据文件、dataset_index 写入和 data_input 转换链路。"""

from __future__ import annotations

import argparse
import json
import sys
from pathlib import Path

from control_data_common import (
    CHASSIS_RESPONSE_FIELDS,
    CONTROL_EVALUATION_FIELDS,
    REFERENCE_SIGNAL_FIELDS,
    TRUTH_TRAJECTORY_FIELDS,
    apply_cli_overrides,
    build_dataset_index,
    build_summary,
    copy_or_generate_file,
    load_config,
    read_csv_rows,
    resolve_path,
    synthetic_rows,
    validate_config,
    validate_control_dataset_files,
    validate_summary,
    write_yaml,
)


def parse_args() -> argparse.Namespace:
    parser = argparse.ArgumentParser(
        description="生成或校验一组运控标定现场数据，并写入 dataset_index.yaml。"
    )
    parser.add_argument(
        "--config",
        default="src/site_deployment/workshop_control_calibration_real/config/control_data_template.yaml",
        help="运控现场数据配置 YAML。",
    )
    parser.add_argument("--session-id", default="", help="覆盖 session_id。")
    parser.add_argument("--site-id", default="", help="覆盖 site_id。")
    parser.add_argument("--vehicle-id", default="", help="覆盖 vehicle_id。")
    parser.add_argument("--session-dir", default="", help="覆盖 session_dir。")
    parser.add_argument("--dataset-index-path", default="", help="覆盖 dataset_index_path。")
    parser.add_argument("--chassis-type", default="", help="覆盖 chassis_type。")
    parser.add_argument("--control-axis", default="", help="覆盖 control_axis。")
    parser.add_argument("--controller-algorithm", default="", help="覆盖 controller_algorithm。")
    parser.add_argument("--control-role", default="", help="覆盖 control_role。")
    parser.add_argument("--source-control-evaluation", default="", help="已有运控评估 CSV；为空则生成合成数据。")
    parser.add_argument("--source-reference-signal", default="", help="已有参考信号 CSV；为空则生成合成数据。")
    parser.add_argument("--source-chassis-response", default="", help="已有底盘响应 CSV；为空则生成合成数据。")
    parser.add_argument("--source-truth-trajectory", default="", help="已有真值轨迹 CSV；为空则生成合成数据。")
    return parser.parse_args()


def print_validation_result(prefix: str, errors: list[str], warnings: list[str]) -> None:
    for warning in warnings:
        print(f"[WARN] {prefix}: {warning}", file=sys.stderr)
    for error in errors:
        print(f"[ERROR] {prefix}: {error}", file=sys.stderr)


def main() -> int:
    args = parse_args()
    config_path = Path(args.config).expanduser().resolve(strict=False)
    config = load_config(config_path)
    apply_cli_overrides(config, args)

    config_result = validate_config(config, config_path)
    print_validation_result("配置检查", config_result.errors, config_result.warnings)
    if not config_result.ok:
        return 2

    session_dir = Path(str(config["session_dir"])).expanduser().resolve(strict=False)
    files = config["files"]
    target_paths = {
        "control_evaluation_data_file": resolve_path(session_dir, str(files["control_evaluation_data_file"])),
        "reference_signal_file": resolve_path(session_dir, str(files["reference_signal_file"])),
        "chassis_response_file": resolve_path(session_dir, str(files["chassis_response_file"])),
        "truth_trajectory_file": resolve_path(session_dir, str(files["truth_trajectory_file"])),
        "diagnostics_file": resolve_path(session_dir, str(files["diagnostics_file"])),
    }

    control_rows, reference_rows, chassis_rows, truth_rows = synthetic_rows(config)
    copy_or_generate_file(
        args.source_control_evaluation,
        target_paths["control_evaluation_data_file"],
        CONTROL_EVALUATION_FIELDS,
        control_rows,
    )
    copy_or_generate_file(
        args.source_reference_signal,
        target_paths["reference_signal_file"],
        REFERENCE_SIGNAL_FIELDS,
        reference_rows,
    )
    copy_or_generate_file(
        args.source_chassis_response,
        target_paths["chassis_response_file"],
        CHASSIS_RESPONSE_FIELDS,
        chassis_rows,
    )
    copy_or_generate_file(
        args.source_truth_trajectory,
        target_paths["truth_trajectory_file"],
        TRUTH_TRAJECTORY_FIELDS,
        truth_rows,
    )

    file_result = validate_control_dataset_files(target_paths)
    print_validation_result("CSV 检查", file_result.errors, file_result.warnings)
    if not file_result.ok:
        return 3

    control_rows = read_csv_rows(target_paths["control_evaluation_data_file"])
    reference_rows = read_csv_rows(target_paths["reference_signal_file"])
    chassis_rows = read_csv_rows(target_paths["chassis_response_file"])
    truth_rows = read_csv_rows(target_paths["truth_trajectory_file"])
    summary = build_summary(control_rows, reference_rows, chassis_rows, truth_rows, config)
    summary_result = validate_summary(summary, config)
    print_validation_result("摘要检查", summary_result.errors, summary_result.warnings)
    if not summary_result.ok:
        return 4

    target_paths["diagnostics_file"].parent.mkdir(parents=True, exist_ok=True)
    target_paths["diagnostics_file"].write_text(
        json.dumps(summary, ensure_ascii=False, indent=2),
        encoding="utf-8",
    )

    dataset_index = build_dataset_index(config, summary, target_paths, config_path)
    dataset_index_path = Path(str(config["dataset_index_path"])).expanduser().resolve(strict=False)
    write_yaml(dataset_index_path, dataset_index)

    print(f"[OK] 已写入运控评估数据: {target_paths['control_evaluation_data_file']}", file=sys.stderr)
    print(f"[OK] 已写入运控数据集索引: {dataset_index_path}", file=sys.stderr)
    print(f"[OK] 运控 RMS 横向误差: {summary['rms_lateral_error_m']:.6f} m", file=sys.stderr)
    return 0


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