"""Pantone 认证摸底测试面板。"""

from __future__ import annotations

import datetime
import os
import sys
import threading
import tkinter as tk
from tkinter import filedialog, messagebox

import ttkbootstrap as ttk

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from pqAutomationApp import PQAutomationApp



_TEMPLATE_FILE = "pantone_2670_colors.xlsx"


def create_pantone_baseline_panel(self: "PQAutomationApp"):
    """创建 Pantone 认证摸底测试面板。"""
    frame = ttk.Frame(self.view_stack)
    self.pantone_baseline_frame = frame
    self.pantone_baseline_visible = False
    self.pantone_patterns = []
    self.pantone_results = []
    self._pantone_control_event = None
    self._pantone_running = False
    self._pantone_paused = False
    self._pantone_pause_requested = False
    self._pantone_stop_requested = False
    self._pantone_next_index = 0
    self._pantone_target_count = 0

    root = ttk.Frame(frame, padding=10)
    root.pack(fill=tk.BOTH, expand=True)

    title_row = ttk.Frame(root)
    title_row.pack(fill=tk.X, pady=(0, 8))
    ttk.Label(
        title_row,
        text="Pantone认证摸底测试",
        font=("微软雅黑", 14, "bold"),
    ).pack(side=tk.LEFT)

    self.pantone_status_var = tk.StringVar(value="未开始")
    self.pantone_progress_var = tk.StringVar(value="0 / 0")
    self.pantone_settle_var = tk.StringVar(value="0.3")

    config_row = ttk.LabelFrame(root, text="任务配置", padding=8)
    config_row.pack(fill=tk.X)
    ttk.Label(config_row, text=f"Pattern来源: settings/{_TEMPLATE_FILE}").pack(
        side=tk.LEFT
    )
    ttk.Label(config_row, text="稳定等待(s):").pack(side=tk.LEFT, padx=(14, 4))
    ttk.Entry(config_row, textvariable=self.pantone_settle_var, width=8).pack(
        side=tk.LEFT
    )
    ttk.Label(config_row, textvariable=self.pantone_progress_var).pack(
        side=tk.RIGHT, padx=(8, 0)
    )
    ttk.Label(config_row, textvariable=self.pantone_status_var, style="Muted.TLabel").pack(
        side=tk.RIGHT
    )

    btn_row = ttk.Frame(root)
    btn_row.pack(fill=tk.X, pady=(8, 8))
    self.pantone_start_btn = ttk.Button(
        btn_row,
        text="开始",
        bootstyle="primary",
        command=lambda: _start_pantone_baseline(self),
    )
    self.pantone_start_btn.pack(side=tk.LEFT, padx=(0, 6))
    self.pantone_pause_btn = ttk.Button(
        btn_row,
        text="暂停",
        bootstyle="warning-outline",
        command=lambda: _pause_pantone_baseline(self),
        state=tk.DISABLED,
    )
    self.pantone_pause_btn.pack(side=tk.LEFT, padx=(0, 6))
    self.pantone_resume_btn = ttk.Button(
        btn_row,
        text="继续",
        bootstyle="info-outline",
        command=lambda: _resume_pantone_baseline(self),
        state=tk.DISABLED,
    )
    self.pantone_resume_btn.pack(side=tk.LEFT, padx=(0, 6))
    self.pantone_end_btn = ttk.Button(
        btn_row,
        text="结束",
        bootstyle="danger-outline",
        command=lambda: _end_pantone_baseline(self),
        state=tk.DISABLED,
    )
    self.pantone_end_btn.pack(side=tk.LEFT, padx=(0, 6))
    ttk.Button(
        btn_row,
        text="清空结果",
        bootstyle="secondary-outline",
        command=lambda: _clear_results(self),
    ).pack(side=tk.LEFT, padx=(0, 6))
    ttk.Button(
        btn_row,
        text="另存为模板",
        bootstyle="success",
        command=lambda: _save_as_template(self),
    ).pack(side=tk.LEFT)

    table_frame = ttk.LabelFrame(root, text="测试结果（R,G,B,L,x,y）", padding=8)
    table_frame.pack(fill=tk.BOTH, expand=True)
    columns = ("idx", "r", "g", "b", "l", "x", "y", "time")
    self.pantone_tree = ttk.Treeview(
        table_frame,
        columns=columns,
        show="headings",
        height=18,
    )
    headings = {
        "idx": "序号",
        "r": "R",
        "g": "G",
        "b": "B",
        "l": "L",
        "x": "x",
        "y": "y",
        "time": "时间",
    }
    widths = {
        "idx": 70,
        "r": 70,
        "g": 70,
        "b": 70,
        "l": 90,
        "x": 90,
        "y": 90,
        "time": 110,
    }
    for col in columns:
        self.pantone_tree.heading(col, text=headings[col])
        self.pantone_tree.column(col, width=widths[col], anchor=tk.CENTER)
    self.pantone_tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

    scrollbar = ttk.Scrollbar(table_frame, orient=tk.VERTICAL, command=self.pantone_tree.yview)
    scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
    self.pantone_tree.configure(yscrollcommand=scrollbar.set)

    self.register_panel("pantone_baseline", frame, None, "pantone_baseline_visible")
    _set_button_states(self)


