"""侧边面板（日志 / Local Dimming / 调试）"""

import traceback
import tkinter as tk
import ttkbootstrap as ttk

from app.views.pq_log_gui import PQLogGUI
from app.views.pq_debug_panel import PQDebugPanel

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from pqAutomationApp import PQAutomationApp


def create_log_panel(self: "PQAutomationApp"):
    """创建日志面板"""
    self.log_frame = ttk.Frame(self.view_stack)
    self.log_gui = PQLogGUI(self.log_frame)
    self.log_gui.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

    # 默认隐藏日志面板
    self.log_visible = False

    # 注册到面板管理系统
    self.register_panel(
        "log", self.log_frame, None, "log_visible"
    )  # button会在后面设置


def create_local_dimming_panel(self: "PQAutomationApp"):
    """创建 Local Dimming 测试面板。"""
    self.local_dimming_frame = ttk.Frame(self.main_view)

    # 主容器
    main_container = ttk.Frame(self.local_dimming_frame, padding=10)
    main_container.pack(fill=tk.BOTH, expand=True)

    # ==================== 1. 标题 ====================
    title_frame = ttk.Frame(main_container)
    title_frame.pack(fill=tk.X, pady=(0, 10))

    ttk.Label(
        title_frame,
        text="Local Dimming 窗口测试",
        font=("微软雅黑", 14, "bold"),
    ).pack(side=tk.LEFT)

    # ==================== 2. 窗口百分比按钮 ====================
    window_frame = ttk.LabelFrame(
        main_container, text="窗口百分比", padding=10
    )
    window_frame.pack(fill=tk.X, pady=(0, 10))

    # 说明文字
    ttk.Label(
        window_frame,
        text="点击按钮发送对应百分比的白色窗口（黑色背景 + 居中白色矩形）",
        font=("", 9),
        style="SuccessState.TLabel",
    ).pack(pady=(0, 8))

    window_level_row = ttk.Frame(window_frame)
    window_level_row.pack(fill=tk.X, pady=(0, 8))

    ttk.Label(window_level_row, text="窗口(%):").pack(side=tk.LEFT)
    self.ld_window_percentage_var = tk.StringVar(value="10")
    ld_window_percentage_entry = ttk.Entry(
        window_level_row,
        textvariable=self.ld_window_percentage_var,
        width=8,
    )
    ld_window_percentage_entry.pack(side=tk.LEFT, padx=(6, 10))

    ttk.Label(window_level_row, text="窗口亮度(%):").pack(side=tk.LEFT)
    self.ld_window_luminance_var = tk.StringVar(value="100")
    ld_window_luminance_entry = ttk.Entry(
        window_level_row,
        textvariable=self.ld_window_luminance_var,
        width=8,
    )
    ld_window_luminance_entry.pack(side=tk.LEFT, padx=(6, 10))

    ttk.Button(
        window_level_row,
        text="生成窗口",
        command=self.send_ld_manual_window,
        bootstyle="success-outline",
        width=12,
    ).pack(side=tk.LEFT)

    ld_window_percentage_entry.bind(
        "<Return>",
        lambda _event: self.send_ld_manual_window(),
    )
    ld_window_luminance_entry.bind(
        "<Return>",
        lambda _event: self.send_ld_manual_window(),
    )

    ttk.Label(
        window_level_row,
        text="输入后可直接点生成或回车",
        style="InfoState.TLabel",
    ).pack(side=tk.LEFT, padx=(8, 0))

    # 第一行：1%, 2%, 5%, 10%, 18%
    row1 = ttk.Frame(window_frame)
    row1.pack(fill=tk.X, pady=(0, 5))

    percentages_row1 = [1, 2, 5, 10, 18]
    for p in percentages_row1:
        ttk.Button(
            row1,
            text=f"{p}%",
            command=lambda p=p: self.send_ld_window(p),
            bootstyle="success",
            width=12,
        ).pack(side=tk.LEFT, padx=3)

    # 第二行：25%, 50%, 75%, 100%
    row2 = ttk.Frame(window_frame)
    row2.pack(fill=tk.X)

    percentages_row2 = [25, 50, 75, 100]
    for p in percentages_row2:
        ttk.Button(
            row2,
            text=f"{p}%",
            command=lambda p=p: self.send_ld_window(p),
            bootstyle="success",
            width=12,
        ).pack(side=tk.LEFT, padx=3)

    # ==================== 3. 其他手动图案 ====================
    pattern_frame = ttk.LabelFrame(main_container, text="其他测试图案", padding=10)
    pattern_frame.pack(fill=tk.X, pady=(0, 10))

    pattern_row = ttk.Frame(pattern_frame)
    pattern_row.pack(fill=tk.X)

    ttk.Button(
        pattern_row,
        text="棋盘格(中心白)",
        command=lambda: self.send_ld_checkerboard(True),
        bootstyle="secondary",
        width=14,
    ).pack(side=tk.LEFT, padx=3)

    ttk.Button(
        pattern_row,
        text="棋盘格(中心黑)",
        command=lambda: self.send_ld_checkerboard(False),
        bootstyle="secondary",
        width=14,
    ).pack(side=tk.LEFT, padx=3)

    ttk.Button(
        pattern_row,
        text="全黑画面",
        command=self.send_ld_black_pattern,
        bootstyle="dark",
        width=12,
    ).pack(side=tk.LEFT, padx=3)

    # ==================== 4. 独立瞬时峰值连续测试 ====================
    peak_frame = ttk.LabelFrame(main_container, text="瞬时峰值独立测试", padding=10)
    peak_frame.pack(fill=tk.X, pady=(0, 10))

    self.ld_peak_window_size_var = tk.StringVar(value="10")
    self.ld_peak_window_luminance_var = tk.StringVar(value="100")
    self.ld_peak_duration_var = tk.StringVar(value="20")
    self.ld_peak_sample_interval_var = tk.StringVar(value="0.3")
    self.ld_peak_record_curve_var = tk.BooleanVar(value=True)
    self.ld_peak_no_limit_var = tk.BooleanVar(value=False)
    self.ld_peak_drop_percent_var = tk.StringVar(value="3")

    ttk.Label(peak_frame, text="窗口(%):").grid(row=1, column=0, sticky=tk.W, padx=(0, 4))
    ttk.Entry(peak_frame, textvariable=self.ld_peak_window_size_var, width=8).grid(
        row=1, column=1, sticky=tk.W, padx=(0, 10)
    )

    ttk.Label(peak_frame, text="窗口亮度(%):").grid(
        row=1, column=2, sticky=tk.W, padx=(0, 4)
    )
    ttk.Entry(peak_frame, textvariable=self.ld_peak_window_luminance_var, width=8).grid(
        row=1, column=3, sticky=tk.W, padx=(0, 10)
    )

    ttk.Label(peak_frame, text="连续时长(s):").grid(
        row=1, column=4, sticky=tk.W, padx=(0, 4)
    )
    ttk.Entry(peak_frame, textvariable=self.ld_peak_duration_var, width=8).grid(
        row=1, column=5, sticky=tk.W, padx=(0, 10)
    )

    ttk.Label(peak_frame, text="采样间隔(s):").grid(
        row=1, column=6, sticky=tk.W, padx=(0, 4)
    )
    ttk.Entry(peak_frame, textvariable=self.ld_peak_sample_interval_var, width=8).grid(
        row=1, column=7, sticky=tk.W
    )

    ttk.Checkbutton(
        peak_frame,
        text="记录曲线点到表格",
        variable=self.ld_peak_record_curve_var,
        bootstyle="round-toggle",
    ).grid(row=2, column=0, columnspan=3, sticky=tk.W, pady=(8, 0))

    peak_btn_row = ttk.Frame(peak_frame)
    peak_btn_row.grid(row=2, column=4, columnspan=4, sticky=tk.EW, pady=(8, 0))

    self.ld_peak_start_btn = ttk.Button(
        peak_btn_row,
        text="开始峰值追踪",
        command=self.start_ld_instant_peak_tracking,
        bootstyle="warning",
        width=14,
    )
    self.ld_peak_start_btn.pack(side=tk.LEFT, padx=(0, 5))

    self.ld_peak_stop_btn = ttk.Button(
        peak_btn_row,
        text="停止",
        command=self.stop_ld_instant_peak_tracking,
        bootstyle="danger-outline",
        width=10,
        state="disabled",
    )
    self.ld_peak_stop_btn.pack(side=tk.LEFT)

    ttk.Label(peak_frame, text="亮度回落(%):").grid(
        row=2, column=0, sticky=tk.W, padx=(0, 4), pady=(6, 0)
    )

    ttk.Entry(
        peak_frame,
        textvariable=self.ld_peak_drop_percent_var,
        width=8
    ).grid(row=2, column=1, sticky=tk.W, pady=(6, 0))

    ttk.Checkbutton(
        peak_frame,
        text="不固定测试时间",
        variable=self.ld_peak_no_limit_var,
        bootstyle="round-toggle",
    ).grid(row=2, column=2, columnspan=3, sticky=tk.W, pady=(6, 0))

    # ==================== 5. CA410 采集按钮 ====================
    measure_frame = ttk.LabelFrame(main_container, text="CA410 测量", padding=10)
    measure_frame.pack(fill=tk.X, pady=(0, 10))

    measure_btn_frame = ttk.Frame(measure_frame)
    measure_btn_frame.pack(fill=tk.X)

    self.ld_measure_btn = ttk.Button(
        measure_btn_frame,
        text="采集当前亮度",
        command=self.measure_ld_luminance,
        bootstyle="primary",
        width=15,
    )
    self.ld_measure_btn.pack(side=tk.LEFT, padx=(0, 5))

    # 显示测量结果
    self.ld_result_label = ttk.Label(
        measure_btn_frame,
        text="亮度: -- cd/m² | x: -- | y: --",
        font=("Consolas", 10),
        style="InfoState.TLabel",
    )
    self.ld_result_label.pack(side=tk.LEFT, padx=(10, 0))

    # ==================== 6. 测试结果表格 ====================
    result_frame = ttk.LabelFrame(main_container, text="测试记录", padding=10)
    result_frame.pack(fill=tk.BOTH, expand=True, pady=(0, 10))

    # Treeview
    columns = ("测试项目", "图案", "亮度/结果", "x", "y", "时间")
    self.ld_tree = ttk.Treeview(
        result_frame, columns=columns, show="headings", height=10
    )

    for col in columns:
        self.ld_tree.heading(col, text=col)
        if col == "测试项目":
            self.ld_tree.column(col, width=120, anchor=tk.CENTER)
        elif col == "图案":
            self.ld_tree.column(col, width=140, anchor=tk.CENTER)
        elif col == "亮度/结果":
            self.ld_tree.column(col, width=110, anchor=tk.CENTER)
        elif col == "时间":
            self.ld_tree.column(col, width=120, anchor=tk.CENTER)
        else:
            self.ld_tree.column(col, width=100, anchor=tk.CENTER)

    self.ld_tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

    # 滚动条
    scrollbar = ttk.Scrollbar(
        result_frame, orient=tk.VERTICAL, command=self.ld_tree.yview
    )
    scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
    self.ld_tree.configure(yscrollcommand=scrollbar.set)

    # ==================== 7. 底部操作按钮 ====================
    bottom_frame = ttk.Frame(main_container)
    bottom_frame.pack(fill=tk.X)

    self.ld_clear_btn = ttk.Button(
        bottom_frame,
        text="清空记录",
        command=self.clear_ld_records,
        bootstyle="danger-outline",
        width=12,
    )
    self.ld_clear_btn.pack(side=tk.LEFT, padx=(0, 5))

    self.ld_save_btn = ttk.Button(
        bottom_frame,
        text="保存结果",
        command=self.save_local_dimming_results,
        bootstyle="info",
        width=12,
    )
    self.ld_save_btn.pack(side=tk.LEFT)

    self.ld_plot_btn = ttk.Button(
        bottom_frame,
        text="生成峰值曲线",
        command=self.plot_ld_instant_peak_curve,
        bootstyle="warning-outline",
        width=14,
    )
    self.ld_plot_btn.pack(side=tk.LEFT, padx=(5, 0))

    # 默认隐藏
    self.local_dimming_visible = False

    # 注册到面板管理系统
    self.register_panel(
        "local_dimming",
        self.local_dimming_frame,
        None,
        "local_dimming_visible",
    )

    # 初始化当前窗口百分比（用于记录）
    self.current_ld_percentage = None
    self.current_ld_test_item = None
    self.current_ld_pattern_label = None
    self.ld_peak_tracking = False


