"""MiniTIAS 白板画像の照明均一性評価スクリプト.

使い方（単一画像）:
    python scripts/run_uniformity.py --image data/minitias/whiteboard/xxx.png
    python scripts/run_uniformity.py --image data/minitias/whiteboard/xxx.png \\
        --config config/roi_config.json --roi minitias.whiteboard

使い方（ディレクトリ一括）:
    python scripts/run_uniformity.py --image data/minitias/whiteboard/
"""

import argparse
import json
import sys
from pathlib import Path

# プロジェクトルートを sys.path に追加（スクリプトを任意の場所から実行できるよう）
PROJECT_ROOT = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(PROJECT_ROOT))

from src.analysis.uniformity import calc_uniformity, to_grayscale  # noqa: E402
from src.export.exporter import (  # noqa: E402
    ensure_output_dirs,
    export_results,
    export_summary,
)
from src.io.loader import extract_roi, load_image  # noqa: E402
from src.visualization.plotter import plot_histogram, plot_luminance_map  # noqa: E402


def load_roi_config(config_path: str, roi_key: str) -> dict | None:
    """ROI 設定ファイルを読み込んで指定キーの ROI を返す．

    Args:
        config_path: JSON 設定ファイルのパス．
        roi_key: ドット区切りのキー（例: "minitias.whiteboard"）．

    Returns:
        ROI の辞書（x, y, width, height）．キーが存在しない場合は None．

    Raises:
        FileNotFoundError: 設定ファイルが存在しない場合．
    """
    config_file = Path(config_path)
    if not config_file.exists():
        raise FileNotFoundError(f"設定ファイルが見つかりません: {config_path}")

    with config_file.open(encoding="utf-8") as f:
        config = json.load(f)

    # ドット区切りでネストされたキーを辿る
    node = config
    for key in roi_key.split("."):
        if not isinstance(node, dict) or key not in node:
            return None
        node = node[key]

    return node if isinstance(node, dict) else None


def analyze_single_image(
    image_path: str,
    roi: dict | None,
    output_base: Path,
) -> dict | None:
    """1 枚の画像を解析し，結果を出力する．

    Args:
        image_path: 解析対象画像のパス．
        roi: ROI の辞書（x, y, width, height）．None の場合は画像全体を解析．
        output_base: 出力ルートディレクトリのパス．

    Returns:
        均一性指標に image_name を加えた辞書．エラー時は None．
    """
    print(f"解析開始: {image_path}")

    # 画像読み込み
    image = load_image(image_path)
    print(f"画像サイズ: {image.shape[1]} x {image.shape[0]} px")

    # ROI 切り出し
    if roi is not None:
        print(
            f"ROI を適用します: x={roi['x']}, y={roi['y']}, "
            f"width={roi['width']}, height={roi['height']}"
        )
        region = extract_roi(image, roi["x"], roi["y"], roi["width"], roi["height"])
    else:
        print("ROI 未指定: 画像全体を解析します")
        region = image

    # 輝度変換（Rec.709）
    luminance = to_grayscale(region)

    # 均一性指標算出
    results = calc_uniformity(luminance)
    print("--- 均一性指標 ---")
    print(f"  平均輝度     : {results['mean']:.2f}")
    print(f"  標準偏差     : {results['std']:.2f}")
    print(f"  CoV          : {results['cov']:.4f}")
    print(f"  最大/最小比  : {results['max_min_ratio']:.4f}")
    print(f"  最大輝度     : {results['max']:.2f}")
    print(f"  最小輝度     : {results['min']:.2f}")

    # 出力ファイル名（入力ファイル名ベース）
    stem = Path(image_path).stem

    # 可視化
    luminance_map_path = str(output_base / "figures" / f"{stem}_luminance_map.png")
    plot_luminance_map(luminance, luminance_map_path)
    plot_histogram(luminance, str(output_base / "figures" / f"{stem}_histogram.png"))

    # CSV 出力
    export_results(results, str(output_base / "results" / f"{stem}_uniformity.csv"))

    print(f"解析完了: {image_path}")

    return {"image_name": stem, **results}


def main() -> None:
    """エントリーポイント."""
    parser = argparse.ArgumentParser(
        description="MiniTIAS 白板画像の照明均一性を評価する．"
    )
    parser.add_argument(
        "--image",
        required=True,
        help="解析対象の画像ファイルパスまたはディレクトリパス",
    )
    parser.add_argument(
        "--config",
        default=str(PROJECT_ROOT / "config" / "roi_config.json"),
        help="ROI 設定ファイルのパス（デフォルト: config/roi_config.json）",
    )
    parser.add_argument(
        "--roi",
        default="minitias.whiteboard",
        help="ROI のキー（ドット区切り，デフォルト: minitias.whiteboard）",
    )
    parser.add_argument(
        "--output",
        default=str(PROJECT_ROOT / "output"),
        help="出力ディレクトリのパス（デフォルト: output/）",
    )
    args = parser.parse_args()

    output_base = Path(args.output)
    ensure_output_dirs(args.output)

    # ROI 設定読み込み
    roi = None
    if args.config:
        try:
            roi = load_roi_config(args.config, args.roi)
        except FileNotFoundError as e:
            print(f"警告: {e}  → 画像全体を解析します")

    image_target = Path(args.image)

    if image_target.is_dir():
        # バッチ解析: ディレクトリ内の全 PNG を処理
        png_files = sorted(image_target.glob("*.png"))
        if not png_files:
            print(f"PNG ファイルが見つかりません: {image_target}")
            return

        print(f"バッチ解析: {len(png_files)} 枚の画像を処理します")

        all_results: list[dict] = []
        for png_path in png_files:
            try:
                result = analyze_single_image(str(png_path), roi, output_base)
                if result is not None:
                    all_results.append(result)
            except Exception as e:
                print(f"エラー（スキップ）: {png_path} — {e}")

        # まとめ CSV 出力
        if all_results:
            summary_path = str(output_base / "results" / "summary_uniformity.csv")
            export_summary(all_results, summary_path)

        print(f"バッチ解析完了: {len(all_results)} / {len(png_files)} 枚成功")

    else:
        # 単一画像解析（後方互換）
        analyze_single_image(args.image, roi, output_base)


if __name__ == "__main__":
    main()