def toggle_pantone_baseline_panel(self: "PQAutomationApp"):
    """切换 Pantone 认证摸底测试面板。"""
    self.show_panel("pantone_baseline")


def _get_settings_dir(self: "PQAutomationApp"):
    """返回 settings 绝对目录，避免依赖当前工作目录。"""
    if getattr(self, "config_file", None):
        return os.path.dirname(self.config_file)

    if getattr(sys, "frozen", False):
        base_dir = os.path.dirname(sys.executable)
    else:
        base_dir = os.path.dirname(
            os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
        )
    return os.path.join(base_dir, "settings")


def _load_patterns(self: "PQAutomationApp"):
    path = os.path.join(_get_settings_dir(self), _TEMPLATE_FILE)
    if not os.path.isfile(path):
        raise FileNotFoundError(f"未找到模板文件: {path}")

    from openpyxl import load_workbook

    patterns = []
    wb = load_workbook(path, read_only=True, data_only=True)
    ws = wb.active
    try:
        for row in ws.iter_rows(min_row=2, values_only=True):
            if not row:
                continue
            try:
                r = int(row[0]) if row[0] is not None else None
                g = int(row[1]) if len(row) > 1 and row[1] is not None else None
                b = int(row[2]) if len(row) > 2 and row[2] is not None else None
            except Exception:
                continue
            if r is None or g is None or b is None:
                continue
            if min(r, g, b) < 0 or max(r, g, b) > 255:
                continue
            patterns.append((r, g, b))
    finally:
        wb.close()

    if not patterns:
        raise RuntimeError("模板中未找到有效 RGB 列表（需包含 R/G/B 三列）")
    return patterns


def _start_pantone_baseline(self: "PQAutomationApp"):
    if self._pantone_running:
        messagebox.showinfo("提示", "Pantone 任务正在执行")
        return
    if not self.signal_service.is_connected:
        messagebox.showwarning("警告", "请先连接 UCD323")
        return
    if not getattr(self, "ca", None):
        messagebox.showwarning("警告", "请先连接 CA410")
        return

    try:
        settle = float(self.pantone_settle_var.get().strip())
        if settle < 0:
            raise ValueError()
    except Exception:
        messagebox.showerror("参数错误", "稳定等待时间必须是非负数字")
        return

    try:
        self.pantone_patterns = _load_patterns(self)
        self._pantone_target_count = len(self.pantone_patterns)
    except Exception as exc:
        messagebox.showerror("读取失败", str(exc))
        return

    if self.pantone_results:
        if not messagebox.askyesno("确认开始", "开始将清空当前内存中的测试结果，是否继续？"):
            return

    self._pantone_running = True
    self._pantone_paused = False
    self._pantone_pause_requested = False
    self._pantone_stop_requested = False
    self._pantone_control_event = threading.Event()
    self._pantone_next_index = 0
    self.pantone_status_var.set("执行中")
    self.pantone_progress_var.set(f"0 / {self._pantone_target_count}")
    self.pantone_results = []
    for item in self.pantone_tree.get_children():
        self.pantone_tree.delete(item)
    _set_button_states(self)

    _launch_worker(self, start_index=0, settle=settle)