def toggle_local_dimming_panel(self: "PQAutomationApp"):
    """切换 Local Dimming 面板显示"""
    self.show_panel("local_dimming")


def toggle_log_panel(self: "PQAutomationApp"):
    """切换日志面板的显示状态"""
    self.show_panel("log")


# ---- 单步调试面板（统一实现） ----
DEBUG_PANEL_CONFIGS = {
    "screen_module": {
        "window_attr": "debug_window",
        "btn_attr": "screen_debug_btn",
        "title": " 单步调试面板",
        "window_log_prefix": "",
        "data_log_prefix": "屏模组",
        "failure_data_label": "调试数据",
        # (item_key, debug_key, (category, subkey), data_label, enable_desc)
        "data_items": [
            ("gamma", "gamma", ("shared", "gray"), "灰阶", "Gamma 单步调试"),
            ("gamut", "rgb", ("gamut", "rgb"), "RGB", "RGB 单步调试"),
        ],
    },
    "sdr_movie": {
        "window_attr": "sdr_debug_window",
        "btn_attr": "sdr_debug_btn",
        "title": " SDR 单步调试面板",
        "window_log_prefix": "SDR ",
        "data_log_prefix": "SDR",
        "failure_data_label": "SDR 调试数据",
        "data_items": [
            ("gamma", "gamma", ("shared", "gray"), "灰阶", "Gamma 单步调试"),
            ("accuracy", "accuracy", ("accuracy", "measured"), "色准", "色准单步调试"),
            ("gamut", "rgb", ("gamut", "rgb"), "RGB", "RGB 单步调试"),
        ],
    },
    "hdr_movie": {
        "window_attr": "hdr_debug_window",
        "btn_attr": "hdr_debug_btn",
        "title": " HDR 单步调试面板",
        "window_log_prefix": "HDR ",
        "data_log_prefix": "HDR",
        "failure_data_label": "HDR 调试数据",
        "data_items": [
            ("eotf", "eotf", ("shared", "gray"), "灰阶", "EOTF 单步调试"),
            ("accuracy", "accuracy", ("accuracy", "measured"), "色准", "色准单步调试"),
            ("gamut", "rgb", ("gamut", "rgb"), "RGB", "RGB 单步调试"),
        ],
    },
}


