"""チェックボックス方式の確認ダイアログ（枝番ファイル結合〔4.7〕のグループ選択で使用）。

項目（枝番ファイル結合の候補グループ）ごとに個別のチェックボックスを持つ、一括実行／
スキップの二択ではないダイアログ。枝番ファイル結合は複数ファイルにまたがる決定であり、
逐次レビュー画面（write_review_dialog.py）の1ファイル単位の仕組みにはなじまない
ため、候補一覧をまとめて提示しつつグループ単位で選択できるようにする
（CLAUDE.md「絶対に譲れない設計原則」3の「チェックボックスで選択」要件に対応）。
"""

from __future__ import annotations

import tkinter as tk
from dataclasses import dataclass
from tkinter import ttk


@dataclass(frozen=True)
class ChecklistItem:
    key: str
    before_text: str
    after_text: str
    default_checked: bool = True


class ChecklistDialog(tk.Toplevel):
    def __init__(
        self,
        parent: tk.Misc,
        title: str,
        description: str,
        items: list[ChecklistItem],
    ) -> None:
        super().__init__(parent)
        self.title(title)
        self.geometry("750x550")
        self.transient(parent)
        self.grab_set()

        self.result: dict[str, bool] | None = None
        self._vars: dict[str, tk.BooleanVar] = {}

        ttk.Label(self, text=description, wraplength=700, justify="left", padding=12).pack(
            side=tk.TOP, fill=tk.X
        )
        self.count_label = ttk.Label(
            self, text=f"対象：{len(items)} 件", padding=(12, 0, 12, 8), anchor="w"
        )
        self.count_label.pack(side=tk.TOP, fill=tk.X)

        list_frame = ttk.Frame(self)
        list_frame.pack(side=tk.TOP, fill=tk.BOTH, expand=True, padx=12)
        canvas = tk.Canvas(list_frame)
        vsb = ttk.Scrollbar(list_frame, orient="vertical", command=canvas.yview)
        canvas.configure(yscrollcommand=vsb.set)
        canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        vsb.pack(side=tk.LEFT, fill=tk.Y)

        inner = ttk.Frame(canvas)
        canvas.create_window((0, 0), window=inner, anchor="nw")
        inner.bind(
            "<Configure>", lambda e: canvas.configure(scrollregion=canvas.bbox("all"))
        )

        for item in items:
            var = tk.BooleanVar(value=item.default_checked)
            self._vars[item.key] = var
            row = ttk.Frame(inner)
            row.pack(side=tk.TOP, fill=tk.X, pady=4, anchor="w")
            ttk.Checkbutton(row, variable=var).pack(side=tk.LEFT, anchor="n")
            ttk.Label(
                row,
                text=f"{item.before_text}\n  → {item.after_text}",
                justify="left",
                wraplength=650,
            ).pack(side=tk.LEFT, anchor="w")

        button_frame = ttk.Frame(self, padding=12)
        button_frame.pack(side=tk.BOTTOM, fill=tk.X)
        ttk.Button(button_frame, text="中止（結合しない）", command=self._on_cancel).pack(
            side=tk.RIGHT, padx=(6, 0)
        )
        ttk.Button(button_frame, text="この内容で実行", command=self._on_execute).pack(
            side=tk.RIGHT
        )

        self.protocol("WM_DELETE_WINDOW", self._on_cancel)

    def _on_execute(self) -> None:
        self.result = {key: var.get() for key, var in self._vars.items()}
        self.destroy()

    def _on_cancel(self) -> None:
        self.result = None
        self.destroy()


def ask_checklist(
    parent: tk.Misc, title: str, description: str, items: list[ChecklistItem]
) -> dict[str, bool] | None:
    """チェックリストダイアログを表示し、キーごとのON/OFF結果を返す。

    ウィンドウを閉じる・「中止」を選んだ場合はNone（呼び出し側はこれを
    「対象なし」と同義に扱うこと）。
    """
    dialog = ChecklistDialog(parent, title, description, items)
    parent.wait_window(dialog)
    return dialog.result