def _resume_pantone_baseline(self: "PQAutomationApp"):
    if self._pantone_running:
        messagebox.showinfo("提示", "Pantone 任务正在执行")
        return
    if not self._pantone_paused:
        messagebox.showinfo("提示", "当前没有可继续的暂停任务")
        return
    if not self.signal_service.is_connected:
        messagebox.showwarning("警告", "请先连接 UCD323")
        return
    if not getattr(self, "ca", None):
        messagebox.showwarning("警告", "请先连接 CA410")
        return

    try:
        settle = float(self.pantone_settle_var.get().strip())
        if settle < 0:
            raise ValueError()
    except Exception:
        messagebox.showerror("参数错误", "稳定等待时间必须是非负数字")
        return

    try:
        self.pantone_patterns = _load_patterns(self)
        self._pantone_target_count = len(self.pantone_patterns)
    except Exception as exc:
        messagebox.showerror("读取失败", str(exc))
        return

    if self._pantone_next_index >= self._pantone_target_count:
        messagebox.showinfo("提示", "任务已完成，无需继续")
        return

    self._pantone_running = True
    self._pantone_paused = False
    self._pantone_pause_requested = False
    self._pantone_stop_requested = False
    self._pantone_control_event = threading.Event()
    self.pantone_status_var.set("执行中")
    _set_button_states(self)

    _launch_worker(self, start_index=self._pantone_next_index, settle=settle)


def _launch_worker(self: "PQAutomationApp", start_index, settle):
    total = self._pantone_target_count or len(self.pantone_patterns)

    def worker():
        end_state = "completed"
        try:
            src = self.pantone_patterns
            src_count = len(src)
            rgb_session = self.pattern_service.prepare_session("rgb", log_details=False)
            self._dispatch_ui(
                self.log_gui.log,
                f"Pantone 认证摸底启动: source={src_count}, target={total}, start={start_index + 1}",
                "info",
            )
            for i in range(start_index, total):
                if self._pantone_stop_requested:
                    end_state = "stopped"
                    break
                if self._pantone_pause_requested:
                    end_state = "paused"
                    break

                r, g, b = src[i % src_count]
                try:
                    self.pattern_service.send_rgb((r, g, b), session=rgb_session)
                except Exception as exc:
                    raise RuntimeError(f"第 {i + 1} 组发送失败: {exc}") from exc

                if settle > 0 and self._pantone_control_event is not None:
                    self._pantone_control_event.clear()
                    self._pantone_control_event.wait(timeout=settle)

                if self._pantone_stop_requested:
                    end_state = "stopped"
                    break
                if self._pantone_pause_requested:
                    end_state = "paused"
                    break

                x, y, lv, _X, _Y, _Z = self.read_ca_xyLv()
                if lv is None:
                    raise RuntimeError(f"第 {i + 1} 组 CA410 采集失败")

                record = {
                    "idx": i + 1,
                    "r": r,
                    "g": g,
                    "b": b,
                    "l": float(lv),
                    "x": float(x),
                    "y": float(y),
                    "time": datetime.datetime.now().strftime("%H:%M:%S"),
                }
                self.pantone_results.append(record)
                self._pantone_next_index = i + 1
                self._dispatch_ui(_append_result_row, self, record, total)

            if end_state == "paused":
                self._pantone_paused = True
                self._dispatch_ui(self.pantone_status_var.set, "已暂停")
                self._dispatch_ui(
                    self.log_gui.log,
                    f"Pantone 任务已暂停，断点 {self._pantone_next_index} / {total}",
                    "warning",
                )
            elif end_state == "stopped":
                self._pantone_paused = False
                self._pantone_next_index = 0
                self._dispatch_ui(self.pantone_status_var.set, "已结束")
                self._dispatch_ui(
                    self.log_gui.log,
                    f"Pantone 任务已结束，保留 {len(self.pantone_results)} 条内存结果",
                    "warning",
                )
            else:
                self._pantone_paused = False
                self._pantone_next_index = total
                self._dispatch_ui(self.pantone_status_var.set, "已完成")
                self._dispatch_ui(
                    self.log_gui.log,
                    f"Pantone 任务完成，共 {len(self.pantone_results)} 条数据",
                    "success",
                )
                try:
                    auto_path = _auto_save_template(self)
                    self._dispatch_ui(
                        self.log_gui.log,
                        f"Pantone 模板已自动保存: {auto_path}",
                        "success",
                    )
                except Exception as exc:
                    self._dispatch_ui(
                        self.log_gui.log,
                        f"Pantone 自动保存模板失败: {exc}",
                        "error",
                    )
        except Exception as exc:
            self._pantone_paused = False
            self._dispatch_ui(self.pantone_status_var.set, "执行失败")
            self._dispatch_ui(self.log_gui.log, f"Pantone 任务失败: {exc}", "error")
            self._dispatch_ui(messagebox.showerror, "执行失败", str(exc))
        finally:
            self._pantone_running = False
            self._pantone_pause_requested = False
            self._pantone_stop_requested = False
            self._dispatch_ui(_set_button_states, self)

    threading.Thread(target=worker, daemon=True).start()