def _toggle_debug_panel(self: "PQAutomationApp", test_type):
    """打开/关闭对应测试类型的单步调试面板（独立窗口）。"""
    cfg = DEBUG_PANEL_CONFIGS[test_type]
    win_attr = cfg["window_attr"]
    btn = getattr(self, cfg["btn_attr"])
    wlp = cfg["window_log_prefix"]

    # 如果窗口已存在且可见，关闭它
    existing = getattr(self, win_attr, None)
    if existing is not None and existing.winfo_exists():
        existing.destroy()
        btn.config(text="打开调试面板")
        return

    # 创建新窗口
    win = ttk.Toplevel(self.root)
    win.title(cfg["title"])
    win.geometry("900x400")
    win.transient(self.root)
    setattr(self, win_attr, win)

    # 调试面板容器
    debug_container = ttk.Frame(win, padding=10)
    debug_container.pack(fill=tk.BOTH, expand=True)

    # 创建调试面板实例（不要对它调用 pack）
    debug_panel_instance = PQDebugPanel(debug_container, self)

    # 重新启用调试（如果有数据）
    try:
        selected_items = self.get_selected_test_items()
        dlp = cfg["data_log_prefix"]
        # 显式按 test_type 拿历史结果，避免依赖"当前活跃"状态
        results_store = getattr(self, "results", None)
        results_obj = results_store.get(test_type) if results_store is not None else None
        if results_obj is None:
            self.log_gui.log(f"{dlp} 暂无 {test_type} 的测试结果，面板已打开", level="warning")
        else:
            for item_key, debug_key, (cat, sub), data_label, enable_desc in cfg["data_items"]:
                if item_key not in selected_items:
                    continue
                data = results_obj.get_intermediate_data(cat, sub)
                if not data:
                    if test_type == "screen_module" and item_key == "gamma":
                        self.log_gui.log("没有可用的灰阶数据", level="error")
                    continue
                self.log_gui.log(f"  → 加载 {len(data)} 个{data_label}数据点", level="info")
                debug_panel_instance.enable_debug(test_type, debug_key, data)
    except Exception as e:
        self.log_gui.log(f"加载{cfg['failure_data_label']}失败: {str(e)}", level="error")
        self.log_gui.log(traceback.format_exc(), level="error")

    btn.config(text="关闭调试面板")

    def on_closing():
        btn.config(text="打开调试面板")
        getattr(self, win_attr).destroy()

    win.protocol("WM_DELETE_WINDOW", on_closing)
    win.update_idletasks()


