"""现代化的可折叠面板（取代 v1 的图标按钮版本）。

升级要点（保留 ``add(child, title=...)`` 旧签名兼容）：
- header 整条可点击切换展开/收起；
- 使用 Unicode chevron (▾/▸)，无需 PNG 资源；
- 新增 ``preview_textvariable``：折叠时在 header 显示当前配置摘要；
- 新增 ``header_actions``：在 header 右侧注入自定义按钮（如顶部工具条）。
"""

import tkinter
from tkinter import ttk


class CollapsingFrame(ttk.Frame):
    """A modern collapsible frame widget."""

    CHEVRON_OPEN = "\u25be"    # ▾
    CHEVRON_CLOSED = "\u25b8"  # ▸

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.columnconfigure(0, weight=1)
        self.cumulative_rows = 0
        # 兼容旧代码可能引用 self.images
        self.images: list = []

    # ------------------------------------------------------------------
    # 公共 API
    # ------------------------------------------------------------------
    def add(
        self,
        child,
        title: str = "",
        style: str = "primary.TButton",     # 兼容旧签名（不再使用）
        preview_textvariable=None,
        header_actions=None,
        **kwargs,
    ):
        """添加一个子区段到折叠面板。

        :param child: 必须是一个 ttk.Frame；
        :param title: 标题文本；
        :param preview_textvariable: 折叠时显示在 header 上的状态摘要 StringVar；
        :param header_actions: 回调 ``fn(actions_frame)``，可在 header 右侧添加按钮。
        """
        if child.winfo_class() != "TFrame":
            return

        header = ttk.Frame(self, style="ConfigHeader.TFrame", padding=(12, 6))
        header.grid(row=self.cumulative_rows, column=0, sticky="ew")
        header.columnconfigure(1, weight=1)

        # 左：chevron + 标题
        title_box = ttk.Frame(header, style="ConfigHeader.TFrame")
        title_box.grid(row=0, column=0, sticky="w")

        chevron = ttk.Label(
            title_box, text=self.CHEVRON_OPEN, style="ConfigChevron.TLabel"
        )
        chevron.pack(side="left", padx=(0, 8))

        title_lbl = ttk.Label(title_box, text=title, style="ConfigHeader.TLabel")
        if kwargs.get("textvariable"):
            title_lbl.configure(textvariable=kwargs.get("textvariable"))
        title_lbl.pack(side="left")

        # 中：折叠状态预览
        preview_lbl = None
        if preview_textvariable is not None:
            preview_lbl = ttk.Label(
                header,
                textvariable=preview_textvariable,
                style="ConfigPreview.TLabel",
            )
            preview_lbl.grid(row=0, column=1, sticky="w", padx=(16, 8))

        # 右：actions（如顶部工具条按钮）
        actions_frame = ttk.Frame(header, style="ConfigHeader.TFrame")
        actions_frame.grid(row=0, column=2, sticky="e")
        if callable(header_actions):
            try:
                header_actions(actions_frame)
            except Exception:
                # 注入失败不应影响整体折叠面板渲染
                pass

        # 整条 header 点击切换
        clickable = [header, title_box, chevron, title_lbl]
        if preview_lbl is not None:
            clickable.append(preview_lbl)
        for w in clickable:
            w.bind(
                "<Button-1>",
                lambda _e, c=child: self._toggle_open_close(c),
            )
            try:
                w.configure(cursor="hand2")
            except tkinter.TclError:
                pass

        child._chevron = chevron
        child._header = header
        child._preview_lbl = preview_lbl
        # 兼容旧代码 child.btn.invoke() / child.btn.configure(image=...)
        child.btn = _HeaderToggleProxy(self, child, chevron)

        child.grid(row=self.cumulative_rows + 1, column=0, sticky="news")
        self.cumulative_rows += 2

    # ------------------------------------------------------------------
    # 内部实现
    # ------------------------------------------------------------------
    def _toggle_open_close(self, child):
        if child.winfo_viewable():
            child.grid_remove()
            try:
                child._chevron.configure(text=self.CHEVRON_CLOSED)
            except (AttributeError, tkinter.TclError):
                pass
        else:
            child.grid()
            try:
                child._chevron.configure(text=self.CHEVRON_OPEN)
            except (AttributeError, tkinter.TclError):
                pass


class _HeaderToggleProxy:
    """兼容旧代码：``child.btn.invoke()`` / ``child.btn.configure(image=...)``。"""

    def __init__(self, owner: "CollapsingFrame", child, chevron):
        self._owner = owner
        self._child = child
        self._chevron = chevron

    def invoke(self):
        self._owner._toggle_open_close(self._child)

    def configure(self, **kwargs):
        image = kwargs.get("image")
        if image == "closed":
            self._chevron.configure(text=CollapsingFrame.CHEVRON_CLOSED)
        elif image == "open":
            self._chevron.configure(text=CollapsingFrame.CHEVRON_OPEN)

    config = configure


# class Application(tkinter.Tk):

#     def __init__(self):
#         super().__init__()
#         self.title('Collapsing Frame')
#         # self.style = Style()

#         cf = CollapsingFrame(self)
#         cf.pack(fill='both')

#         # option group 1
#         group1 = ttk.Frame(cf, padding=10)
#         for x in range(5):
#             ttk.Checkbutton(group1, text=f'Option {x + 1}').pack(fill='x')
#         cf.add(group1, title='Option Group 1', style='primary.TButton')

#         # option group 2
#         group2 = ttk.Frame(cf, padding=10)
#         for x in range(5):
#             ttk.Checkbutton(group2, text=f'Option {x + 1}').pack(fill='x')
#         cf.add(group2, title='Option Group 2', style='danger.TButton')

# if __name__ == '__main__':
#     Application().mainloop()