def _append_result_row(self: "PQAutomationApp", record, total):
    self.pantone_tree.insert(
        "",
        tk.END,
        values=(
            record["idx"],
            record["r"],
            record["g"],
            record["b"],
            f"{record['l']:.2f}",
            f"{record['x']:.4f}",
            f"{record['y']:.4f}",
            record["time"],
        ),
    )
    self.pantone_progress_var.set(f"{record['idx']} / {total}")
    # 每次插入都滚到末尾，便于观察采集进度。
    children = self.pantone_tree.get_children()
    if children:
        self.pantone_tree.see(children[-1])


def _pause_pantone_baseline(self: "PQAutomationApp"):
    if not self._pantone_running:
        messagebox.showinfo("提示", "当前没有运行中的任务")
        return
    self._pantone_pause_requested = True
    self.pantone_status_var.set("暂停中...")
    if self._pantone_control_event is not None:
        self._pantone_control_event.set()


def _end_pantone_baseline(self: "PQAutomationApp"):
    if self._pantone_running:
        self._pantone_stop_requested = True
        self.pantone_status_var.set("结束中...")
        if self._pantone_control_event is not None:
            self._pantone_control_event.set()
        return

    # 非运行态下点击“结束”：清除断点，保留当前内存结果。
    self._pantone_paused = False
    self._pantone_next_index = 0
    self.pantone_status_var.set("已结束")
    _set_button_states(self)


def _clear_results(self: "PQAutomationApp"):
    if self._pantone_running:
        messagebox.showinfo("提示", "任务执行中，无法清空")
        return
    self.pantone_results = []
    self._pantone_paused = False
    self._pantone_next_index = 0
    for item in self.pantone_tree.get_children():
        self.pantone_tree.delete(item)
    self._pantone_target_count = 0
    self.pantone_progress_var.set("0 / 0")
    self.pantone_status_var.set("结果已清空")
    _set_button_states(self)


def _set_button_states(self: "PQAutomationApp"):
    if self._pantone_running:
        self.pantone_start_btn.configure(state=tk.DISABLED)
        self.pantone_pause_btn.configure(state=tk.NORMAL)
        self.pantone_resume_btn.configure(state=tk.DISABLED)
        self.pantone_end_btn.configure(state=tk.NORMAL)
        return

    self.pantone_start_btn.configure(state=tk.NORMAL)
    self.pantone_pause_btn.configure(state=tk.DISABLED)
    self.pantone_end_btn.configure(state=tk.NORMAL if (self._pantone_paused or self.pantone_results) else tk.DISABLED)

    can_resume = self._pantone_paused and self._pantone_next_index < self._pantone_target_count
    self.pantone_resume_btn.configure(state=tk.NORMAL if can_resume else tk.DISABLED)