def toggle_screen_debug_panel(self: "PQAutomationApp"):
    _toggle_debug_panel(self, "screen_module")


def toggle_sdr_debug_panel(self: "PQAutomationApp"):
    _toggle_debug_panel(self, "sdr_movie")


def toggle_hdr_debug_panel(self: "PQAutomationApp"):
    _toggle_debug_panel(self, "hdr_movie")



def update_sidebar_selection(self: "PQAutomationApp"):
    """更新侧边栏按钮的选中状态"""
    # 重置所有按钮样式为默认
    self.screen_module_btn.configure(style="Sidebar.TButton")
    self.sdr_movie_btn.configure(style="Sidebar.TButton")
    self.hdr_movie_btn.configure(style="Sidebar.TButton")
    self.local_dimming_btn.configure(style="Sidebar.TButton")

    # 设置当前选中按钮的样式
    current_type = self.test_type_var.get()
    if current_type == "screen_module":
        self.screen_module_btn.configure(style="SidebarSelected.TButton")
    elif current_type == "sdr_movie":
        self.sdr_movie_btn.configure(style="SidebarSelected.TButton")
    elif current_type == "hdr_movie":
        self.hdr_movie_btn.configure(style="SidebarSelected.TButton")
    elif current_type == "local_dimming":
        self.local_dimming_btn.configure(style="SidebarSelected.TButton")


class SidePanelsMixin:
    """由 tools/refactor_to_mixins.py 自动生成。
    把本模块的自由函数挂到 PQAutomationApp 上，便于 F12 跳转与类型推断。
    """
    create_log_panel = create_log_panel
    create_local_dimming_panel = create_local_dimming_panel
    toggle_local_dimming_panel = toggle_local_dimming_panel
    toggle_log_panel = toggle_log_panel
    _toggle_debug_panel = _toggle_debug_panel
    toggle_screen_debug_panel = toggle_screen_debug_panel
    toggle_sdr_debug_panel = toggle_sdr_debug_panel
    toggle_hdr_debug_panel = toggle_hdr_debug_panel
    update_sidebar_selection = update_sidebar_selection