def _save_as_template(self: "PQAutomationApp"):
    if not self.pantone_results:
        messagebox.showinfo("提示", "暂无可导出的结果")
        return

    default_name = _TEMPLATE_FILE.replace("\xa0", " ")
    path = filedialog.asksaveasfilename(
        title="另存为 Pantone 模板",
        defaultextension=".xlsx",
        initialfile=default_name,
        filetypes=[("Excel 文件", "*.xlsx")],
    )
    if not path:
        return

    try:
        _write_template_xlsx(self, path)
        self.log_gui.log(f"Pantone 模板已保存: {path}", level="success")
        self.pantone_status_var.set(f"已保存: {os.path.basename(path)}")
    except Exception as exc:
        messagebox.showerror("保存失败", f"写入 xlsx 失败: {exc}")


def _resolve_results_dir(self: "PQAutomationApp"):
    if getattr(self, "config_file", None):
        root_dir = os.path.dirname(os.path.dirname(self.config_file))
    else:
        root_dir = os.path.dirname(
            os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
        )
    results_dir = os.path.join(root_dir, "results")
    os.makedirs(results_dir, exist_ok=True)
    return results_dir


def _auto_save_template(self: "PQAutomationApp"):
    results_dir = _resolve_results_dir(self)
    target_count = len(self.pantone_results)
    filename = (
        f"pantone_{target_count}_baseline_"
        f"{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.xlsx"
    )
    path = os.path.join(results_dir, filename)
    _write_template_xlsx(self, path)
    return path


def _write_template_xlsx(self: "PQAutomationApp", path):
    # 优先复制 settings 模板，再覆盖数据区；没有模板时自动创建同结构表。
    template_path = os.path.join(_get_settings_dir(self), _TEMPLATE_FILE)
    from openpyxl import load_workbook, Workbook

    if os.path.isfile(template_path):
        wb = load_workbook(template_path)
        ws = wb.active
    else:
        wb = Workbook()
        ws = wb.active
        ws.title = "Sheet1"
        ws.cell(row=1, column=1, value="R")
        ws.cell(row=1, column=2, value="G")
        ws.cell(row=1, column=3, value="B")
        ws.cell(row=1, column=4, value="L")
        ws.cell(row=1, column=5, value="x")
        ws.cell(row=1, column=6, value="y")

    # 清空旧数据
    max_row = max(ws.max_row, 2)
    for row in range(2, max_row + 1):
        for col in range(1, 7):
            ws.cell(row=row, column=col, value=None)

    for idx, item in enumerate(self.pantone_results, start=2):
        ws.cell(row=idx, column=1, value=int(item["r"]))
        ws.cell(row=idx, column=2, value=int(item["g"]))
        ws.cell(row=idx, column=3, value=int(item["b"]))
        ws.cell(row=idx, column=4, value=float(item["l"]))
        ws.cell(row=idx, column=5, value=float(item["x"]))
        ws.cell(row=idx, column=6, value=float(item["y"]))

    wb.save(path)


class PantoneBaselinePanelMixin:
    """由 tools/refactor_to_mixins.py 自动生成。
    把本模块的自由函数挂到 PQAutomationApp 上，便于 F12 跳转与类型推断。
    """
    create_pantone_baseline_panel = create_pantone_baseline_panel
    toggle_pantone_baseline_panel = toggle_pantone_baseline_panel
    _get_settings_dir = _get_settings_dir
    _load_patterns = _load_patterns
    _start_pantone_baseline = _start_pantone_baseline
    _resume_pantone_baseline = _resume_pantone_baseline
    _launch_worker = _launch_worker
    _append_result_row = _append_result_row
    _pause_pantone_baseline = _pause_pantone_baseline
    _end_pantone_baseline = _end_pantone_baseline
    _clear_results = _clear_results
    _set_button_states = _set_button_states
    _save_as_template = _save_as_template
    _resolve_results_dir = _resolve_results_dir
    _auto_save_template = _auto_save_template
    _write_template_xlsx = _write_template_xlsx
