# Programa: fast_threshold_module.py (classe QuickThresholdModule)
# Criado em: Janeiro de 2025
# Descrição: Módulo Quick Threshold - Versão simplificada do Fasusurance para medição rápida de threshold

# Importações necessárias
import ctypes
import os
import sys
import tkinter as tk
from tkinter import messagebox, font, filedialog, ttk
import threading
import queue
import time
import traceback
from datetime import datetime
import json
from typing import Optional
import struct
import re
from src.core.port_manager import get_port_manager
from .i18n import get_translator, t
from .app_console import fc_log
from .shell_open import open_path_with_default_app

# Tenta importar as bibliotecas de gráfico.
try:
    from matplotlib.figure import Figure
    from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
except ImportError:
    _mpl_msg_en = (
        "The 'matplotlib' library was not found.\nPlease install it with the command:\n\npy -m pip install matplotlib"
    )
    try:
        messagebox.showerror(t('fastthreshold.missing_dependency'), t('fastthreshold.missing_dependency_msg'))
    except Exception:
        try:
            from .i18n import TRANSLATIONS, get_translator
            _trans = get_translator()
            _lc = 'pt' if str((_trans.get_language() if _trans else None) or 'pt').startswith('pt') else 'en'
            _b = TRANSLATIONS.get(_lc, TRANSLATIONS.get('pt', {}))
            messagebox.showerror(
                _b.get('fastthreshold.missing_dependency', 'Missing Dependency'),
                _b.get('fastthreshold.missing_dependency_msg', _mpl_msg_en),
            )
        except Exception:
            try:
                from .i18n import TRANSLATIONS
                _b = TRANSLATIONS.get('pt', TRANSLATIONS.get('en', {}))
                messagebox.showerror(
                    _b.get('fastthreshold.missing_dependency', 'Missing Dependency'),
                    _b.get('fastthreshold.missing_dependency_msg', _mpl_msg_en),
                )
            except Exception:
                messagebox.showerror('Missing Dependency', _mpl_msg_en)
    sys.exit()

# --- CONFIGURAÇÃO DA DLL E FUNÇÕES ---
dll_name = "UHFRFID.dll"
try:
    # CORREÇÃO: Caminho robusto para executável e desenvolvimento
    if hasattr(sys, '_MEIPASS'):
        # Modo executável (PyInstaller)
        dll_path = os.path.join(sys._MEIPASS, dll_name)
    else:
        # Modo desenvolvimento
        dll_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), dll_name)

    rfid_sdk = ctypes.CDLL(dll_path)
except OSError as e:
    try:
        messagebox.showerror(
            t('fastthreshold.dll_critical_error'),
            t('fastthreshold.dll_critical_error_msg').format(dll=dll_name, error=str(e)),
        )
    except Exception:
        try:
            from .i18n import TRANSLATIONS, get_translator
            _trans = get_translator()
            _lc = 'pt' if str((_trans.get_language() if _trans else None) or 'pt').startswith('pt') else 'en'
            _b = TRANSLATIONS.get(_lc, TRANSLATIONS.get('pt', {}))
            _tpl = _b.get(
                'fastthreshold.dll_critical_error_msg',
                "Could not load DLL '{dll}'.\nMake sure the file is in the same folder as the program.\n\nReason: {error}",
            )
            messagebox.showerror(
                _b.get('fastthreshold.dll_critical_error', 'Critical DLL Error'),
                _tpl.format(dll=dll_name, error=str(e)),
            )
        except Exception:
            try:
                from .i18n import TRANSLATIONS
                _b = TRANSLATIONS.get('pt', TRANSLATIONS.get('en', {}))
                _tpl = _b.get(
                    'fastthreshold.dll_critical_error_msg',
                    "Could not load DLL '{dll}'.\nMake sure the file is in the same folder as the program.\n\nReason: {error}",
                )
                messagebox.showerror(
                    _b.get('fastthreshold.dll_critical_error', 'Critical DLL Error'),
                    _tpl.format(dll=dll_name, error=str(e)),
                )
            except Exception:
                messagebox.showerror(
                    'Critical DLL Error',
                    f"Could not load DLL '{dll_name}'.\nMake sure the file is in the same folder as the program.\n\nReason: {e}",
                )
    sys.exit()

rfid_sdk.UHF_RFID_Open.argtypes = [ctypes.c_ubyte, ctypes.c_int]; rfid_sdk.UHF_RFID_Open.restype = ctypes.c_int
rfid_sdk.UHF_RFID_Close.argtypes = [ctypes.c_ubyte]; rfid_sdk.UHF_RFID_Close.restype = ctypes.c_int
rfid_sdk.UHF_RFID_Set.argtypes = [ctypes.c_int, ctypes.c_char_p, ctypes.c_uint, ctypes.c_char_p, ctypes.POINTER(ctypes.c_uint)]; rfid_sdk.UHF_RFID_Set.restype = ctypes.c_int

# Comandos da DLL
RFID_CMD_GET_TEMPERATURE = 0x34
RFID_CMD_SET_CW_STATUS = 0x24
RFID_CMD_GET_PORT_LOSS = 0x32
RFID_CMD_SET_TXPOWER = 0x10
RFID_CMD_SET_FREQ_TABLE = 0x14
RFID_CMD_INV_TAG = 0x80
RFID_CMD_GET_RSSIVALU = 0x64
RFID_CMD_STOP_INVENTORY = 0x82

# --- PARÂMETROS ---
DEFAULT_MAX_POWER_DBM = 25
DEFAULT_MIN_POWER_DBM = 5
DEFAULT_MIN_FREQ_MHZ = 902
DEFAULT_MAX_FREQ_MHZ = 928

INVENTORY_POWER_DBM = 15
HEATING_POWER_DBM = 25
BAUD_RATE = 115200
REFLECTED_POWER_LIMIT = 10.0  # dBm - Potência refletida máxima aceitável
TEMPERATURE_LIMIT = 50.0

RxAdcTable = [
    0x0000, 0x0000, 0x0000, 0x0001, 0x0002, 0x0005, 0x0007, 0x000B, 0x0010, 0x0116, 0x011D, 0x0126,
    0x0131, 0x013E, 0x024C, 0x0260, 0x0374, 0x048B, 0x05A5, 0x06C3, 0x08E6, 0x09FF, 0x0BFF, 0x0EFF,
    0x10FF, 0x14FF, 0x17FF, 0x1CFF, 0x21FF, 0x26FF, 0x2DFF, 0x34FF, 0x3CFF, 0x46FF, 0x50FF, 0x5DFF,
    0x6AFF, 0x7AFF, 0x8BFF, 0x9EFF, 0xB4FF, 0xCCFF, 0xE7FF, 0xFFFF
]

class QuickThresholdModule(tk.Frame):
    def __init__(self, master, hardware_controller=None, demo_mode=False, com_port=4, app_shell=None):
        super().__init__(master)
        self.master = master
        self.hardware_controller = hardware_controller
        self.demo_mode = demo_mode
        self.com_port = com_port
        self.app_shell = app_shell
        self.port_manager = get_port_manager()
        self.translator = get_translator()
        self._widget_refs = {}  # Para armazenar referências aos widgets para atualização de idioma

        self.root_window = self.master.winfo_toplevel()
        # Em AppShell, não sobrescreve o título global da aplicação ao trocar de aba.
        if self.app_shell is None and self.root_window == self.master:
            self.root_window.title(t('fastthreshold.title'))

        self.grid(row=0, column=0, sticky="nsew")
        self.master.columnconfigure(0, weight=1) # Modificado
        self.master.rowconfigure(0, weight=1) # Modificado

        self.module_name = "QuickThreshold"
        self.blinking_job_id = None
        self.pady_val = 3

        # Captura o evento de destruição do frame
        self.bind("<Destroy>", self._on_frame_destroy)

        # Inicialização da licença
        self.license_limits = {'min_freq': DEFAULT_MIN_FREQ_MHZ, 'max_freq': DEFAULT_MAX_FREQ_MHZ, 'min_power': DEFAULT_MIN_POWER_DBM, 'max_power': DEFAULT_MAX_POWER_DBM, 'is_licensed': False}

        # Atualiza limites de licença do app_shell
        self.after(500, self._update_license_limits_from_app_shell)

        self.results_queue = queue.Queue()
        self.scan_parameters = []
        self.available_tags, self.selected_epc = [], None
        self.last_tag_test_data, self.last_threshold_test_data = None, None

        # Estado de execução/cancelamento do teste
        self.test_running = False
        self.cancel_requested = False

        # Sistema de persistência de dados
        self.db_file = os.path.join(os.path.dirname(os.path.abspath(__file__)), "fast_threshold_db.json")
        self.all_tag_test_data, self.test_history = [], []
        self.tags_testadas, self.tags_aprovadas, self.tags_reprovadas = 0, 0, 0

        # Inicializa variáveis de threshold
        self.threshold_graph_data = []

        # NOVO: Frequências persistentes para os testes 1-5
        self.persistent_frequencies = [None, None, None, None, None]

        # CORREÇÃO: Flag para controlar se dados foram limpos pelo usuário
        self.data_cleared_by_user = False

        # CORREÇÃO: Armazena temporariamente o nome do teste para restaurar depois
        self._pending_test_name = ""
        self._pending_frequencies = [None, None, None, None, None]

        # Carrega dados persistentes
        self._load_persistent_data()
        self.tags_testadas_var = tk.StringVar(value="")
        self.tags_aprovadas_var = tk.StringVar(value="")
        self.tags_reprovadas_var = tk.StringVar(value="")
        self.yield_var = tk.StringVar(value="")

        # Variáveis para controle de ordenação
        self.current_sort_column = None
        self.current_sort_reverse = False

        self._create_widgets()
        self.update_ui_for_test_type()
        self.process_queue()

        # Restaura dados persistentes na interface
        self.restore_timer_1 = self.after(1000, self._restore_persistent_interface)
        self.restore_timer_2 = self.after(3000, self._restore_persistent_interface)

        # Inicia salvamento automático periódico
        self._start_auto_save()

        # Inicializa hardware
        self._initialize_hardware_on_enter()

    def _initialize_hardware_on_enter(self):
        """Inicializa hardware ao entrar no módulo - sem capturar porta COM"""
        # CORREÇÃO: Não captura porta COM para evitar conflitos
        # A porta será aberta apenas durante os testes
        fc_log("fast_threshold", f"🔧 FastThreshold: Módulo inicializado (porta COM será gerenciada durante testes)")

    def _update_license_limits_from_app_shell(self):
        """Atualiza limites de licença a partir do app_shell"""
        try:
            if not hasattr(self, 'app_shell') or self.app_shell is None:
                fc_log("fast_threshold", f"⚠️ FastThreshold: app_shell não disponível para atualizar licença")
                return

            valid_lics = ["QuickThreshold", "FastChecker"]
            license_limits = self.app_shell._calculate_license_limits(valid_lics)

            if license_limits.get('is_licensed', False):
                self.license_limits = license_limits
                fc_log("fast_threshold", f"✅ FastThreshold: Licença atualizada - {license_limits.get('license_name', 'N/A')}")
                fc_log("fast_threshold", f"📊 FastThreshold: Frequências permitidas: {license_limits.get('min_freq', 800)}-{license_limits.get('max_freq', 1000)} MHz")
                fc_log("fast_threshold", f"📊 FastThreshold: Potências permitidas: {license_limits.get('min_power', 5)}-{license_limits.get('max_power', 25)} dBm")
                if license_limits.get('freq_ranges'):
                    fc_log("fast_threshold", f"📊 FastThreshold: Faixas específicas: {license_limits.get('freq_ranges', [])}")
            else:
                fc_log("fast_threshold", f"⚠️ FastThreshold: Nenhuma licença válida encontrada")

        except Exception as e:
            fc_log("fast_threshold", f"⚠️ FastThreshold: Erro ao atualizar licença: {e}")

    def destroy(self):
        """Cleanup ao sair do módulo"""
        try:
            fc_log("fast_threshold", f"🔄 FastThreshold: Iniciando cleanup...")

            if hasattr(self, 'test_running') and self.test_running:
                self.test_running = False

            # CORREÇÃO: Não tenta gerenciar porta COM - deixa para o app_shell
            fc_log("fast_threshold", f"✅ FastThreshold: Cleanup concluído")
        except:
            pass

        try:
            super().destroy()
        except:
            pass

    def _on_frame_destroy(self, event=None):
        """Captura a destruição do frame para garantir salvamento dos dados"""
        try:
            fc_log("fast_threshold", "🔄 FastThreshold: Frame sendo destruído, salvando dados...")
            # CORREÇÃO: Só salva se não foi uma limpeza manual recente
            if not hasattr(self, 'data_cleared_by_user') or not self.data_cleared_by_user:
                self._save_persistent_data()
            else:
                fc_log("fast_threshold", "🧹 Dados já foram limpos pelo usuário - não salvando na destruição")
        except Exception as e:
            fc_log("fast_threshold", f"⚠️ FastThreshold: Erro ao salvar dados na destruição: {e}")
            # CORREÇÃO: Não propaga o erro para evitar fechamento do programa
            pass
        
        # CORREÇÃO: Previne que o evento de destruição cause fechamento do programa
        return "break"

    def _create_widgets(self):
        """Cria a interface do usuário"""

        # --- INÍCIO DA MODIFICAÇÃO DE LAYOUT (PanedWindow 2x2 - CORRIGIDO) ---

        # Configura estilo para o PanedWindow (divisor) - Opcional, pode não ter efeito visual
        style = ttk.Style()
        # Tenta configurar o estilo padrão, pode ser ignorado pelo tema
        try:
             # O nome do estilo pode variar com o tema (e.g., 'TPanedwindow', 'Panedwindow')
             # Tentamos configurar alguns nomes comuns, mas sem forçar na criação
             style.configure("TPanedwindow", background=self.cget("bg"))
             style.configure("Panedwindow", background=self.cget("bg"))
             style.configure("Vertical.TPanedwindow", background=self.cget("bg"))
             style.configure("Horizontal.TPanedwindow", background=self.cget("bg"))
             style.configure("Vertical.Panedwindow", background=self.cget("bg"))
             style.configure("Horizontal.Panedwindow", background=self.cget("bg"))
        except tk.TclError:
             # Ignora se o estilo específico não existir no tema atual
             pass

        # 1. Painel Principal (Divisão Esquerda/Direita)
        # MODIFICADO: Removido style="TPanedWindow"
        self.main_paned_window = ttk.PanedWindow(self, orient=tk.HORIZONTAL)
        self.main_paned_window.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

        # 2. Painel da Esquerda (Divisão Cima/Baixo)
        # MODIFICADO: Removido style="TPanedWindow"
        self.left_pane = ttk.PanedWindow(self.main_paned_window, orient=tk.VERTICAL)
        self.main_paned_window.add(self.left_pane, weight=1) # Peso 1 para ~50%

        # 3. Painel da Direita (Divisão Cima/Baixo)
        # MODIFICADO: Removido style="TPanedWindow"
        self.right_pane = ttk.PanedWindow(self.main_paned_window, orient=tk.VERTICAL)
        self.main_paned_window.add(self.right_pane, weight=1) # Peso 1 para ~50%

        # --- Bloco Superior Esquerdo (Configs) ---
        # Frame para agrupar os 3 painéis de configuração
        self.top_left_frame = tk.Frame(self.left_pane, padx=0, pady=0, bg=self.cget("bg"))
        self.top_left_frame.columnconfigure(0, weight=1)
        self.left_pane.add(self.top_left_frame, weight=0) # weight=0 = Não expande

        # --- Bloco Inferior Esquerdo (Histórico) ---
        self.history_container = tk.LabelFrame(self.left_pane, text=t('fastthreshold.test_history'), padx=10, pady=10, font=("Helvetica", 10))
        self.left_pane.add(self.history_container, weight=1) # weight=1 = Expande
        self.history_container.rowconfigure(0, weight=1)
        self.history_container.columnconfigure(0, weight=1)
        self._widget_refs['history_container'] = self.history_container

        # --- Bloco Superior Direito (Gráfico) ---
        self.graph_frame = tk.LabelFrame(self.right_pane, text=t('fastthreshold.graph_title'), padx=10, pady=5, font=("Helvetica", 10))
        self.right_pane.add(self.graph_frame, weight=0) # weight=0 = Não expande
        self._widget_refs['graph_frame'] = self.graph_frame

        # --- Bloco Inferior Direito (Gráfico Estatístico) ---
        self.new_graph_frame = tk.LabelFrame(self.right_pane, text=t('fastthreshold.statistics'), 
                                            padx=10, pady=5, font=("Helvetica", 10))
        self.right_pane.add(self.new_graph_frame, weight=1) # weight=1 = Expande
        self._widget_refs['new_graph_frame'] = self.new_graph_frame

        # --- FIM DA MODIFICAÇÃO DE LAYOUT (PanedWindow 2x2) ---


        # --- Agora, preencha os blocos ---

        # --- Conteúdo do Bloco Superior Esquerdo (self.top_left_frame) ---

        # Frame de segurança
        safety_frame = tk.LabelFrame(self.top_left_frame, text=t('fastthreshold.safety_system'), padx=10, pady=5, font=("Helvetica", 10))
        safety_frame.grid(row=0, column=0, sticky="ew", pady=(0, 5)) # Espaçamento interno
        safety_frame.columnconfigure(3, weight=1)
        self._widget_refs['safety_frame'] = safety_frame

        self.safety_status_label = tk.Label(safety_frame, text="", fg="green", font=("Helvetica", 9))
        self.safety_status_label.grid(row=0, column=0, columnspan=5, sticky='w', padx=(0, 5))
        self._widget_refs['safety_status_label'] = self.safety_status_label

        self.temperature_label_text = tk.Label(safety_frame, text=t('fastthreshold.temperature'), fg="black")
        self.temperature_label_text.grid(row=1, column=0, sticky='w', padx=(0, 5))
        self._widget_refs['temperature_label_text'] = self.temperature_label_text
        
        self.temperature_label = tk.Label(safety_frame, text="--°C", fg="gray", font=("Helvetica", 10))
        self.temperature_label.grid(row=1, column=1, sticky='w')

        self.vswr_label_text = tk.Label(safety_frame, text=t('fastthreshold.vswr'), fg="black")
        self.vswr_label_text.grid(row=1, column=2, sticky='w', padx=(15, 5))
        self._widget_refs['vswr_label_text'] = self.vswr_label_text
        
        self.vswr_label = tk.Label(safety_frame, text="--", fg="gray", font=("Helvetica", 10))
        self.vswr_label.grid(row=1, column=3, sticky='w')
        self.vswr_status_label = tk.Label(safety_frame, text="", fg="gray", font=("Helvetica", 8))
        self.vswr_status_label.grid(row=1, column=4, sticky='w', padx=(5,0))

        # Frame de configuração de teste
        test_config_frame = tk.LabelFrame(self.top_left_frame, text=t('fastthreshold.test_config'), padx=10, pady=5, font=("Helvetica", 10))
        test_config_frame.grid(row=1, column=0, sticky="ew", pady=(0, 5)) # Espaçamento interno
        self._widget_refs['test_config_frame'] = test_config_frame

        # Campo Nome do Teste
        test_name_label = tk.Label(test_config_frame, text=t('fastthreshold.test_name'), font=("Helvetica", 10, "bold"))
        test_name_label.grid(row=0, column=0, padx=(0, 5), pady=(0, 10), sticky="w")
        self._widget_refs['test_name_label'] = test_name_label
        self.test_name_var = tk.StringVar()
        self.test_name_entry = tk.Entry(test_config_frame, font=("Helvetica", 10), width=30, textvariable=self.test_name_var)
        self.test_name_entry.grid(row=0, column=1, columnspan=4, padx=(0, 0), pady=(0, 10), sticky="ew")
        self.test_name_entry.bind('<FocusOut>', lambda e: self._save_test_name())
        self.test_name_entry.bind('<Return>', lambda e: self._save_test_name())

        # Configuração das frequências e threshold
        freq_header = tk.Label(test_config_frame, text=t('fastthreshold.freq_mhz'), font=("Helvetica", 10))
        freq_header.grid(row=2, column=1, padx=5)
        self._widget_refs['freq_header'] = freq_header
        
        threshold_header = tk.Label(test_config_frame, text=t('fastthreshold.threshold_dbm'), font=("Helvetica", 10))
        threshold_header.grid(row=2, column=2, columnspan=2, padx=5)
        self._widget_refs['threshold_header'] = threshold_header

        # 5 linhas de teste
        self.freq_entries = []
        self.threshold_entries = []
        self.test_labels = []

        for i in range(5):
            test_label = tk.Label(test_config_frame, text=f"{t('fastthreshold.test')} {i+1}:")
            test_label.grid(row=i+3, column=0, padx=5, pady=2, sticky="w")
            self.test_labels.append(test_label)

            # Campo de frequência
            freq_entry = tk.Entry(test_config_frame, width=10, justify='center')
            freq_entry.grid(row=i+3, column=1, padx=5, pady=2)
            freq_entry.bind('<FocusOut>', lambda e, idx=i: self._save_frequency_change(idx))
            freq_entry.bind('<Return>', lambda e, idx=i: self._save_frequency_change(idx))
            self.freq_entries.append(freq_entry)

            # Campo de threshold (será preenchido automaticamente)
            threshold_entry = tk.Entry(test_config_frame, width=10, justify='center', state='readonly')
            threshold_entry.grid(row=i+3, column=2, padx=5, pady=2)
            self.threshold_entries.append(threshold_entry)

        # Botões de controle
        command_button_frame = tk.Frame(test_config_frame)
        command_button_frame.grid(row=2, column=4, rowspan=6, padx=20, sticky="ns")

        self.start_button = tk.Button(command_button_frame, text=t('fastthreshold.test_button'), command=self.start_measurement,
                                     font=("Helvetica", 10), width=15)
        self.start_button.pack(pady=3, fill="x")
        self._widget_refs['start_button'] = self.start_button

        self.clear_button = tk.Button(command_button_frame, text=t('fastthreshold.clear'), command=self.clear_all_data,
                                    font=("Helvetica", 10), width=15)
        self.clear_button.pack(pady=3, fill="x")
        self._widget_refs['clear_button'] = self.clear_button

        self.save_button = tk.Button(command_button_frame, text=t('fastthreshold.save'), command=self.save_report_to_file,
                                   font=("Helvetica", 10), width=15)
        self.save_button.pack(pady=3, fill="x")
        self._widget_refs['save_button'] = self.save_button

        self.import_button = tk.Button(command_button_frame, text=t('fastthreshold.import'), command=self.import_report_from_file,
                                     font=("Helvetica", 10), width=15)
        self.import_button.pack(pady=3, fill="x")
        self._widget_refs['import_button'] = self.import_button

        self.report_button = tk.Button(command_button_frame, text=t('fastthreshold.report_pdf'), command=self.generate_pdf_report,
                                     font=("Helvetica", 10), width=15)
        self.report_button.pack(pady=3, fill="x")
        self._widget_refs['report_button'] = self.report_button

        # Status label - CORREÇÃO: Movido para não bloquear o Teste 5
        self.status_label = tk.Label(test_config_frame, text=t('fastthreshold.ready'),
                                   font=("Helvetica", 9), fg="#27ae60")
        self.status_label.grid(row=8, column=0, columnspan=3, pady=(5, 0), sticky="w")
        self._widget_refs['status_label'] = self.status_label

        # Frame de resumo
        self.summary_frame = tk.LabelFrame(self.top_left_frame, text=t('fastthreshold.execution_summary'), padx=10, pady=5, font=("Helvetica", 9))
        self._widget_refs['summary_frame'] = self.summary_frame
        self.summary_frame.grid(row=2, column=0, sticky="ew", pady=(0, 5)) # Espaçamento interno

        summary_inner = tk.Frame(self.summary_frame)
        summary_inner.pack(fill='x')

        # Tags Testadas e Tags Selecionadas - layout compacto
        self.tags_display_label = tk.Label(summary_inner, text="Tags Testadas: 0 | Tags Selecionadas: 0", font=("Helvetica", 10))
        self.tags_display_label.grid(row=0, column=0, sticky="w")
        
        # Atualiza o label quando os valores mudam
        self.tags_testadas_var.trace('w', self._update_tags_display)

        # Botões de gerenciamento do histórico - seguindo padrão do Noise Check
        buttons_frame = tk.Frame(summary_inner)
        buttons_frame.grid(row=1, column=0, columnspan=2, pady=(10, 0), sticky="ew")

        self.select_all_button = ttk.Button(buttons_frame, text=t('fastthreshold.select_all'), 
                                           command=self._select_all_tests)
        self.select_all_button.pack(side="left", padx=(0, 5), fill="x", expand=True)
        self._widget_refs['select_all_button'] = self.select_all_button

        self.deselect_all_button = ttk.Button(buttons_frame, text=t('fastthreshold.deselect_all'), 
                                             command=self._deselect_all_tests)
        self.deselect_all_button.pack(side="left", padx=(0, 5), fill="x", expand=True)
        self._widget_refs['deselect_all_button'] = self.deselect_all_button

        self.delete_selected_button = ttk.Button(buttons_frame, text=t('fastthreshold.delete_selected'), 
                                                command=self._delete_selected_tests)
        self.delete_selected_button.pack(side="left", padx=(0, 5), fill="x", expand=True)
        self._widget_refs['delete_selected_button'] = self.delete_selected_button

        self.generate_stats_button = ttk.Button(buttons_frame, text=t('fastthreshold.generate_stats'), 
                                               command=self._generate_statistics)
        self.generate_stats_button.pack(side="left", padx=(0, 5), fill="x", expand=True)
        self._widget_refs['generate_stats_button'] = self.generate_stats_button

        self.export_excel_button = ttk.Button(buttons_frame, text=t('fastthreshold.export_excel'), 
                                             command=self._export_to_excel)
        self.export_excel_button.pack(side="left", padx=(0, 5), fill="x", expand=True)
        self._widget_refs['export_excel_button'] = self.export_excel_button


        # --- Conteúdo do Bloco Superior Direito (self.graph_frame) ---

        # Usa figsize razoável
        self.threshold_fig = Figure(figsize=(7, 4), dpi=100) # Mantido

        self.threshold_ax = self.threshold_fig.add_subplot(111)
        self.threshold_ax.set_ylabel(t('fastthreshold.threshold_dbm_label'))
        self.threshold_ax.set_ylim(5, 25)
        self.threshold_ax.grid(True, alpha=0.3)

        # Canvas para o gráfico
        self.threshold_canvas = FigureCanvasTkAgg(self.threshold_fig, self.graph_frame)
        self.threshold_canvas.draw()
        self.threshold_canvas.get_tk_widget().pack(fill="both", expand=True)

        # Hover para mostrar valores dos pontos ao passar o mouse (igual aos outros módulos)
        self._setup_threshold_hover()

        # Layout com mais espaço para legenda larga
        self.threshold_fig.subplots_adjust(left=0.1, right=0.55, top=0.95, bottom=0.1)


        # --- Conteúdo do Bloco Inferior Direito (self.new_graph_frame) ---

        # Gráfico estatístico
        self.stats_fig = Figure(figsize=(7, 4), dpi=100)
        self.stats_ax = self.stats_fig.add_subplot(111)
        self.stats_ax.set_ylabel(t('fastthreshold.threshold_dbm_label'))
        self.stats_ax.set_ylim(5, 25)
        self.stats_ax.grid(True, alpha=0.3)

        # Canvas para o gráfico estatístico
        self.stats_canvas = FigureCanvasTkAgg(self.stats_fig, self.new_graph_frame)
        self.stats_canvas.draw()
        self.stats_canvas.get_tk_widget().pack(fill="both", expand=True)
        
        # NOVO: Configura hover para o gráfico de Análise Estatística
        self._setup_stats_hover()

        # Layout com espaço para legenda
        self.stats_fig.subplots_adjust(left=0.1, right=0.75, top=0.95, bottom=0.1)


        # --- Conteúdo do Bloco Inferior Esquerdo (self.history_container) ---

        cols = ('Plot', 'EPC', 'Freq 1', 'Freq 2', 'Freq 3', 'Freq 4', 'Freq 5', 'Data/Hora')
        self.history_tree = ttk.Treeview(self.history_container, columns=cols, show='headings', height=20)

        # Headers com comandos de ordenação (mesmo padrão RSSI x Power: Plot ↕, ☑/☐)
        self.history_tree.heading('Plot', text=f"{t('fastthreshold.plot')} ↕", command=lambda: self.sort_treeview('Plot'))
        self.history_tree.column('Plot', width=40, anchor='center')

        self.history_tree.heading('EPC', text=f"{t('fastthreshold.tag_epc')} ↕", command=lambda: self.sort_treeview('EPC'))
        self.history_tree.column('EPC', width=180, anchor='w')

        for i in range(5):
            col_name = f'Freq {i+1}'
            self.history_tree.heading(col_name, text=f'Freq {i+1} ↕', command=lambda c=col_name: self.sort_treeview(c))
            self.history_tree.column(col_name, width=80, anchor='center')

        self.history_tree.heading('Data/Hora', text=f"{t('fastthreshold.date_time')} ↕", command=lambda: self.sort_treeview('Data/Hora'))
        self.history_tree.column('Data/Hora', width=120, anchor='center')

        history_scrollbar = ttk.Scrollbar(self.history_container, orient="vertical", command=self.history_tree.yview)
        self.history_tree.configure(yscrollcommand=history_scrollbar.set)
        self.history_tree.grid(row=0, column=0, sticky="nsew", padx=5, pady=5)
        history_scrollbar.grid(row=0, column=1, sticky="ns")

        # Métodos de clique serão criados abaixo
        self.history_tree.bind('<Button-1>', self.on_tree_click)
        self.history_tree.bind('<Double-1>', self.on_tree_double_click)
        
        # Atualiza estado da UI
        self.update_ui_state()
    
    def refresh_language(self):
        """Atualiza todos os textos da interface quando o idioma é alterado"""
        try:
            # Atualiza título apenas em modo standalone (fora do AppShell)
            if self.app_shell is None and self.root_window == self.master:
                self.root_window.title(t('fastthreshold.title'))
            
            # Atualiza títulos de frames
            if 'history_container' in self._widget_refs:
                self._widget_refs['history_container'].config(text=t('fastthreshold.test_history'))
            if 'graph_frame' in self._widget_refs:
                self._widget_refs['graph_frame'].config(text=t('fastthreshold.graph_title'))
            if 'new_graph_frame' in self._widget_refs:
                self._widget_refs['new_graph_frame'].config(text=t('fastthreshold.statistics'))
            if 'safety_frame' in self._widget_refs:
                self._widget_refs['safety_frame'].config(text=t('fastthreshold.safety_system'))
            if 'test_config_frame' in self._widget_refs:
                self._widget_refs['test_config_frame'].config(text=t('fastthreshold.test_config'))
            if 'summary_frame' in self._widget_refs:
                self._widget_refs['summary_frame'].config(text=t('fastthreshold.execution_summary'))
            
            # Atualiza labels
            if 'temperature_label_text' in self._widget_refs:
                self._widget_refs['temperature_label_text'].config(text=t('fastthreshold.temperature'))
            if 'vswr_label_text' in self._widget_refs:
                self._widget_refs['vswr_label_text'].config(text=t('fastthreshold.vswr'))
            if 'test_name_label' in self._widget_refs:
                self._widget_refs['test_name_label'].config(text=t('fastthreshold.test_name'))
            if 'freq_header' in self._widget_refs:
                self._widget_refs['freq_header'].config(text=t('fastthreshold.freq_mhz'))
            if 'threshold_header' in self._widget_refs:
                self._widget_refs['threshold_header'].config(text=t('fastthreshold.threshold_dbm'))
            
            # Atualiza labels de teste (Teste 1:, Teste 2:, etc.)
            if hasattr(self, 'test_labels'):
                for i, label in enumerate(self.test_labels):
                    label.config(text=f"{t('fastthreshold.test')} {i+1}:")
            
            # Atualiza botões
            if 'start_button' in self._widget_refs:
                current = self.start_button.cget('text')
                if 'Testando' in current or 'Testing' in current:
                    self.start_button.config(text=t('fastthreshold.testing'))
                else:
                    self.start_button.config(text=t('fastthreshold.test_button'))
            if 'clear_button' in self._widget_refs:
                self._widget_refs['clear_button'].config(text=t('fastthreshold.clear'))
            if 'save_button' in self._widget_refs:
                self._widget_refs['save_button'].config(text=t('fastthreshold.save'))
            if 'import_button' in self._widget_refs:
                self._widget_refs['import_button'].config(text=t('fastthreshold.import'))
            if 'report_button' in self._widget_refs:
                self._widget_refs['report_button'].config(text=t('fastthreshold.report_pdf'))
            if 'select_all_button' in self._widget_refs:
                self._widget_refs['select_all_button'].config(text=t('fastthreshold.select_all'))
            if 'deselect_all_button' in self._widget_refs:
                self._widget_refs['deselect_all_button'].config(text=t('fastthreshold.deselect_all'))
            if 'delete_selected_button' in self._widget_refs:
                self._widget_refs['delete_selected_button'].config(text=t('fastthreshold.delete_selected'))
            if 'generate_stats_button' in self._widget_refs:
                self._widget_refs['generate_stats_button'].config(text=t('fastthreshold.generate_stats'))
            if 'export_excel_button' in self._widget_refs:
                self._widget_refs['export_excel_button'].config(text=t('fastthreshold.export_excel'))
            
            # Atualiza status label
            if 'status_label' in self._widget_refs:
                current = self.status_label.cget('text')
                if 'Pronto' in current or 'Ready' in current:
                    self.status_label.config(text=t('fastthreshold.ready'))
                elif 'Testando tag' in current or 'Testing tag' in current:
                    self.status_label.config(text=t('fastthreshold.testing_tag'))
            
            # Atualiza cabeçalhos da tabela
            if hasattr(self, 'history_tree'):
                self.history_tree.heading('Plot', text=f"{t('fastthreshold.plot')} ↕")
                self.history_tree.heading('EPC', text=f"{t('fastthreshold.tag_epc')} ↕")
                self.history_tree.heading('Data/Hora', text=f"{t('fastthreshold.date_time')} ↕")
                
                # Atualiza labels de Tags Testadas/Selecionadas se necessário
                if hasattr(self, 'tags_display_label'):
                    current = self.tags_display_label.cget('text')
                    import re
                    # Extrai números do texto atual
                    matches = re.findall(r'\d+', current)
                    if len(matches) >= 2:
                        tested = matches[0]
                        selected = matches[1]
                        no_test = matches[2] if len(matches) > 2 else "0"
                        self.tags_display_label.config(text=f"{t('fastthreshold.tags_tested')} {tested} | {t('fastthreshold.tags_selected')} {selected}")
        except Exception as e:
            fc_log("fast_threshold", f"⚠️ Erro ao atualizar idioma no FastThreshold: {e}")

    def _save_test_name(self):
        """Salva nome do teste quando o usuário sai do campo ou pressiona Enter"""
        try:
            fc_log("fast_threshold", f"🔍 _save_test_name chamada")
            if hasattr(self, 'test_name_entry'):
                test_name = self.test_name_entry.get().strip()
                fc_log("fast_threshold", f"💾 Nome do teste obtido do campo: '{test_name}'")
                # Atualiza _pending_test_name para uso em _save_persistent_data
                self._pending_test_name = test_name
                fc_log("fast_threshold", f"💾 _pending_test_name atualizado: '{self._pending_test_name}'")
                # Salva dados persistentes automaticamente
                self._save_persistent_data()
                fc_log("fast_threshold", f"✅ Nome do teste salvo com sucesso")
            else:
                fc_log("fast_threshold", f"⚠️ test_name_entry não existe em _save_test_name")
        except Exception as e:
            fc_log("fast_threshold", f"❌ Erro ao salvar nome do teste: {e}")
            import traceback
            traceback.print_exc()

    def _save_frequency_change(self, index):
        """Salva frequência alterada quando o usuário sai do campo ou pressiona Enter"""
        try:
            if 0 <= index < len(self.freq_entries):
                freq_text = self.freq_entries[index].get().strip()
                if freq_text:
                    try:
                        freq_value = float(freq_text)
                        self.persistent_frequencies[index] = freq_value
                        fc_log("fast_threshold", f"💾 Frequência {index+1} salva: {freq_value} MHz")
                        # Salva dados persistentes automaticamente
                        self._save_persistent_data()
                    except ValueError:
                        fc_log("fast_threshold", f"⚠️ Frequência {index+1} inválida: {freq_text}")
                else:
                    # Campo vazio - remove frequência salva
                    self.persistent_frequencies[index] = None
                    fc_log("fast_threshold", f"🗑️ Frequência {index+1} removida")
                    self._save_persistent_data()
        except Exception as e:
            fc_log("fast_threshold", f"❌ Erro ao salvar frequência {index+1}: {e}")

    def update_ui_for_test_type(self):
        """Atualiza interface baseada no tipo de teste"""
        pass  # Quick Threshold sempre usa threshold

    def update_ui_state(self):
        """Atualiza estado da UI baseado na licença"""
        # CORREÇÃO: Sempre habilita o botão para permitir testes
        self.start_button.config(state='normal')

    def start_measurement(self):
        """Inicia medição de threshold"""
        if self.demo_mode:
            messagebox.showinfo(t('fastthreshold.demo_mode_title'), t('fastthreshold.demo_mode_msg'))
            return
        
        # Validação de nome do teste (obrigatório)
        test_name = self.test_name_var.get().strip() if hasattr(self, 'test_name_var') else ""
        if not test_name:
            messagebox.showerror(t('fastthreshold.error'), t('fastthreshold.test_name_required'), parent=self)
            return

        # Limpa os 5 valores dos testes anteriores (campos de threshold)
        try:
            if hasattr(self, 'threshold_entries') and isinstance(self.threshold_entries, list):
                for i in range(min(5, len(self.threshold_entries))):
                    entry = self.threshold_entries[i]
                    try:
                        entry.config(state='normal')
                        entry.delete(0, 'end')
                    except Exception:
                        pass
        except Exception:
            pass

        # Valida frequências (igual ao Fasusurance)
        frequencies = []
        for i, entry in enumerate(self.freq_entries):
            try:
                freq = float(entry.get())

                # Validação igual ao Fasusurance
                freq_valid = False
                freq_ranges = self.license_limits.get('freq_ranges', [])
                excluded_ranges = self.license_limits.get('excluded_ranges', [])

                if freq_ranges:
                    # Valida contra faixas específicas
                    for range_min, range_max in freq_ranges:
                        if range_min <= freq <= range_max:
                            # Verifica se não está em uma faixa excluída
                            in_excluded = False
                            for excl_min, excl_max in excluded_ranges:
                                if excl_min <= freq <= excl_max:
                                    in_excluded = True
                                    fc_log("fast_threshold", f"⚠️ FastThreshold: Frequência {freq} MHz está na faixa excluída {excl_min}-{excl_max} MHz")
                                    break
                            
                            if not in_excluded:
                                freq_valid = True
                                fc_log("fast_threshold", f"✅ FastThreshold: Frequência {freq} MHz ACEITA na faixa {range_min}-{range_max} MHz")
                                break
                            else:
                                fc_log("fast_threshold", f"❌ FastThreshold: Frequência {freq} MHz REJEITADA - faixa excluída")
                else:
                    # Fallback para validação simples
                    min_freq = self.license_limits.get('min_freq', 800)
                    max_freq = self.license_limits.get('max_freq', 1000)
                    freq_valid = (min_freq <= freq <= max_freq)

                if not freq_valid:
                    messagebox.showerror(t('fastthreshold.error'), t('fastthreshold.freq_not_allowed').format(n=i+1, freq=freq))
                    return

                frequencies.append(freq)
            except ValueError:
                messagebox.showerror(t('fastthreshold.error'), t('fastthreshold.freq_invalid').format(n=i+1))
                return

        if not frequencies:
            messagebox.showerror(t('fastthreshold.error'), t('fastthreshold.no_freq_configured'))
            return

        # Prepara parâmetros de teste
        self.scan_parameters = []
        for i, freq in enumerate(frequencies):
            self.scan_parameters.append({
                'index': i,
                'freq': freq
            })

        # Marca estado de execução e reseta cancelamento
        self.cancel_requested = False
        self.test_running = True

        self.start_button.config(state="disabled", text=t('fastthreshold.testing'))
        self.status_label.config(text=t('fastthreshold.testing_tag'), fg="#f39c12")

        if self.app_shell:
            self.app_shell.set_test_running(True, "QuickThreshold")

        # Inicia thread de medição
        worker_thread = threading.Thread(target=self._measurement_workflow, daemon=True)
        worker_thread.start()

    def _measurement_workflow(self):
        """Workflow principal de medição"""
        try:
            if not self.port_manager.acquire_port("QuickThreshold", timeout=2.0):
                self.results_queue.put({'error': f"Timeout ao adquirir a porta COM{self.com_port}."})
                return
            if rfid_sdk.UHF_RFID_Open(self.com_port, BAUD_RATE) != 0:
                self.results_queue.put({'error': f"Falha ao abrir a porta COM{self.com_port}."})
                self.port_manager.release_port("QuickThreshold")
                return

            # Verificações de segurança
            current_temp = self._get_temperature_worker()
            if current_temp is None:
                self.results_queue.put({'error': "Falha na comunicação: Temperatura"})
                return

            current_vswr = self._get_vswr_worker()
            if current_vswr is None:
                self.results_queue.put({'error': "Falha na comunicação: VSWR"})
                return

            self.results_queue.put({'type': 'SAFETY_UPDATE', 'temp': current_temp, 'reflected_power': current_vswr})

            # Verifica limites de segurança
            if current_temp >= TEMPERATURE_LIMIT:
                self.results_queue.put({'error': f"Temperatura crítica: {current_temp:.1f}°C. Teste bloqueado por segurança."})
                return

            if current_vswr > REFLECTED_POWER_LIMIT:
                self.results_queue.put({'error': f"VSWR alto: {current_vswr:.1f}. Verifique o sistema irradiante."})
                return

            # Executa medições de threshold
            self.results_queue.put({'type': 'STATUS_UPDATE', 'text': 'Iniciando medições de threshold...'})

            threshold_results = []
            detected_epc = None

            for params in self.scan_parameters:
                # Cancelamento antes de cada frequência
                if getattr(self, 'cancel_requested', False):
                    self.results_queue.put({'type': 'MEASUREMENT_CANCELLED'})
                    return
                freq = params['freq']
                self.results_queue.put({'type': 'STATUS_UPDATE', 'text': f'Medindo threshold em {freq} MHz...'})

                threshold, epc = self._measure_threshold_at_frequency(freq)
                # Cancelamento após tentativa de medir
                if getattr(self, 'cancel_requested', False):
                    self.results_queue.put({'type': 'MEASUREMENT_CANCELLED'})
                    return
                if threshold is not None:
                    threshold_results.append({'freq': freq, 'threshold': threshold})
                    self.results_queue.put({'type': 'THRESHOLD_RESULT', 'freq': freq, 'threshold': threshold})
                    if epc and not detected_epc:
                        detected_epc = epc  # Captura o primeiro EPC detectado
                else:
                    self.results_queue.put({'type': 'THRESHOLD_ERROR', 'freq': freq, 'error': 'Falha na medição'})

            # Processa resultados
            if threshold_results:
                self.results_queue.put({'type': 'MEASUREMENT_COMPLETE', 'results': threshold_results, 'epc': detected_epc})

        except Exception as e:
            self.results_queue.put({'error': f"Erro durante medição: {e}"})
        finally:
            try:
                rfid_sdk.UHF_RFID_Close(self.com_port)
            except:
                pass
            self.port_manager.release_port("QuickThreshold")

    def _measure_threshold_at_frequency(self, frequency):
        """Mede threshold em uma frequência específica - implementação real baseada no Fasusurance"""
        try:
            # Checagem de cancelamento imediata
            if getattr(self, 'cancel_requested', False):
                return None, None
            # Configura frequência
            freq_data = b'\x01' + int(frequency * 1000).to_bytes(3, 'big')
            output_buffer, output_len = ctypes.create_string_buffer(256), ctypes.c_uint(0)
            rfid_sdk.UHF_RFID_Set(RFID_CMD_SET_FREQ_TABLE, ctypes.c_char_p(freq_data), 4, output_buffer, ctypes.byref(output_len))

            # Parâmetros de busca de threshold (igual ao Fasusurance)
            start_power_for_run = self.license_limits.get('max_power', DEFAULT_MAX_POWER_DBM)
            min_power = self.license_limits.get('min_power', DEFAULT_MIN_POWER_DBM)
            stop_value = (min_power * 10) - 5

            # Timeout de segurança
            HARD_TIMEOUT_S = 6.0
            start_time = time.time()
            iteration_count = 0
            last_successful_power = None
            detected_epc = None

            fc_log("fast_threshold", f"🔍 Iniciando busca de threshold em {frequency} MHz (de {start_power_for_run} dBm até {min_power} dBm)")

            # Loop de busca de threshold (igual ao Fasusurance)
            for power_int_x10 in range(start_power_for_run * 10, stop_value, -5):
                if getattr(self, 'cancel_requested', False):
                    return None, None
                if time.time() - start_time > HARD_TIMEOUT_S:
                    fc_log("fast_threshold", f"⏱️ Timeout de threshold em {frequency} MHz - sem leitura dentro de {HARD_TIMEOUT_S}s")
                    break

                power_dbm = power_int_x10 / 10.0
                fc_log("fast_threshold", f"🔍 Testando {frequency} MHz em {power_dbm} dBm...")

                # CORREÇÃO: Envia atualização em tempo real para a interface
                # Encontra o índice da frequência atual nos parâmetros de teste
                freq_index = None
                for i, params in enumerate(self.scan_parameters):
                    if params['freq'] == frequency:
                        freq_index = i
                        break

                if freq_index is not None:
                    self.results_queue.put({'type': 'LIVE_UPDATE', 'row': freq_index, 'power': power_dbm})

                # Configura potência (igual ao Fasusurance)
                power_val = int(power_dbm * 100)
                power_data = bytes([0x00, 0x00]) + power_val.to_bytes(2, 'big') * 2
                rfid_sdk.UHF_RFID_Set(RFID_CMD_SET_TXPOWER, ctypes.c_char_p(power_data), 6, output_buffer, ctypes.byref(output_len))

                time.sleep(0.02)  # Delay de estabilização

                # Tenta inventário (igual ao Fasusurance)
                inv_tag_input_data = bytes([0x00, 0x1E])
                ret = rfid_sdk.UHF_RFID_Set(RFID_CMD_INV_TAG, ctypes.c_char_p(inv_tag_input_data), 2, output_buffer, ctypes.byref(output_len))

                if ret == 0 and output_len.value > 5:
                    # Tag detectada - este é o threshold
                    # CORREÇÃO: Extração correta do EPC (igual ao Threshold Module)
                    detected_epc = output_buffer.raw[2:14].hex().upper()
                    last_successful_power = power_dbm
                    fc_log("fast_threshold", f"✅ Tag detectada em {frequency} MHz: {power_dbm} dBm (EPC: {detected_epc})")
                    # No Quick Threshold, não há filtro por EPC - qualquer tag detectada é válida
                    # Continua o loop para encontrar o threshold mais baixo possível
                else:
                    # Nenhuma tag detectada - se já tinha uma tag detectada antes, para aqui
                    if last_successful_power is not None:
                        fc_log("fast_threshold", f"✅ Threshold encontrado em {frequency} MHz: {last_successful_power} dBm")
                        break
                    fc_log("fast_threshold", f"❌ Nenhuma tag detectada em {frequency} MHz: {power_dbm} dBm")

            # Determina resultado final (igual ao Fasusurance)
            final_threshold_value = None
            if last_successful_power is None:
                final_threshold_value = f">{start_power_for_run:.1f}"
                fc_log("fast_threshold", f"❌ Threshold não encontrado em {frequency} MHz - acima de {start_power_for_run} dBm")
            elif last_successful_power == DEFAULT_MIN_POWER_DBM:
                final_threshold_value = f"<{DEFAULT_MIN_POWER_DBM:.1f}"
                fc_log("fast_threshold", f"✅ Threshold em {frequency} MHz: abaixo de {DEFAULT_MIN_POWER_DBM} dBm")
            else:
                final_threshold_value = last_successful_power
                fc_log("fast_threshold", f"✅ Threshold encontrado em {frequency} MHz: {last_successful_power} dBm")

            return final_threshold_value, detected_epc

        except Exception as e:
            fc_log("fast_threshold", f"Erro ao medir threshold em {frequency} MHz: {e}")
            return None, None


    def _get_temperature_worker(self):
        """Obtém temperatura do hardware - igual ao Fasusurance"""
        try:
            fc_log("fast_threshold", f"🌡️ FastThreshold: Iniciando medição de temperatura...")

            output_buffer = ctypes.create_string_buffer(64)
            output_len = ctypes.c_uint(0)

            fc_log("fast_threshold", f"🌡️ FastThreshold: Chamando RFID_CMD_GET_TEMPERATURE...")
            status = rfid_sdk.UHF_RFID_Set(RFID_CMD_GET_TEMPERATURE, None, 0, output_buffer, ctypes.byref(output_len))
            fc_log("fast_threshold", f"🌡️ FastThreshold: Status do comando: {status}")
            fc_log("fast_threshold", f"🌡️ FastThreshold: Tamanho da resposta: {output_len.value}")

            if status == 0 and output_len.value >= 3:
                # CORREÇÃO: Usa o mesmo método do Fasusurance
                temp_val = struct.unpack('>h', output_buffer.raw[1:3])[0]
                temp_celsius = temp_val / 100.0
                fc_log("fast_threshold", f"🌡️ FastThreshold: Temperatura lida: {temp_val} -> {temp_celsius}°C")
                return temp_celsius
            else:
                fc_log("fast_threshold", f"🌡️ FastThreshold: Erro na leitura de temperatura - Status: {status}, Len: {output_len.value}")

            return None
        except Exception as e:
            fc_log("fast_threshold", f"🌡️ FastThreshold: Erro ao ler temperatura: {e}")
            return None

    def _get_vswr_worker(self, tx_power_dbm=25):
        """Obtém VSWR do hardware"""
        try:
            # Implementação simplificada
            return 1.2  # Valor simulado
        except:
            return None

    def process_queue(self):
        """Processa fila de resultados"""
        try:
            while not self.results_queue.empty():
                result = self.results_queue.get_nowait()

                if result.get('type') == 'SAFETY_UPDATE':
                    temp = result.get('temp', 0)
                    vswr = result.get('reflected_power', 0)

                    self.temperature_label.config(text=f"{temp:.1f}°C")
                    self.vswr_label.config(text=f"{vswr:.1f}")

                    # Atualiza status de segurança
                    if temp >= TEMPERATURE_LIMIT or vswr > REFLECTED_POWER_LIMIT:
                        self.safety_status_label.config(text=t('fastthreshold.attention_critical'), fg="red")
                    else:
                        self.safety_status_label.config(text=t('fastthreshold.system_safe'), fg="green")

                elif result.get('type') == 'STATUS_UPDATE':
                    # Atualiza status na interface
                    pass

                elif result.get('type') == 'LIVE_UPDATE':
                    # Atualização em tempo real dos campos de threshold
                    row = result.get('row')
                    power = result.get('power')
                    if row is not None and row < len(self.threshold_entries) and power is not None:
                        entry = self.threshold_entries[row]
                        entry.config(state="normal")
                        entry.delete(0, 'end')
                        entry.insert(0, f"{power:.1f}")
                        entry.config(state="readonly")

                elif result.get('type') == 'THRESHOLD_RESULT':
                    freq = result.get('freq')
                    threshold = result.get('threshold')
                    self.update_threshold_graph(freq, threshold)

                elif result.get('type') == 'MEASUREMENT_COMPLETE':
                    results = result.get('results', [])
                    detected_epc = result.get('epc', None)
                    self._process_measurement_results(results, detected_epc)

                elif result.get('type') == 'MEASUREMENT_CANCELLED':
                    # Finaliza UI imediatamente após cancelamento
                    self.test_running = False
                    self.cancel_requested = False
                    self.start_button.config(state="normal", text="Testar")
                    self.status_label.config(text=t('fastthreshold.test_cancelled'), fg="#e67e22")
                    if self.app_shell:
                        self.app_shell.set_test_running(False, "QuickThreshold")
                    # Limpa campos de threshold
                    try:
                        for entry in self.threshold_entries:
                            entry.config(state='normal'); entry.delete(0, tk.END); entry.config(state='readonly')
                        # Limpa gráficos
                        self._reset_threshold_graph()
                        self._clear_statistics_graph()
                    except Exception:
                        pass

                elif 'error' in result:
                    messagebox.showerror(t('fastthreshold.error'), result['error'])
                    self.start_button.config(state="normal", text=t('fastthreshold.test_button'))
                    self.status_label.config(text=t('fastthreshold.test_error'), fg="#e74c3c")
                    if self.app_shell:
                        self.app_shell.set_test_running(False, "QuickThreshold")

        except queue.Empty:
            pass
        except Exception as e:
            fc_log("fast_threshold", f"Erro ao processar fila: {e}")

        # Agenda próxima verificação
        self.after(100, self.process_queue)

    def update_threshold_graph(self, freq, threshold):
        """Atualiza gráfico de threshold - CORREÇÃO: Separa dados em tempo real dos históricos"""
        try:
            # Verifica se o threshold é um valor válido para plotar
            should_plot = True
            numeric_threshold = None

            if isinstance(threshold, (int, float)):
                numeric_threshold = float(threshold)
            elif isinstance(threshold, str):
                # Verifica se é um valor fora da faixa (não plotar)
                if threshold.startswith('>') or threshold.startswith('<'):
                    should_plot = False
                    fc_log("fast_threshold", f"🚫 Threshold {threshold} está fora da faixa - não será plotado")
                else:
                    # Tenta extrair valor numérico de strings válidas
                    import re
                    match = re.search(r'(\d+\.?\d*)', str(threshold))
                    if match:
                        numeric_threshold = float(match.group(1))

            # CORREÇÃO: Só adiciona ao gráfico se for um valor válido
            if should_plot and numeric_threshold is not None:
                # CORREÇÃO CRÍTICA: Inicializa dados em tempo real se não existir
                if not hasattr(self, 'realtime_threshold_data'):
                    self.realtime_threshold_data = []

                # CORREÇÃO: Adiciona apenas aos dados em tempo real (não mistura com históricos)
                self.realtime_threshold_data.append({'freq': freq, 'threshold': numeric_threshold})

                # CORREÇÃO: Plota apenas dados em tempo real + dados históricos selecionados
                self._plot_realtime_with_history()
            else:
                fc_log("fast_threshold", f"⚠️ Threshold {threshold} não será plotado no gráfico")

        except Exception as e:
            fc_log("fast_threshold", f"Erro ao atualizar gráfico: {e}")

    def _plot_realtime_with_history(self):
        """CORREÇÃO: Plota dados em tempo real + dados históricos com estilo visual consistente"""
        try:
            # Limpa o gráfico
            self.threshold_ax.clear()
            if hasattr(self, 'threshold_annot') and self.threshold_annot is not None:
                self.threshold_annot = None
            self.threshold_ax.set_ylabel(t('fastthreshold.threshold_dbm_label'))
            self.threshold_ax.set_ylim(5, 25)
            self.threshold_ax.grid(True, alpha=0.3)

            # CORREÇÃO: Coleta todos os dados (históricos + tempo real) em uma lista unificada
            all_data = []

            # Adiciona dados históricos selecionados
            if hasattr(self, 'test_history') and self.test_history:
                for entry in self.test_history:
                    if entry.get('show_in_graph', True):
                        results = entry.get('results', [])
                        epc = entry.get('epc', 'N/A')
                        timestamp = entry.get('timestamp', '')
                        test_id = entry.get('test_id', '')

                        # CORREÇÃO: Para dados legados sem test_id, gera um baseado no timestamp
                        if not test_id and timestamp:
                            test_id = f"{epc}_{timestamp.replace(' ', '_').replace(':', '')}"
                            entry['test_id'] = test_id  # Salva para futuras referências

                        for result in results:
                            if isinstance(result, dict):
                                freq = result.get('freq')
                                threshold = result.get('threshold')
                                if freq is not None and threshold is not None:
                                    # Verifica se é um valor válido para plotar
                                    should_plot = True
                                    if isinstance(threshold, str) and (threshold.startswith('>') or threshold.startswith('<')):
                                        should_plot = False

                                    if should_plot:
                                        all_data.append({
                                            'freq': freq,
                                            'threshold': threshold,
                                            'epc': epc,
                                            'test_id': test_id,  # NOVO: Inclui test_id
                                            'timestamp': timestamp,  # NOVO: Inclui timestamp
                                            'is_realtime': False  # Marca como histórico
                                        })

            # Adiciona dados em tempo real
            if hasattr(self, 'realtime_threshold_data') and self.realtime_threshold_data:
                for data in self.realtime_threshold_data:
                    all_data.append({
                        'freq': data['freq'],
                        'threshold': data['threshold'],
                        'epc': 'Teste Atual',
                        'is_realtime': True  # Marca como tempo real
                    })

            # CORREÇÃO: Plota todos os dados com o mesmo estilo visual
            if all_data:
                # NOVO: Agrupa dados por test_id para lidar com EPCs duplicados
                test_data = {}
                for data in all_data:
                    # Usa test_id se disponível, senão usa EPC como fallback
                    test_id = data.get('test_id', data.get('epc', 'N/A'))
                    if test_id not in test_data:
                        test_data[test_id] = []
                    test_data[test_id].append(data)

                # CORREÇÃO: Usa cores consistentes para todos os dados
                colors = ['blue', 'red', 'green', 'orange', 'purple', 'brown', 'pink', 'gray', 'olive', 'cyan']
                color_index = 0

                for test_id, data_list in test_data.items():
                    if data_list:
                        sorted_data = sorted(data_list, key=lambda x: x['freq'])
                        freqs = [d['freq'] for d in sorted_data]
                        thresholds = [d['threshold'] for d in sorted_data]

                        # CORREÇÃO: Mesmo estilo para todos os dados
                        color = colors[color_index % len(colors)]
                        color_index += 1

                        # CORREÇÃO: Label simples com apenas EPC original
                        epc = data_list[0].get('epc', 'N/A')

                        # NOVO: Usa o EPC completo (24 dígitos) em uma única linha
                        label = epc

                        # CORREÇÃO: Estilo visual consistente (mesmo que o original)
                        self.threshold_ax.plot(freqs, thresholds, 'o-',
                                            color=color,
                                            linewidth=1,
                                            markersize=4,
                                            alpha=0.7,
                                            label=label)

            # CORREÇÃO: Layout otimizado para legenda completa
            if all_data:
                # *** ALTERAÇÃO: Mudar right de 0.55 para 0.65 ***
                self.threshold_fig.subplots_adjust(left=0.1, right=0.65, top=0.95, bottom=0.1)

                # CORREÇÃO: Legenda simples que funciona
                legend = self.threshold_ax.legend(bbox_to_anchor=(1.05, 1), loc='upper left',
                                                fontsize=6, frameon=True, fancybox=True, shadow=True)

                # CORREÇÃO: Força atualização para garantir que a legenda seja visível
                self.threshold_fig.canvas.draw()

            self.threshold_canvas.draw()

        except Exception as e:
            fc_log("fast_threshold", f"❌ Erro ao plotar dados em tempo real com histórico: {e}")
            import traceback
            traceback.print_exc()

    def update_threshold_fields(self, results):
        """Atualiza os campos de threshold com os resultados"""
        try:
            # Limpa todos os campos primeiro
            for entry in self.threshold_entries:
                entry.config(state='normal')
                entry.delete(0, tk.END)
                entry.config(state='readonly')

            # Preenche com os resultados
            for i, result in enumerate(results):
                if i < len(self.threshold_entries):
                    threshold_value = result.get('threshold', 'N/A')
                    if threshold_value != 'N/A':
                        self.threshold_entries[i].config(state='normal')
                        self.threshold_entries[i].delete(0, tk.END)
                        # Lida com valores numéricos e strings (como ">25.0" ou "<5.0")
                        if isinstance(threshold_value, (int, float)):
                            self.threshold_entries[i].insert(0, f"{threshold_value:.1f}")
                        else:
                            self.threshold_entries[i].insert(0, str(threshold_value))
                        self.threshold_entries[i].config(state='readonly')

        except Exception as e:
            fc_log("fast_threshold", f"Erro ao atualizar campos de threshold: {e}")

    def _process_measurement_results(self, results, detected_epc=None):
        """Processa resultados da medição - CORREÇÃO: Limpa dados em tempo real e integra ao histórico"""
        try:
            # Atualiza os campos de threshold na interface
            self.update_threshold_fields(results)

            # Usa EPC real detectado; se não houver (tag morta), registra como "SEM MEDIDA"
            if detected_epc:
                epc = detected_epc
            else:
                epc = "SEM MEDIDA"

            # Cria entrada no histórico
            # NOVO: Cria identificador único para cada teste (mesmo com EPCs duplicados)
            test_id = f"{epc}_{datetime.now().strftime('%Y%m%d_%H%M%S')}"

            # CORREÇÃO: Captura o nome do teste da sessão (identificador geral)
            session_test_name = self.test_name_entry.get().strip() if hasattr(self, 'test_name_entry') else ""

            # Verifica duplicidade de EPC no histórico existente
            is_duplicate = any((isinstance(e, dict) and e.get('epc') == epc) for e in self.test_history)
            if is_duplicate:
                try:
                    messagebox.showwarning(t('fastthreshold.duplicate_epc_title'),
                                          t('fastthreshold.duplicate_epc_msg').format(epc=epc),
                                          parent=self)
                except Exception:
                    pass

            history_entry = {
                'epc': epc,
                'test_id': test_id,  # NOVO: Identificador único para o teste
                'session_test_name': session_test_name,  # CORREÇÃO: Nome da sessão de trabalho
                'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                'results': results,
                'show_in_graph': True,  # Por padrão, todas as tags são plotadas
                'duplicate': bool(is_duplicate)
            }

            # Adiciona ao histórico
            self.test_history.append(history_entry)

            # CORREÇÃO: Limpa dados em tempo real após integrar ao histórico
            if hasattr(self, 'realtime_threshold_data'):
                self.realtime_threshold_data = []
                fc_log("fast_threshold", "🧹 Dados em tempo real limpos após integração ao histórico")

            # Atualiza contadores baseado no histórico real
            self._update_counters_from_history()

            # Atualiza interface
            self.tags_testadas_var.set(str(self.tags_testadas))

            # Atualiza árvore de histórico
            self._update_history_tree()

            # CORREÇÃO: Atualiza gráfico com dados históricos (sem dados em tempo real)
            self._update_graph_from_history()

            # Salva dados
            self._save_persistent_data()

            self.start_button.config(state="normal", text="Testar")
            self.status_label.config(text=t('fastthreshold.test_completed'), fg="#27ae60")
            if self.app_shell:
                self.app_shell.set_test_running(False, "QuickThreshold")

        except Exception as e:
            fc_log("fast_threshold", f"Erro ao processar resultados: {e}")

    def _update_history_tree(self):
        """Atualiza árvore de histórico"""
        try:
            # Limpa árvore
            for item in self.history_tree.get_children():
                self.history_tree.delete(item)

            fc_log("fast_threshold", f"🔄 Atualizando árvore de histórico com {len(self.test_history)} entradas")

            # Configura a tag de destaque para duplicados (uma vez por atualização)
            try:
                self.history_tree.tag_configure('duplicate', foreground='red', background='#ffe6e6')
            except Exception:
                pass

            # Adiciona entradas
            for entry in self.test_history:
                fc_log("fast_threshold", f"📊 Processando entrada: EPC={entry.get('epc', 'N/A')}, Results={entry.get('results', [])}")

                # Verifica se deve plotar (padrão: sim para novas entradas)
                should_plot = entry.get('show_in_graph', True)
                checkbox_text = "☑" if should_plot else "☐"
                values = [checkbox_text]

                # CORREÇÃO: Mostra apenas EPC original (sem timestamp)
                epc = entry.get('epc', 'N/A')
                timestamp = entry.get('timestamp', '')
                test_id = entry.get('test_id', '')

                # CORREÇÃO: Para dados legados sem test_id, gera um baseado no timestamp
                if not test_id and timestamp:
                    test_id = f"{epc}_{timestamp.replace(' ', '_').replace(':', '')}"
                    entry['test_id'] = test_id  # Salva para futuras referências

                # CORREÇÃO: Exibe apenas o EPC original (sem timestamp)
                values.append(epc)

                # Adiciona resultados por frequência
                results = entry.get('results', [])
                for i in range(5):
                    if i < len(results):
                        result = results[i]
                        if isinstance(result, dict):
                            threshold = result.get('threshold', 'N/A')
                        else:
                            threshold = result

                        # Formata o threshold corretamente
                        if threshold != 'N/A':
                            if isinstance(threshold, (int, float)):
                                values.append(f"{threshold:.1f}")
                            else:
                                values.append(str(threshold))
                        else:
                            values.append("N/A")
                    else:
                        values.append("--")

                # Formata timestamp conforme idioma
                timestamp_raw = entry.get('timestamp', 'N/A')
                if timestamp_raw != 'N/A' and isinstance(timestamp_raw, str) and timestamp_raw:
                    try:
                        from datetime import datetime
                        if 'T' in timestamp_raw:
                            timestamp_dt = datetime.fromisoformat(timestamp_raw.replace('Z', '+00:00'))
                        else:
                            timestamp_dt = datetime.strptime(timestamp_raw, '%Y-%m-%d %H:%M:%S')
                        from .i18n import get_translator
                        if get_translator().get_language() == 'en':
                            timestamp_formatted = timestamp_dt.strftime('%m/%d/%y %H:%M:%S')
                        else:
                            timestamp_formatted = timestamp_dt.strftime('%d/%m/%Y %H:%M:%S')
                        values.append(timestamp_formatted)
                    except:
                        values.append(timestamp_raw)
                else:
                    values.append(timestamp_raw)
                fc_log("fast_threshold", f"📋 Valores para inserir: {values}")

                # Insere na árvore (marca duplicados em vermelho)
                tags = ('duplicate',) if entry.get('duplicate', False) else ()
                self.history_tree.insert('', 'end', values=values, tags=tags)

            # CORREÇÃO: Scroll automático para a última linha (mais recente)
            if self.history_tree.get_children():
                last_item = self.history_tree.get_children()[-1]
                self.history_tree.see(last_item)
                self.history_tree.selection_set(last_item)
                fc_log("fast_threshold", "📜 Scroll automático para última linha ativado")

        except Exception as e:
            fc_log("fast_threshold", f"❌ Erro ao atualizar árvore de histórico: {e}")
            import traceback
            traceback.print_exc()

    def _toggle_plot_checkbox(self, event):
        """Alterna o estado do checkbox de plotagem"""
        try:
            # Obtém o item clicado
            item = self.history_tree.identify_row(event.y)
            if not item:
                return

            # Obtém a coluna clicada
            column = self.history_tree.identify_column(event.x)

            # Só processa se clicou na coluna "Plot" (coluna 0)
            if column != '#1':  # #1 é a primeira coluna (Plot)
                return

            # Obtém o índice do item na lista
            item_index = self.history_tree.index(item)

            # Atualiza o estado no histórico
            if item_index < len(self.test_history):
                current_state = self.test_history[item_index].get('show_in_graph', True)
                new_state = not current_state
                self.test_history[item_index]['show_in_graph'] = new_state

                fc_log("fast_threshold", f"🔄 Alternando checkbox do item {item_index}: {current_state} -> {new_state}")

                # Atualiza o texto do checkbox
                checkbox_text = "☑" if new_state else "☐"

                # CORREÇÃO: Usa apenas EPC original (sem timestamp)
                entry = self.test_history[item_index]
                epc = entry.get('epc', 'N/A')
                timestamp = entry.get('timestamp', '')
                test_id = entry.get('test_id', '')

                # CORREÇÃO: Para dados legados sem test_id, gera um baseado no timestamp
                if not test_id and timestamp:
                    test_id = f"{epc}_{timestamp.replace(' ', '_').replace(':', '')}"
                    entry['test_id'] = test_id  # Salva para futuras referências

                # CORREÇÃO: Exibe apenas o EPC original (sem timestamp)
                epc_display = epc

                self.history_tree.item(item, values=(
                    checkbox_text,
                    epc_display,
                    *[entry.get('results', [{}])[i].get('threshold', '--') if i < len(entry.get('results', [])) else '--' for i in range(5)],
                    entry.get('timestamp', 'N/A')
                ))

                # Atualiza o gráfico
                self._update_graph_from_history()
                
                # Atualiza o display
                self._update_tags_display()
                
                # Limpa o gráfico estatístico
                self._clear_statistics_graph()

        except Exception as e:
            fc_log("fast_threshold", f"❌ Erro ao alternar checkbox: {e}")
            import traceback
            traceback.print_exc()

    def _update_graph_from_history(self):
        """Atualiza o gráfico baseado nas tags selecionadas - CORREÇÃO: Usa nova lógica de separação"""
        try:
            fc_log("fast_threshold", f"🔄 Atualizando gráfico com {len(self.test_history)} entradas no histórico")

            # CORREÇÃO: Usa a nova função de plotagem que separa dados em tempo real dos históricos
            self._plot_realtime_with_history()

        except Exception as e:
            fc_log("fast_threshold", f"❌ Erro ao atualizar gráfico: {e}")
            import traceback
            traceback.print_exc()

    def _refresh_graph(self):
        """Atualiza o gráfico com os dados atuais"""
        try:
            # Limpa e replota
            self.threshold_ax.clear()
            if hasattr(self, 'threshold_annot') and self.threshold_annot is not None:
                self.threshold_annot = None
            self.threshold_ax.set_ylabel(t('fastthreshold.threshold_dbm_label'))
            self.threshold_ax.set_ylim(5, 25)
            self.threshold_ax.grid(True, alpha=0.3)

            if self.threshold_graph_data:
                # Agrupa dados por EPC para plotar com cores diferentes
                epc_data = {}
                for data in self.threshold_graph_data:
                    epc = data.get('epc', 'N/A')
                    if epc not in epc_data:
                        epc_data[epc] = []
                    epc_data[epc].append(data)

                fc_log("fast_threshold", f"🔍 Dados agrupados por EPC: {list(epc_data.keys())}")
                for epc, data_list in epc_data.items():
                    fc_log("fast_threshold", f"   EPC {epc}: {len(data_list)} pontos")

                # Cores diferentes para cada tag
                colors = ['blue', 'red', 'green', 'orange', 'purple', 'brown', 'pink', 'gray', 'olive', 'cyan']
                color_index = 0

                # Plota cada tag com cor diferente
                for epc, data_list in epc_data.items():
                    if data_list:
                        # Ordena dados por frequência
                        sorted_data = sorted(data_list, key=lambda x: x['freq'])
                        freqs = [d['freq'] for d in sorted_data]
                        thresholds = [d['threshold'] for d in sorted_data]

                        fc_log("fast_threshold", f"🎨 Plotando EPC {epc} com {len(freqs)} pontos: {list(zip(freqs, thresholds))}")

                        # Escolhe cor para esta tag
                        color = colors[color_index % len(colors)]
                        color_index += 1

                        # Plota com cor específica - EPC completo em uma linha
                        self.threshold_ax.plot(freqs, thresholds, 'o-',
                                            color=color,
                                            linewidth=1,
                                            markersize=4,
                                            alpha=0.7,
                                            label=f'EPC: {epc}')

                        fc_log("fast_threshold", f"   🎨 Cor atribuída: {color}")

                # Adiciona legenda
                self.threshold_ax.legend(bbox_to_anchor=(1.0, 1), loc='upper left', fontsize=8)

                fc_log("fast_threshold", f"✅ Gráfico atualizado com {len(epc_data)} tags diferentes")
            else:
                fc_log("fast_threshold", "⚠️ Nenhum dado para plotar")

            self.threshold_canvas.draw()

        except Exception as e:
            fc_log("fast_threshold", f"❌ Erro ao atualizar gráfico: {e}")
            import traceback
            traceback.print_exc()

    def on_tree_click(self, event):
        """Callback para cliques simples no treeview de histórico"""
        region = self.history_tree.identify("region", event.x, event.y)
        if region == "cell":
            column = self.history_tree.identify_column(event.x)
            item = self.history_tree.identify_row(event.y)
            if column == '#1' and item:  # Coluna do checkbox (Plot)
                # Alterna estado de plotagem
                values = list(self.history_tree.item(item, 'values'))
                if values:
                    # Encontra o teste correspondente pelo índice
                    children = self.history_tree.get_children()
                    try:
                        index = children.index(item)
                        if index < len(self.test_history):
                            entry = self.test_history[index]
                            # Alterna estado
                            entry['show_in_graph'] = not entry.get('show_in_graph', True)
                            # Atualiza árvore e gráfico
                            self._update_history_tree()
                            self._update_graph_from_history()
                    except (ValueError, IndexError):
                        pass
    
    def on_tree_double_click(self, event):
        """Callback para duplo-clique no treeview de histórico"""
        # Por enquanto, não faz nada com duplo-clique
        pass

    def sort_treeview(self, column):
        """Ordena o histórico pela coluna especificada (mesmo padrão RSSI / Noise)."""
        try:
            items = []
            for item in self.history_tree.get_children(""):
                try:
                    items.append((self.history_tree.set(item, column), item))
                except Exception:
                    items.append(("", item))

            if self.current_sort_column == column:
                self.current_sort_reverse = not self.current_sort_reverse
            else:
                self.current_sort_reverse = False
                self.current_sort_column = column

            def sort_key(row):
                val = row[0]
                if column == "Plot":
                    return 0 if val == "☐" else 1
                if column == "EPC":
                    return (val or "").lower()
                if column.startswith("Freq"):
                    s = (val or "").replace("dBm", "").strip()
                    try:
                        return float(s)
                    except (ValueError, TypeError):
                        return float("nan")
                if column == "Data/Hora":
                    return val or ""
                return (val or "").lower()

            items.sort(key=sort_key, reverse=self.current_sort_reverse)
            for index, (_, item) in enumerate(items):
                self.history_tree.move(item, "", index)
        except Exception as e:
            fc_log("fast_threshold", f"Erro ao ordenar árvore: {e}")

    def clear_all_data(self):
        """Limpa todos os dados - SOLUÇÃO DEFINITIVA"""
        try:
            fc_log("fast_threshold", "🧹 INICIANDO LIMPEZA COMPLETA DOS DADOS...")
            # Se estiver rodando, solicita cancelamento imediato
            if getattr(self, 'test_running', False):
                self.cancel_requested = True
                self.test_running = False
                # Atualiza UI e estado global
                try:
                    if self.app_shell:
                        self.app_shell.set_test_running(False, "QuickThreshold")
                    self.start_button.config(state='normal', text='Testar')
                    self.status_label.config(text=t('fastthreshold.test_cancelled'), fg="#e67e22")
                except Exception:
                    pass

            # SOLUÇÃO: Marca que os dados foram explicitamente limpos
            self.data_cleared_by_user = True
            fc_log("fast_threshold", "🧹 Flag de limpeza ativada")
            
            # CORREÇÃO: Cancela timers de restauração para evitar que restaurem dados limpos
            if hasattr(self, 'restore_timer_1'):
                self.after_cancel(self.restore_timer_1)
                fc_log("fast_threshold", "🧹 Timer de restauração 1 cancelado")
            if hasattr(self, 'restore_timer_2'):
                self.after_cancel(self.restore_timer_2)
                fc_log("fast_threshold", "🧹 Timer de restauração 2 cancelado")
            
            # CORREÇÃO: Desabilita temporariamente o evento de destruição para evitar fechamento
            self.unbind("<Destroy>")
            fc_log("fast_threshold", "🧹 Evento de destruição temporariamente desabilitado")
            
            # SOLUÇÃO: Limpa dados em tempo real
            if hasattr(self, 'realtime_threshold_data'):
                self.realtime_threshold_data = []
                fc_log("fast_threshold", "🧹 Dados em tempo real limpos")

            # SOLUÇÃO: Limpa dados principais
            self.threshold_graph_data = []
            self.test_history = []
            fc_log("fast_threshold", "🧹 Histórico e dados de gráfico limpos")
            
            # SOLUÇÃO: Atualiza contadores
            self._update_counters_from_history()
            self.tags_testadas_var.set(str(self.tags_testadas))
            fc_log("fast_threshold", "🧹 Contadores atualizados")

            # SOLUÇÃO: Limpa gráfico principal
            self.threshold_ax.clear()
            if hasattr(self, 'threshold_annot') and self.threshold_annot is not None:
                self.threshold_annot = None
            self.threshold_ax.set_ylabel(t('fastthreshold.threshold_dbm_label'))
            self.threshold_ax.set_ylim(5, 25)
            self.threshold_ax.grid(True, alpha=0.3)
            self.threshold_canvas.draw()
            fc_log("fast_threshold", "🧹 Gráfico principal limpo")

            # SOLUÇÃO: Limpa gráfico estatístico
            if hasattr(self, 'stats_ax'):
                self.stats_ax.clear()
                self.stats_ax.set_ylabel(t('fastthreshold.freq_mhz_label'))
                self.stats_ax.set_xlabel(t('fastthreshold.threshold_dbm_label'))
                self.stats_ax.grid(True, alpha=0.3)
                if hasattr(self, 'stats_canvas'):
                    self.stats_canvas.draw()
                fc_log("fast_threshold", "🧹 Gráfico de análise estatística limpo")

            # SOLUÇÃO: Limpa árvore de histórico
            for item in self.history_tree.get_children():
                self.history_tree.delete(item)
            fc_log("fast_threshold", "🧹 Árvore de histórico limpa")

            # SOLUÇÃO: Limpa campos de entrada
            if hasattr(self, 'test_name_entry'):
                self.test_name_entry.delete(0, tk.END)
                fc_log("fast_threshold", "🧹 Campo nome do teste limpo")
            
            # CORREÇÃO: Limpa também _pending_test_name para evitar restauração
            self._pending_test_name = ""
            fc_log("fast_threshold", "🧹 _pending_test_name limpo")

            if hasattr(self, 'freq_entries'):
                for freq_entry in self.freq_entries:
                    freq_entry.delete(0, tk.END)
                fc_log("fast_threshold", "🧹 Campos de frequência limpos")

            if hasattr(self, 'threshold_entries'):
                for threshold_entry in self.threshold_entries:
                    # CORREÇÃO: Define o estado como 'normal' para permitir a limpeza
                    threshold_entry.config(state='normal')
                    threshold_entry.delete(0, tk.END)
                    # CORREÇÃO: Retorna o estado para 'readonly'
                    threshold_entry.config(state='readonly')
                fc_log("fast_threshold", "🧹 Campos de threshold limpos")

            # SOLUÇÃO: Limpa dados persistentes
            self.persistent_frequencies = [None, None, None, None, None]
            fc_log("fast_threshold", "🧹 Frequências persistentes limpas")

            # SOLUÇÃO: Limpa status e dados anteriores
            if hasattr(self, 'status_label'):
                self.status_label.config(text=t('fastthreshold.ready'), fg="#27ae60")
                fc_log("fast_threshold", "🧹 Status label limpo")

            self.last_tag_test_data = None
            self.last_threshold_test_data = None
            self.selected_epc = None
            fc_log("fast_threshold", "🧹 Dados de teste anteriores limpos")

            # SOLUÇÃO: Salva dados limpos
            try:
                self._save_persistent_data()
                fc_log("fast_threshold", "🧹 Dados salvos após limpeza")
            except Exception as save_error:
                fc_log("fast_threshold", f"⚠️ Erro ao salvar dados após limpeza: {save_error}")

            fc_log("fast_threshold", "✅ LIMPEZA COMPLETA CONCLUÍDA!")
            
            # SOLUÇÃO: Força atualização visual
            self.update()
            fc_log("fast_threshold", "🔄 Interface atualizada após limpeza")
            
            # SOLUÇÃO: Reseta flag imediatamente (sem delay)
            self.data_cleared_by_user = False
            fc_log("fast_threshold", "🔄 Flag de limpeza resetada imediatamente")
            
            # SOLUÇÃO: Força foco e redesenho
            try:
                self.focus_set()
                fc_log("fast_threshold", "🔄 Foco retornado para o módulo FastThreshold")
            except Exception as focus_error:
                fc_log("fast_threshold", f"⚠️ Erro ao definir foco: {focus_error}")
            
            # SOLUÇÃO: Força redesenho dos gráficos
            try:
                if hasattr(self, 'threshold_canvas'):
                    self.threshold_canvas.draw()
                    fc_log("fast_threshold", "🔄 Gráfico principal redesenhado")
                if hasattr(self, 'stats_canvas'):
                    self.stats_canvas.draw()
                    fc_log("fast_threshold", "🔄 Gráfico estatístico redesenhado")
            except Exception as draw_error:
                fc_log("fast_threshold", f"⚠️ Erro ao redesenhar gráficos: {draw_error}")
            
            # CORREÇÃO: Reabilita o evento de destruição após a limpeza
            self.bind("<Destroy>", self._on_frame_destroy)
            fc_log("fast_threshold", "🔄 Evento de destruição reabilitado")

        except Exception as e:
            fc_log("fast_threshold", f"❌ Erro ao limpar dados: {e}")
            import traceback
            traceback.print_exc()
            
            # CORREÇÃO: Reabilita o evento de destruição mesmo em caso de erro
            try:
                self.bind("<Destroy>", self._on_frame_destroy)
                fc_log("fast_threshold", "🔄 Evento de destruição reabilitado após erro")
            except:
                pass

    def save_report_to_file(self):
        """Salva relatório em arquivo - CORREÇÃO: Sugere nome seguindo padrão dos outros módulos"""
        try:
            # Nome sugerido padronizado: Nome do Módulo dd.mm.aa_hh.mm.ss.json
            timestamp = datetime.now().strftime('%d.%m.%y_%H.%M.%S')
            default_filename = f"FastThreshold {timestamp}.json"

            filename = filedialog.asksaveasfilename(
                title=t('fastthreshold.save_report_title'),
                defaultextension=".json",
                filetypes=[(t('fastthreshold.json_files'), "*.json"), (t('fastthreshold.all_files'), "*.*")],
                initialfile=default_filename  # NOVO: Sugere nome com padrão
            )

            if filename:
                # CORREÇÃO: Captura o nome do teste (lembrete) do campo de entrada
                test_name = self.test_name_entry.get().strip() if hasattr(self, 'test_name_entry') else ""
                fc_log("fast_threshold", f"🔍 Salvando nome do teste no relatório: '{test_name}'")
                fc_log("fast_threshold", f"📊 Salvando frequências: {self.persistent_frequencies}")
                
                report_data = {
                    'module': 'QuickThreshold',
                    'timestamp': datetime.now().isoformat(),
                    'test_name': test_name,  # CORREÇÃO: Inclui o nome do teste
                    'persistent_frequencies': self.persistent_frequencies,  # CORREÇÃO: Inclui as frequências
                    'summary': {
                        'tags_testadas': self.tags_testadas,
                        'tags_aprovadas': self.tags_aprovadas,
                        'tags_reprovadas': self.tags_reprovadas,
                        'yield': (self.tags_aprovadas / self.tags_testadas * 100) if self.tags_testadas > 0 else 0
                    },
                    'history': self.test_history
                }

                with open(filename, 'w', encoding='utf-8') as f:
                    json.dump(report_data, f, indent=2, ensure_ascii=False)

                messagebox.showinfo(t('fastthreshold.success'), t('fastthreshold.report_saved').format(filename=filename))

        except Exception as e:
            messagebox.showerror(t('fastthreshold.error_generic'), t('fastthreshold.error_saving_report').format(error=str(e)))

    def import_report_from_file(self):
        """Importa relatório de arquivo"""
        try:
            filename = filedialog.askopenfilename(
                title=t('fastthreshold.import_report_title'),
                filetypes=[(t('fastthreshold.json_files'), "*.json"), (t('fastthreshold.all_files'), "*.*")]
            )

            if filename:
                with open(filename, 'r', encoding='utf-8') as f:
                    report_data = json.load(f)

                if 'history' in report_data:
                    self.test_history = report_data['history']
                    
                    # --- INÍCIO DA CORREÇÃO ---
                    # Atualiza os contadores com base no histórico importado
                    self._update_counters_from_history()
                    # Atualiza a variável do label (que dispara a atualização do texto)
                    self.tags_testadas_var.set(str(self.tags_testadas))
                    # --- FIM DA CORREÇÃO ---
                    
                    # CORREÇÃO: Restaura o nome do teste se existir no arquivo
                    if 'test_name' in report_data and hasattr(self, 'test_name_entry'):
                        test_name = report_data['test_name']
                        fc_log("fast_threshold", f"🔍 Nome do teste encontrado no arquivo importado: '{test_name}'")
                        self.test_name_entry.delete(0, tk.END)
                        self.test_name_entry.insert(0, test_name)
                        fc_log("fast_threshold", f"📝 Nome do teste restaurado no campo: {test_name}")
                        # CORREÇÃO: Salva o nome importado no banco de dados
                        self._pending_test_name = test_name
                        self._save_persistent_data()
                        fc_log("fast_threshold", f"💾 Nome do teste importado salvo no banco de dados")
                    else:
                        fc_log("fast_threshold", f"⚠️ Nome do teste não encontrado no arquivo importado")
                    
                    # CORREÇÃO: Extrai frequências do primeiro teste do histórico se não existirem em persistent_frequencies
                    if 'persistent_frequencies' in report_data:
                        frequencies = report_data['persistent_frequencies']
                        # Se todas as frequências são None, tenta extrair do primeiro teste
                        if all(f is None for f in frequencies) and self.test_history:
                            first_test = self.test_history[0]
                            results = first_test.get('results', [])
                            if results:
                                fc_log("fast_threshold", f"🔍 Extraindo frequências do primeiro teste: {results}")
                                for i, result in enumerate(results):
                                    if i < len(frequencies):
                                        freq = result.get('freq')
                                        frequencies[i] = freq
                                fc_log("fast_threshold", f"📊 Frequências extraídas: {frequencies}")
                        
                        fc_log("fast_threshold", f"🔍 Restaurando frequências: {frequencies}")
                        fc_log("fast_threshold", f"🔍 Número de campos freq_entries: {len(self.freq_entries)}")
                        for i, freq in enumerate(frequencies):
                            if i < len(self.freq_entries) and freq is not None:
                                fc_log("fast_threshold", f"📊 Restaurando frequência {i+1}: {freq}")
                                self.freq_entries[i].delete(0, tk.END)
                                self.freq_entries[i].insert(0, str(freq))
                        fc_log("fast_threshold", f"📊 Frequências restauradas: {frequencies}")
                        
                        # Atualiza persistent_frequencies
                        self.persistent_frequencies = frequencies
                    else:
                        fc_log("fast_threshold", f"⚠️ Frequências não encontradas no arquivo")
                        fc_log("fast_threshold", f"🔍 persistent_frequencies no arquivo: {'persistent_frequencies' in report_data}")
                        fc_log("fast_threshold", f"🔍 freq_entries existe: {hasattr(self, 'freq_entries')}")
                    
                    self._update_history_tree()
                    # CORREÇÃO: Atualiza o gráfico após importar dados
                    self._update_graph_from_history()
                    messagebox.showinfo(t('fastthreshold.success'), t('fastthreshold.report_imported'))
                else:
                    messagebox.showerror(t('fastthreshold.error_generic'), t('fastthreshold.invalid_file'))

        except Exception as e:
            messagebox.showerror(t('fastthreshold.error_generic'), t('fastthreshold.error_importing_report').format(error=str(e)))
            import traceback
            traceback.print_exc()

    def generate_pdf_report(self):
        """Gera relatório PDF com diálogo para salvar arquivo - apenas testes selecionados"""
        try:
            # Verifica se há dados para relatório
            if not self.test_history:
                messagebox.showwarning(t('fastthreshold.warning'), t('fastthreshold.no_tests_for_report'))
                return
            
            # Obtém apenas os testes selecionados
            selected_tests = [entry for entry in self.test_history if entry.get('show_in_graph', True)]
            
            if not selected_tests:
                messagebox.showwarning(t('fastthreshold.no_tests_selected_title'), 
                                     t('fastthreshold.no_tests_selected_msg'))
                return
            
            # Gera nome do arquivo com data e hora no formato padrão
            now = datetime.now()
            filename = f"Relatório_FastThreshold {now.strftime('%d.%m.%y_%H.%M.%S')}.pdf"
            
            # Diálogo para salvar arquivo
            filepath = filedialog.asksaveasfilename(
                defaultextension=".pdf",
                filetypes=[(t('fastthreshold.pdf_files'), "*.pdf")],
                initialfile=filename,
                title=t('fastthreshold.save_pdf_title')
            )
            
            if not filepath:
                return  # Usuário cancelou
            
            # Mostra mensagem de progresso
            self.status_label.config(text=t('fastthreshold.generating_pdf'), fg="#f39c12")
            self.update()
            
            # Gera o PDF com dados selecionados
            result = self._generate_pdf_with_selected_tests(filepath, selected_tests)
            
            if result['success']:
                self.status_label.config(text=t('fastthreshold.pdf_generated_success'), fg="#27ae60")
                messagebox.showinfo(t('fastthreshold.success'), 
                                  t('fastthreshold.pdf_generated').format(filepath=filepath, count=len(selected_tests)))
                
                # Tenta abrir o PDF automaticamente (fallbacks se startfile falhar)
                open_path_with_default_app(filepath, log_tag="fast_threshold")
            else:
                error_msg = result.get('error', t('fastthreshold.error_generic'))
                self.status_label.config(text=t('fastthreshold.error_generating_pdf_status'), fg="#c0392b")
                messagebox.showerror(t('fastthreshold.error_generic'), t('fastthreshold.error_generating_pdf').format(error=error_msg))
                
        except Exception as e:
            self.status_label.config(text=t('fastthreshold.error_generating_pdf_status'), fg="#c0392b")
            messagebox.showerror(t('fastthreshold.error_generic'), t('fastthreshold.unexpected_error').format(error=str(e)))

    def _generate_pdf_with_selected_tests(self, filepath, selected_tests):
        """Gera PDF com os testes selecionados usando ReportLab"""
        try:
            from reportlab.lib.pagesizes import A4
            from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
            from reportlab.lib.units import cm, inch
            from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle
            from .pdf_pagination_utils import (
                cond_page_break_before_chart_section,
                cond_page_break_before_footer_block,
                cond_page_break_before_subsection_with_figure,
            )
            from reportlab.lib import colors
            from reportlab.lib.enums import TA_CENTER, TA_LEFT
            from datetime import datetime
            import os
            
            # Função para obter informações do sistema da licença ativa
            def _get_system_info():
                """Obtém informações do sistema da licença ativa"""
                try:
                    # Tenta obter informações via app_shell (método preferido)
                    if hasattr(self, 'app_shell') and self.app_shell and hasattr(self.app_shell, 'license_manager'):
                        system_info = self.app_shell.license_manager.get_active_license_system_info(self.com_port)
                        return system_info
                    
                    # Fallback: cria LicenseManager temporário
                    try:
                        from .license_module import LicenseManager
                        import os
                        LICENSE_DB_FILE = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), "licenses.json")
                        license_manager = LicenseManager(LICENSE_DB_FILE)
                        system_info = license_manager.get_active_license_system_info(self.com_port)
                        return system_info
                    except Exception as fallback_error:
                        fc_log("fast_threshold", f"⚠️ Erro no fallback de informações do sistema: {fallback_error}")
                    
                    # Fallback final: informações básicas
                    from .i18n import get_translator
                    translator = get_translator()
                    date_format = '%d/%m/%Y %H:%M:%S' if translator.get_language() == 'pt' else '%m/%d/%Y %I:%M:%S %p'
                    return {
                        'software': '4.0.0',
                        'hardware': 'N/A',
                        'firmware': 'N/A',
                        'serial_number': 'N/A',
                        'license': 'N/A',
                        'generated_at': datetime.now().strftime(date_format)
                    }
                    
                except Exception as e:
                    fc_log("fast_threshold", f"⚠️ Erro geral ao obter informações do sistema: {e}")
                    from .i18n import get_translator
                    translator = get_translator()
                    date_format = '%d/%m/%Y %H:%M:%S' if translator.get_language() == 'pt' else '%m/%d/%Y %I:%M:%S %p'
                    return {
                        'software': '4.0.0',
                        'hardware': 'N/A',
                        'firmware': 'N/A',
                        'serial_number': 'N/A',
                        'license': 'N/A',
                        'generated_at': datetime.now().strftime(date_format)
                    }
            
            # Cria o documento PDF
            doc = SimpleDocTemplate(
                filepath,
                pagesize=A4,
                rightMargin=72,
                leftMargin=72,
                topMargin=72,
                bottomMargin=18
            )
            
            # Estilos
            styles = getSampleStyleSheet()
            title_style = ParagraphStyle(
                'CustomTitle',
                parent=styles['Heading1'],
                fontSize=24,
                spaceAfter=30,
                alignment=TA_CENTER,
                textColor=colors.HexColor('#2c3e50')
            )
            
            heading_style = ParagraphStyle(
                'CustomHeading',
                parent=styles['Heading2'],
                fontSize=16,
                spaceAfter=12,
                textColor=colors.HexColor('#2c3e50')
            )
            
            # Conteúdo do documento
            story = []
            # Logo FastTag
            try:
                from reportlab.platypus import Image
                root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))
                logo_path = os.path.join(root, 'assets', 'images', 'fasttag_logo.png')
                if os.path.exists(logo_path):
                    logo_size = 1.5*inch
                    logo_img = Image(logo_path, width=logo_size, height=logo_size)
                    story.append(logo_img)
                    story.append(Spacer(1, 10))
            except Exception:
                pass
            
            # Título
            story.append(Paragraph(t('pdf.quick_threshold_report_title'), title_style))
            story.append(Spacer(1, 20))
            
            # Informações do sistema
            sysinfo = _get_system_info()
            story.append(Paragraph(t('pdf.system_info'), heading_style))
            
            info_text = f"""
            <b>{t('pdf.software')}:</b> {sysinfo['software']}<br/>
            <b>{t('pdf.hardware')}:</b> {sysinfo['hardware']}<br/>
            <b>{t('pdf.firmware')}:</b> {sysinfo['firmware']}<br/>
            <b>{t('pdf.serial_number')}:</b> {sysinfo['serial_number']}<br/>
            <b>{t('pdf.license')}:</b> {sysinfo['license']}<br/>
            <b>{t('pdf.generated_at')}:</b> {sysinfo['generated_at']}
            """
            story.append(Paragraph(info_text, styles['Normal']))
            story.append(Spacer(1, 30))
            
            # Resumo dos testes
            story.append(Paragraph(t('pdf.quick_threshold_test_summary'), heading_style))
            
            # Cabeçalhos da tabela
            table_data = [
                [t('pdf.quick_threshold_epc'), 
                 t('pdf.quick_threshold_freq_col').format(n=1), 
                 t('pdf.quick_threshold_freq_col').format(n=2), 
                 t('pdf.quick_threshold_freq_col').format(n=3), 
                 t('pdf.quick_threshold_freq_col').format(n=4), 
                 t('pdf.quick_threshold_freq_col').format(n=5), 
                 t('pdf.date_time')]
            ]
            
            # Adiciona dados dos testes
            duplicate_row_indexes = []  # guarda índices de linhas (no PDF) que são duplicadas
            for entry in selected_tests:
                epc = entry.get('epc', 'N/A')
                results = entry.get('results', [])
                timestamp_raw = entry.get('timestamp', 'N/A')
                
                # Formata os thresholds
                freq_values = []
                for i in range(5):
                    if i < len(results):
                        result = results[i]
                        if isinstance(result, dict):
                            threshold = result.get('threshold', '--')
                        else:
                            threshold = result
                        # Formata o valor
                        if isinstance(threshold, (int, float)):
                            freq_values.append(f"{threshold:.1f}")
                        else:
                            freq_values.append(str(threshold))
                    else:
                        freq_values.append('--')
                
                # Formata timestamp conforme idioma para PDF
                if timestamp_raw != 'N/A' and isinstance(timestamp_raw, str) and timestamp_raw:
                    try:
                        from datetime import datetime
                        timestamp_dt = None
                        # Tenta diferentes formatos de data
                        if 'T' in timestamp_raw:
                            # Formato ISO
                            timestamp_dt = datetime.fromisoformat(timestamp_raw.replace('Z', '+00:00'))
                        else:
                            # Lista de formatos para tentar (igual ao Antenna Check)
                            formats_to_try = [
                                '%d/%m/%Y %H:%M:%S',      # Formato com barras e segundos
                                '%d/%m/%Y %H:%M',         # Formato com barras sem segundos
                                '%d-%m-%Y %H:%M:%S',      # Formato com hífens e segundos
                                '%d-%m-%Y %H:%M',         # Formato com hífens sem segundos
                                '%Y-%m-%d %H:%M:%S',      # Formato ISO sem T
                                '%Y-%m-%d %H:%M'          # Formato ISO sem T e sem segundos
                            ]
                            for fmt in formats_to_try:
                                try:
                                    timestamp_dt = datetime.strptime(timestamp_raw, fmt)
                                    break
                                except ValueError:
                                    continue
                        
                        if timestamp_dt:
                            from .i18n import get_translator
                            translator = get_translator()
                            if translator.get_language() == 'en':
                                # Se a data original tinha segundos, inclui segundos na saída
                                if ':%S' in timestamp_raw or ':' in timestamp_raw and timestamp_raw.count(':') == 2:
                                    timestamp_formatted = timestamp_dt.strftime('%m/%d/%y %I:%M:%S %p')
                                else:
                                    timestamp_formatted = timestamp_dt.strftime('%m/%d/%y %I:%M %p')
                            else:
                                # Português: mantém o formato original se não tinha segundos
                                if ':%S' in timestamp_raw or ':' in timestamp_raw and timestamp_raw.count(':') == 2:
                                    timestamp_formatted = timestamp_dt.strftime('%d/%m/%Y %H:%M:%S')
                                else:
                                    timestamp_formatted = timestamp_dt.strftime('%d/%m/%Y %H:%M')
                        else:
                            timestamp_formatted = timestamp_raw
                    except:
                        timestamp_formatted = timestamp_raw
                    table_data.append([epc] + freq_values + [timestamp_formatted])
                else:
                    table_data.append([epc] + freq_values + [timestamp_raw])
                if entry.get('duplicate', False):
                    # +1 por causa do cabeçalho na linha 0
                    duplicate_row_indexes.append(len(table_data) - 1)
            
            # Cria tabela de testes com colunas ajustadas
            # Larguras otimizadas: EPC (2.2"), Freq1-5 (0.7" cada), Date/Time (1.8" para "MM/DD/YY HH:MM:SS PM")
            # Total: 2.2 + 3.5 + 1.8 = 7.5" (cabe em ~7.7" útil)
            tests_table = Table(
                table_data,
                colWidths=[2.2*inch, 0.7*inch, 0.7*inch, 0.7*inch, 0.7*inch, 0.7*inch, 1.8*inch],
                repeatRows=1,
            )
            base_styles = [
                ('BACKGROUND', (0, 0), (-1, 0), colors.HexColor('#34495e')),
                ('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
                ('ALIGN', (0, 0), (-1, -1), 'CENTER'),
                ('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
                ('FONTSIZE', (0, 0), (-1, 0), 8),  # Reduzido para 8 para evitar corte nos cabeçalhos
                ('BOTTOMPADDING', (0, 0), (-1, 0), 10),
                ('TOPPADDING', (0, 0), (-1, 0), 6),  # Padding reduzido
                ('BACKGROUND', (0, 1), (-1, -1), colors.beige),
                ('GRID', (0, 0), (-1, -1), 1, colors.black),
                ('FONTSIZE', (0, 1), (-1, -1), 8),  # Reduzido para 8 para caber melhor
                ('ROWBACKGROUNDS', (0, 1), (-1, -1), [colors.white, colors.HexColor('#f8f9fa')]),
                ('ALIGN', (0, 0), (0, -1), 'LEFT'),  # Alinha EPC à esquerda
            ]
            # Aplica destaque em vermelho para linhas duplicadas (EPC repetido)
            for row_idx in duplicate_row_indexes:
                base_styles.append(('TEXTCOLOR', (0, row_idx), (-1, row_idx), colors.red))
                base_styles.append(('BACKGROUND', (0, row_idx), (-1, row_idx), colors.HexColor('#ffe6e6')))
            tests_table.setStyle(TableStyle(base_styles))
            story.append(tests_table)
            story.append(Spacer(1, 20))
            
            # Estatísticas
            total_testes = len(selected_tests)
            story.append(Paragraph(t('pdf.quick_threshold_statistics'), heading_style))
            
            # Calcula contadores do resumo da execução
            total_tested = len(self.test_history)
            selected_count = len(selected_tests)
            
            # Conta tags sem teste (thresholds indeterminados)
            no_test_count = 0
            for entry in self.test_history:
                results = entry.get('results', [])
                has_indeterminate = False
                
                for result in results:
                    if isinstance(result, dict):
                        threshold = result.get('threshold', '')
                    else:
                        threshold = result
                    
                    # Verifica se é threshold indeterminado
                    if isinstance(threshold, str) and ('<' in threshold or '>' in threshold):
                        has_indeterminate = True
                        break
                
                if has_indeterminate:
                    no_test_count += 1
            
            stats_data = [
                [t('pdf.quick_threshold_total_selected'), str(total_testes)],
                [t('pdf.quick_threshold_total_measurements'), str(sum(len(entry.get('results', [])) for entry in selected_tests))],
                [t('pdf.quick_threshold_tags_tested'), str(total_tested)],
                [t('pdf.quick_threshold_tags_selected'), str(selected_count)],
                [t('pdf.quick_threshold_tags_no_test'), str(no_test_count)],
            ]
            
            stats_table = Table(stats_data, colWidths=[6*cm, 8*cm])
            stats_table.setStyle(TableStyle([
                ('BACKGROUND', (0, 0), (0, -1), colors.HexColor('#ecf0f1')),
                ('TEXTCOLOR', (0, 0), (-1, -1), colors.black),
                ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
                ('FONTNAME', (0, 0), (0, -1), 'Helvetica-Bold'),
                ('FONTSIZE', (0, 0), (-1, -1), 10),
                ('BOTTOMPADDING', (0, 0), (-1, -1), 8),
                ('GRID', (0, 0), (-1, -1), 1, colors.grey),
            ]))
            story.append(stats_table)
            story.append(Spacer(1, 20))
            
            # Configurações do Teste
            story.append(Paragraph(t('pdf.quick_threshold_test_config'), heading_style))
            
            # Frequências configuradas
            freq_config_data = [[t('pdf.quick_threshold_freq_label'), t('pdf.quick_threshold_freq_value')]]
            for i, freq_entry in enumerate(self.freq_entries):
                freq_value = freq_entry.get().strip()
                if freq_value:
                    freq_config_data.append([f"Freq {i+1}:", f"{freq_value} MHz"])
            
            if len(freq_config_data) > 1:  # Se há frequências configuradas
                freq_config_table = Table(freq_config_data, colWidths=[4*cm, 4*cm])
                freq_config_table.setStyle(TableStyle([
                    ('BACKGROUND', (0, 0), (-1, 0), colors.HexColor('#34495e')),
                    ('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
                    ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
                    ('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
                    ('FONTSIZE', (0, 0), (-1, 0), 10),
                    ('BOTTOMPADDING', (0, 0), (-1, 0), 8),
                    ('BACKGROUND', (0, 1), (-1, -1), colors.beige),
                    ('GRID', (0, 0), (-1, -1), 1, colors.black),
                    ('FONTSIZE', (0, 1), (-1, -1), 9),
                ]))
                story.append(freq_config_table)
            else:
                story.append(Paragraph(f"<i>{t('pdf.quick_threshold_no_freq_configured')}</i>", styles['Normal']))
            
            story.append(Spacer(1, 16))
            
            # Adiciona os gráficos
            story.append(cond_page_break_before_chart_section())
            story.append(Paragraph(t('pdf.quick_threshold_charts'), heading_style))
            
            # Gráfico 1: Threshold
            story.append(cond_page_break_before_subsection_with_figure(8 / 2.54))
            story.append(Paragraph(t('pdf.quick_threshold_chart_title'), styles['Heading3']))
            try:
                import tempfile
                import matplotlib.pyplot as plt
                
                # Cria figura de alta qualidade temporária (sem afetar a original)
                fig_temp = plt.figure(figsize=(12, 6), dpi=300)
                
                # Copia dados do gráfico original para a figura temporária
                ax_temp = fig_temp.add_subplot(111)
                
                # Copia o conteúdo do gráfico original
                for line in self.threshold_ax.get_lines():
                    ax_temp.plot(line.get_xdata(), line.get_ydata(), 
                                color=line.get_color(), linewidth=1.5, 
                                marker=line.get_marker(), markersize=5, 
                                alpha=line.get_alpha(), label=line.get_label())
                
                ax_temp.set_xlabel(t('fastthreshold.freq_mhz_label'), fontsize=11, fontweight='bold')
                ax_temp.set_ylabel(t('fastthreshold.threshold_dbm_label'), fontsize=11, fontweight='bold')
                ax_temp.set_ylim(5, 25)
                ax_temp.grid(True, alpha=0.3, linestyle='--')
                ax_temp.legend(bbox_to_anchor=(1.05, 1), loc='upper left', fontsize=9, framealpha=0.95)
                
                # Ajusta layout
                fig_temp.tight_layout()
                
                # Salva em alta qualidade
                with tempfile.NamedTemporaryFile(suffix='.png', delete=False) as tmp_threshold:
                    fig_temp.savefig(tmp_threshold.name, dpi=300, bbox_inches='tight', 
                                    format='png', facecolor='white', edgecolor='none')
                    plt.close(fig_temp)
                    
                    from reportlab.platypus import Image as RLImage
                    img_threshold = RLImage(tmp_threshold.name, width=16*cm, height=8*cm)
                    story.append(img_threshold)
                    story.append(Spacer(1, 10))
            except Exception as e:
                story.append(Paragraph(f"<i>{t('pdf.quick_threshold_chart_error').format(chart_type=t('pdf.quick_threshold_chart_error_kind_threshold'), error=str(e))}</i>", styles['Normal']))
                fc_log("fast_threshold", f"❌ Erro ao gerar gráfico de Threshold para PDF: {e}")
            
            story.append(Spacer(1, 16))
            
            # Gráfico 2: Estatístico
            story.append(cond_page_break_before_subsection_with_figure(8 / 2.54))
            story.append(Paragraph(t('pdf.quick_threshold_stats_chart'), styles['Heading3']))
            try:
                # Cria figura de alta qualidade temporária (sem afetar a original)
                fig_temp = plt.figure(figsize=(12, 6), dpi=300)
                
                # Copia dados do gráfico original para a figura temporária
                ax_temp = fig_temp.add_subplot(111)
                
                # Copia o conteúdo do gráfico original
                for line in self.stats_ax.get_lines():
                    ax_temp.plot(line.get_xdata(), line.get_ydata(), 
                                color=line.get_color(), linewidth=1.5, 
                                marker=line.get_marker(), markersize=5, 
                                alpha=line.get_alpha(), label=line.get_label())
                
                ax_temp.set_xlabel(t('fastthreshold.freq_mhz_label'), fontsize=11, fontweight='bold')
                ax_temp.set_ylabel(t('fastthreshold.threshold_dbm_label'), fontsize=11, fontweight='bold')
                ax_temp.set_ylim(5, 25)
                ax_temp.grid(True, alpha=0.3, linestyle='--')
                ax_temp.legend(bbox_to_anchor=(1.05, 1), loc='upper left', fontsize=9, framealpha=0.95)
                
                # Ajusta layout
                fig_temp.tight_layout()
                
                # Salva em alta qualidade
                with tempfile.NamedTemporaryFile(suffix='.png', delete=False) as tmp_stats:
                    fig_temp.savefig(tmp_stats.name, dpi=300, bbox_inches='tight', 
                                    format='png', facecolor='white', edgecolor='none')
                    plt.close(fig_temp)
                    
                    from reportlab.platypus import Image as RLImage
                    img_stats = RLImage(tmp_stats.name, width=16*cm, height=8*cm)
                    story.append(img_stats)
                    story.append(Spacer(1, 10))
                    
                    # Adiciona tabela com dados estatísticos
                    story.append(Paragraph(t('pdf.quick_threshold_stats_data'), styles['Heading3']))
                    
                    # Coleta dados das curvas estatísticas
                    lines = self.stats_ax.get_lines()
                    if len(lines) >= 3:
                        freq_data = lines[0].get_xdata()
                        means = lines[0].get_ydata()
                        means_minus_3std = lines[1].get_ydata()
                        means_plus_3std = lines[2].get_ydata()
                        
                        # Cria tabela de dados estatísticos
                        stats_table_data = [
                            [t('fastthreshold.freq_mhz_label'), t('fastthreshold.mean_dbm_label'), t('fastthreshold.mean_minus_3sigma_label'), t('fastthreshold.mean_plus_3sigma_label'), t('fastthreshold.sigma_dbm_label')]
                        ]
                        
                        for freq, mean, mean_minus, mean_plus in zip(freq_data, means, means_minus_3std, means_plus_3std):
                            # Calcula sigma: σ = (Média + 3σ - Média) / 3
                            sigma = (mean_plus - mean) / 3
                            stats_table_data.append([
                                f"{freq:.2f}",
                                f"{mean:.2f}",
                                f"{mean_minus:.2f}",
                                f"{mean_plus:.2f}",
                                f"{sigma:.2f}"
                            ])
                        
                        stats_table = Table(
                            stats_table_data,
                            colWidths=[3.5*cm, 3*cm, 3.5*cm, 3.5*cm, 2.5*cm],
                            repeatRows=1,
                        )
                        stats_table.setStyle(TableStyle([
                            ('BACKGROUND', (0, 0), (-1, 0), colors.HexColor('#34495E')),
                            ('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
                            ('ALIGN', (0, 0), (-1, -1), 'CENTER'),
                            ('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
                            ('FONTSIZE', (0, 0), (-1, 0), 8),
                            ('BOTTOMPADDING', (0, 0), (-1, 0), 10),
                            ('BACKGROUND', (0, 1), (-1, -1), colors.beige),
                            ('GRID', (0, 0), (-1, -1), 1, colors.black),
                            ('FONTSIZE', (0, 1), (-1, -1), 7),
                            ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
                        ]))
                        
                        story.append(stats_table)
                        story.append(Spacer(1, 20))
                    
            except Exception as e:
                story.append(Paragraph(f"<i>{t('pdf.quick_threshold_chart_error').format(chart_type=t('pdf.quick_threshold_chart_error_kind_statistics'), error=str(e))}</i>", styles['Normal']))
                fc_log("fast_threshold", f"❌ Erro ao gerar gráfico de Estatística para PDF: {e}")
            
            # Rodapé do relatório (mesmo padrão do Threshold e outros módulos PDF)
            story.append(cond_page_break_before_footer_block())
            story.append(Spacer(1, 12))
            story.append(Paragraph(t('pdf.additional_info'), heading_style))
            story.append(Paragraph(t('pdf.footer_text'), styles['Normal']))
            translator = get_translator()
            current_lang = translator.get_language()
            if current_lang == 'en':
                gen_ts = datetime.now().strftime("%m/%d/%y at %I:%M:%S %p")
            else:
                gen_ts = datetime.now().strftime("%d/%m/%Y às %H:%M:%S")
            story.append(Paragraph(f"<b>{t('pdf.document_generated_at')}</b> {gen_ts}", styles['Normal']))
            
            # Gera o PDF
            doc.build(story)
            
            fc_log("fast_threshold", f"✅ Relatório PDF gerado: {filepath}")
            return {'success': True}
            
        except Exception as e:
            fc_log("fast_threshold", f"❌ Erro ao gerar PDF: {e}")
            import traceback
            traceback.print_exc()
            return {'success': False, 'error': str(e)}

    def _load_persistent_data(self):
        """Carrega dados persistentes - CORREÇÃO: Não carrega threshold_graph_data misturado"""
        try:
            if os.path.exists(self.db_file):
                with open(self.db_file, 'r', encoding='utf-8') as f:
                    data = json.load(f)

                self.test_history = data.get('test_history', [])
                self.tags_testadas = data.get('tags_testadas', 0)
                self.tags_aprovadas = data.get('tags_aprovadas', 0)
                self.tags_reprovadas = data.get('tags_reprovadas', 0)

                # CORREÇÃO: Log detalhado dos dados carregados
                fc_log("fast_threshold", f"📊 DADOS CARREGADOS:")
                fc_log("fast_threshold", f"   - test_history: {len(self.test_history)} entradas")
                fc_log("fast_threshold", f"   - tags_testadas: {self.tags_testadas}")
                fc_log("fast_threshold", f"   - tags_aprovadas: {self.tags_aprovadas}")
                fc_log("fast_threshold", f"   - tags_reprovadas: {self.tags_reprovadas}")

                # CORREÇÃO: Atualiza contadores baseado no histórico real
                self._update_counters_from_history()
                fc_log("fast_threshold", f"📊 CONTADORES ATUALIZADOS APÓS CARREGAMENTO:")
                fc_log("fast_threshold", f"   - tags_testadas: {self.tags_testadas}")
                fc_log("fast_threshold", f"   - tags_aprovadas: {self.tags_aprovadas}")
                fc_log("fast_threshold", f"   - tags_reprovadas: {self.tags_reprovadas}")

                # NOVO: Carrega frequências persistentes
                self.persistent_frequencies = data.get('persistent_frequencies', [None, None, None, None, None])
                fc_log("fast_threshold", f"📊 Frequências persistentes carregadas: {self.persistent_frequencies}")
                # Armazena temporariamente para restaurar depois nos campos
                self._pending_frequencies = self.persistent_frequencies.copy()

                # CORREÇÃO: Carrega o nome do teste (lembrete) se existir
                test_name = data.get('test_name', '')
                fc_log("fast_threshold", f"🔍 Nome do teste encontrado no arquivo (no carregamento): '{test_name}'")
                # Armazena temporariamente para restaurar depois nos campos
                self._pending_test_name = test_name
                fc_log("fast_threshold", f"🔍 _pending_test_name definido como: '{self._pending_test_name}'")
                if test_name and hasattr(self, 'test_name_entry'):
                    self.test_name_entry.delete(0, tk.END)
                    self.test_name_entry.insert(0, test_name)
                    fc_log("fast_threshold", f"📝 Nome do teste carregado: {test_name}")
                else:
                    fc_log("fast_threshold", f"⚠️ Nome do teste vazio ou campo não existe - será restaurado depois")
                    if not test_name:
                        self._pending_test_name = ""

                # CORREÇÃO: Não carrega threshold_graph_data antigo que pode conter dados misturados
                # Os dados serão reconstruídos a partir do test_history usando a nova lógica
                fc_log("fast_threshold", "🧹 Dados persistentes carregados - threshold_graph_data será reconstruído")

        except Exception as e:
            fc_log("fast_threshold", f"Erro ao carregar dados persistentes: {e}")

    def _save_persistent_data(self):
        """Salva dados persistentes - CORREÇÃO: Não salva threshold_graph_data misturado"""
        try:
            # CORREÇÃO: Captura o nome do teste (lembrete) do campo de entrada com verificação de segurança
            test_name = ""
            if hasattr(self, 'test_name_entry'):
                try:
                    # Tenta verificar se o widget existe
                    if hasattr(self.test_name_entry, 'winfo_exists'):
                        if self.test_name_entry.winfo_exists():
                            test_name = self.test_name_entry.get().strip()
                            fc_log("fast_threshold", f"🔍 Widget existe, valor obtido do campo: '{test_name}'")
                        else:
                            # Widget destruído, usa fallback
                            if hasattr(self, '_pending_test_name'):
                                test_name = self._pending_test_name
                                fc_log("fast_threshold", f"🔍 Widget destruído, valor obtido de _pending_test_name: '{test_name}'")
                    else:
                        # Fallback: tenta pegar o valor diretamente
                        test_name = self.test_name_entry.get().strip()
                        fc_log("fast_threshold", f"🔍 Widget sem winfo_exists, valor obtido diretamente: '{test_name}'")
                except Exception as e:
                    # Widget destruído, usa fallback
                    if hasattr(self, '_pending_test_name'):
                        test_name = self._pending_test_name
                        fc_log("fast_threshold", f"⚠️ Widget destruído, usando fallback _pending_test_name: '{test_name}'")
                    else:
                        fc_log("fast_threshold", f"⚠️ Erro ao obter nome do teste: {e}")
                        import traceback
                        traceback.print_exc()
                        test_name = ""
            else:
                # test_name_entry não existe, usa fallback
                if hasattr(self, '_pending_test_name'):
                    test_name = self._pending_test_name
                    fc_log("fast_threshold", f"⚠️ test_name_entry não existe, usando fallback _pending_test_name: '{test_name}'")
                else:
                    fc_log("fast_threshold", f"⚠️ test_name_entry não existe!")
            fc_log("fast_threshold", f"🔍 Salvando nome do teste: '{test_name}'")
            
            data = {
                'test_history': self.test_history,
                'tags_testadas': self.tags_testadas,
                'tags_aprovadas': self.tags_aprovadas,
                'tags_reprovadas': self.tags_reprovadas,
                'persistent_frequencies': self.persistent_frequencies,  # NOVO: Salva frequências persistentes
                'test_name': test_name  # CORREÇÃO: Salva o nome do teste (lembrete)
                # CORREÇÃO: Não salva threshold_graph_data para evitar dados misturados
                # Os dados serão reconstruídos a partir do test_history
            }

            with open(self.db_file, 'w', encoding='utf-8') as f:
                json.dump(data, f, indent=2, ensure_ascii=False)

        except Exception as e:
            fc_log("fast_threshold", f"Erro ao salvar dados persistentes: {e}")
            import traceback
            traceback.print_exc()

    def _restore_persistent_interface(self):
        """Restaura interface com dados persistentes - CORREÇÃO: Usa nova lógica de separação"""
        try:
            fc_log("fast_threshold", "🔄 _restore_persistent_interface chamada")
            
            # CORREÇÃO: Verifica se os dados foram explicitamente limpos pelo usuário
            if hasattr(self, 'data_cleared_by_user') and self.data_cleared_by_user:
                fc_log("fast_threshold", "🧹 Dados foram limpos pelo usuário - não restaurando")
                return
            
            fc_log("fast_threshold", "📊 Restaurando dados persistentes...")
            fc_log("fast_threshold", f"📊 ANTES da restauração:")
            fc_log("fast_threshold", f"   - tags_testadas: {self.tags_testadas}")
            fc_log("fast_threshold", f"   - tags_aprovadas: {self.tags_aprovadas}")
            fc_log("fast_threshold", f"   - tags_reprovadas: {self.tags_reprovadas}")
            fc_log("fast_threshold", f"   - test_history: {len(self.test_history)} entradas")
            
            # CORREÇÃO: Atualiza contadores baseado no histórico real
            self._update_counters_from_history()
            
            fc_log("fast_threshold", f"📊 DEPOIS da atualização:")
            fc_log("fast_threshold", f"   - tags_testadas: {self.tags_testadas}")
            fc_log("fast_threshold", f"   - tags_aprovadas: {self.tags_aprovadas}")
            fc_log("fast_threshold", f"   - tags_reprovadas: {self.tags_reprovadas}")
            
            # Atualiza interface
            self.tags_testadas_var.set(str(self.tags_testadas))
            fc_log("fast_threshold", f"📊 Interface atualizada - tags_testadas_var: {self.tags_testadas_var.get()}")

            # CORREÇÃO: Restaura nome do teste apenas se _pending_test_name foi definido na inicialização
            if hasattr(self, '_pending_test_name') and self._pending_test_name:
                fc_log("fast_threshold", f"🔍 _restore_persistent_interface - Restaurando nome do teste: '{self._pending_test_name}'")
                if hasattr(self, 'test_name_entry'):
                    try:
                        self.test_name_entry.delete(0, tk.END)
                        self.test_name_entry.insert(0, self._pending_test_name)
                        fc_log("fast_threshold", f"📝 Nome do teste restaurado com sucesso: '{self._pending_test_name}'")
                    except Exception as e:
                        fc_log("fast_threshold", f"⚠️ Erro ao restaurar nome do teste: {e}")
            else:
                fc_log("fast_threshold", f"🔍 _restore_persistent_interface - Nenhum nome do teste para restaurar")
            
            # NOVO: Restaura frequências persistentes nos campos
            if hasattr(self, '_pending_frequencies'):
                for i, freq in enumerate(self._pending_frequencies):
                    if i < len(self.freq_entries) and freq is not None:
                        self.freq_entries[i].delete(0, tk.END)
                        self.freq_entries[i].insert(0, str(freq))
                        fc_log("fast_threshold", f"📊 Frequência {i+1} restaurada: {freq} MHz")

            # CORREÇÃO: Inicializa dados em tempo real como vazios na inicialização
            if not hasattr(self, 'realtime_threshold_data'):
                self.realtime_threshold_data = []

            # CORREÇÃO: Atualiza dados legados para incluir test_id
            self._update_legacy_data()

            # CORREÇÃO: Usa a nova função de plotagem que separa dados corretamente
            self._plot_realtime_with_history()

            # Restaura árvore de histórico
            self._update_history_tree()

        except Exception as e:
            fc_log("fast_threshold", f"❌ Erro ao restaurar interface: {e}")
            import traceback
            traceback.print_exc()

    def _update_counters_from_history(self):
        """CORREÇÃO: Atualiza contadores baseado no número real de entradas no histórico"""
        try:
            # Conta o número real de testes no histórico
            self.tags_testadas = len(self.test_history)
            
            # CORREÇÃO: Calcula tags aprovadas e reprovadas baseado no histórico
            self.tags_aprovadas = 0
            self.tags_reprovadas = 0
            
            for entry in self.test_history:
                results = entry.get('results', [])
                if results:
                    # Verifica se todos os thresholds são válidos (não são 'N/A' ou None)
                    all_valid = all(
                        isinstance(result.get('threshold'), (int, float)) and 
                        result.get('threshold') != 'N/A' and 
                        result.get('threshold') is not None
                        for result in results
                    )
                    
                    if all_valid:
                        self.tags_aprovadas += 1
                    else:
                        self.tags_reprovadas += 1
            
            fc_log("fast_threshold", f"📊 Contadores atualizados: {self.tags_testadas} testes no histórico")
            fc_log("fast_threshold", f"   - Aprovadas: {self.tags_aprovadas}")
            fc_log("fast_threshold", f"   - Reprovadas: {self.tags_reprovadas}")
            
        except Exception as e:
            fc_log("fast_threshold", f"❌ Erro ao atualizar contadores: {e}")

    def _update_tags_display(self, *args):
        """Atualiza o display de Tags Testadas, Tags Selecionadas e Tags sem Teste"""
        try:
            tested_value = self.tags_testadas_var.get()
            selected_count = sum(1 for entry in self.test_history if entry.get('show_in_graph', True))
            
            # Conta tags sem teste (thresholds indeterminados) - INDEPENDENTE do checkbox
            no_test_count = 0
            for entry in self.test_history:
                results = entry.get('results', [])
                has_indeterminate = False
                
                for result in results:
                    if isinstance(result, dict):
                        threshold = result.get('threshold', '')
                    else:
                        threshold = result
                    
                    # Verifica se é threshold indeterminado
                    if isinstance(threshold, str) and ('<' in threshold or '>' in threshold):
                        has_indeterminate = True
                        break  # Basta um threshold indeterminado por tag
                
                if has_indeterminate:
                    no_test_count += 1
            
            self.tags_display_label.config(text=f"Tags Testadas: {tested_value} | Tags Selecionadas: {selected_count} | Tags sem Teste: {no_test_count}")
        except Exception as e:
            fc_log("fast_threshold", f"❌ Erro ao atualizar display de tags: {e}")

    def _update_legacy_data(self):
        """CORREÇÃO: Atualiza dados legados para incluir test_id e melhorar compatibilidade"""
        try:
            updated = False
            for entry in self.test_history:
                # Adiciona test_id se não existir
                if 'test_id' not in entry and 'timestamp' in entry:
                    epc = entry.get('epc', 'N/A')
                    timestamp = entry.get('timestamp', '')
                    if timestamp:
                        test_id = f"{epc}_{timestamp.replace(' ', '_').replace(':', '')}"
                        entry['test_id'] = test_id
                        updated = True
                        fc_log("fast_threshold", f"🔄 Dados legados atualizados: {epc} -> {test_id}")

            # Salva dados atualizados se houve mudanças
            if updated:
                self._save_persistent_data()
                fc_log("fast_threshold", "💾 Dados legados salvos com test_id")

        except Exception as e:
            fc_log("fast_threshold", f"❌ Erro ao atualizar dados legados: {e}")

    def _start_auto_save(self):
        """Inicia salvamento automático periódico"""
        try:
            self._save_persistent_data()
            # Agenda próximo salvamento em 30 segundos
            self.after(30000, self._start_auto_save)
        except Exception as e:
            fc_log("fast_threshold", f"Erro no salvamento automático: {e}")

    def _select_all_tests(self):
        """Seleciona todos os testes no histórico para plotagem"""
        try:
            for i, entry in enumerate(self.test_history):
                entry['show_in_graph'] = True
            
            # Atualiza a árvore
            self._update_history_tree()
            
            # Atualiza o gráfico
            self._update_graph_from_history()
            
            # Atualiza o display
            self._update_tags_display()
            
            # Limpa o gráfico estatístico
            self._clear_statistics_graph()
            
            fc_log("fast_threshold", f"✅ Todos os {len(self.test_history)} testes selecionados para plotagem")
            
        except Exception as e:
            fc_log("fast_threshold", f"❌ Erro ao selecionar todos os testes: {e}")

    def _deselect_all_tests(self):
        """Deseleciona todos os testes no histórico"""
        try:
            for i, entry in enumerate(self.test_history):
                entry['show_in_graph'] = False
            
            # Atualiza a árvore
            self._update_history_tree()
            
            # Atualiza o gráfico
            self._update_graph_from_history()
            
            # Atualiza o display
            self._update_tags_display()
            
            # Limpa o gráfico estatístico
            self._clear_statistics_graph()
            
            fc_log("fast_threshold", f"✅ Todos os {len(self.test_history)} testes deselecionados")
            
        except Exception as e:
            fc_log("fast_threshold", f"❌ Erro ao deselecionar todos os testes: {e}")

    def _delete_selected_tests(self):
        """Exclui os testes selecionados do histórico"""
        try:
            if not self.test_history:
                messagebox.showinfo(t('fastthreshold.info'), t('fastthreshold.no_tests_to_delete'))
                return
            
            # Conta quantos estão selecionados
            selected_count = sum(1 for entry in self.test_history if entry.get('show_in_graph', True))
            
            if selected_count == 0:
                messagebox.showinfo(t('fastthreshold.info'), t('fastthreshold.no_tests_selected_delete'))
                return
            
            # Confirma exclusão
            result = messagebox.askyesno(t('fastthreshold.confirm_delete_title'), 
                                      t('fastthreshold.confirm_delete_msg').format(count=selected_count))
            
            if result:
                # Remove apenas os selecionados
                self.test_history = [entry for entry in self.test_history if not entry.get('show_in_graph', True)]
                
                # Atualiza contadores
                self._update_counters_from_history()
                self.tags_testadas_var.set(str(self.tags_testadas))
                
                # Atualiza interface
                self._update_history_tree()
                self._update_graph_from_history()
                
                # Atualiza o display
                self._update_tags_display()
                
                # Limpa o gráfico estatístico
                self._clear_statistics_graph()
                
                # Salva dados
                self._save_persistent_data()
                
                fc_log("fast_threshold", f"✅ {selected_count} teste(s) excluído(s) do histórico")
                messagebox.showinfo(t('fastthreshold.success'), t('fastthreshold.tests_deleted').format(count=selected_count))
            
        except Exception as e:
            fc_log("fast_threshold", f"❌ Erro ao excluir testes selecionados: {e}")
            messagebox.showerror(t('fastthreshold.error_generic'), t('fastthreshold.error_deleting_tests').format(error=str(e)))

    def _clear_statistics_graph(self):
        """Limpa o gráfico estatístico"""
        try:
            self.stats_ax.clear()
            self.stats_ax.set_ylabel(t('fastthreshold.threshold_dbm_label'))
            self.stats_ax.set_ylim(5, 25)
            self.stats_ax.grid(True, alpha=0.3)
            self.stats_canvas.draw()
            fc_log("fast_threshold", "🧹 Gráfico estatístico limpo")
        except Exception as e:
            fc_log("fast_threshold", f"❌ Erro ao limpar gráfico estatístico: {e}")

    def _generate_statistics(self):
        """Gera análise estatística dos testes selecionados"""
        try:
            # Primeiro, verifica se há thresholds inválidos nos testes selecionados
            invalid_count = 0
            
            for entry in self.test_history:
                if entry.get('show_in_graph', True):
                    results = entry.get('results', [])
                    for result in results:
                        if isinstance(result, dict):
                            threshold = result.get('threshold')
                            if threshold is not None:
                                # Verifica thresholds que indicam valores fora da faixa
                                if isinstance(threshold, str):
                                    if threshold.startswith('>') or threshold.startswith('<'):
                                        invalid_count += 1
            
            # Se houver thresholds inválidos, exibe aviso e não plota
            if invalid_count > 0:
                messagebox.showwarning(t('fastthreshold.indeterminate_thresholds_title'), 
                                     t('fastthreshold.indeterminate_thresholds_msg').format(count=invalid_count))
                return
            
            # Coleta dados dos testes selecionados (apenas valores válidos)
            selected_data = []
            
            for entry in self.test_history:
                if entry.get('show_in_graph', True):
                    results = entry.get('results', [])
                    for result in results:
                        if isinstance(result, dict):
                            freq = result.get('freq')
                            threshold = result.get('threshold')
                            if freq is not None and threshold is not None:
                                # Verifica se é um valor válido para análise
                                if isinstance(threshold, (int, float)):
                                    selected_data.append({'freq': freq, 'threshold': threshold})
                                elif isinstance(threshold, str):
                                    # Tenta extrair valor numérico de strings válidas
                                    import re
                                    match = re.search(r'(\d+\.?\d*)', str(threshold))
                                    if match:
                                        threshold_value = float(match.group(1))
                                        selected_data.append({'freq': freq, 'threshold': threshold_value})
            
            if not selected_data:
                messagebox.showinfo(t('fastthreshold.info'), t('fastthreshold.no_data_for_stats'))
                return
            
            # Agrupa dados por frequência
            freq_data = {}
            for data in selected_data:
                freq = data['freq']
                threshold = data['threshold']
                if freq not in freq_data:
                    freq_data[freq] = []
                freq_data[freq].append(threshold)
            
            # Calcula estatísticas para cada frequência
            frequencies = sorted(freq_data.keys())
            means = []
            stds = []
            means_minus_3std = []
            means_plus_3std = []
            
            for freq in frequencies:
                thresholds = freq_data[freq]
                if len(thresholds) > 0:
                    import statistics
                    mean = statistics.mean(thresholds)
                    std = statistics.stdev(thresholds) if len(thresholds) > 1 else 0
                    
                    means.append(mean)
                    stds.append(std)
                    means_minus_3std.append(mean - 3 * std)
                    means_plus_3std.append(mean + 3 * std)
                else:
                    means.append(0)
                    stds.append(0)
                    means_minus_3std.append(0)
                    means_plus_3std.append(0)
            
            # Plota as curvas estatísticas
            self._plot_statistical_curves(frequencies, means, means_minus_3std, means_plus_3std)
            
            fc_log("fast_threshold", f"📊 Estatísticas geradas para {len(selected_data)} pontos de {len(frequencies)} frequências")
            
        except Exception as e:
            fc_log("fast_threshold", f"❌ Erro ao gerar estatísticas: {e}")
            messagebox.showerror(t('fastthreshold.error_generic'), t('fastthreshold.error_generating_stats').format(error=str(e)))

    def _plot_statistical_curves(self, frequencies, means, means_minus_3std, means_plus_3std):
        """Plota as curvas estatísticas no gráfico"""
        try:
            # Limpa o gráfico
            self.stats_ax.clear()
            self.stats_ax.set_ylabel(t('fastthreshold.threshold_dbm_label'))
            self.stats_ax.set_ylim(5, 25)
            self.stats_ax.grid(True, alpha=0.3)
            
            # Plota as três curvas
            self.stats_ax.plot(frequencies, means, 'o-', color='blue', linewidth=1, markersize=4, alpha=0.7, label=t('fastthreshold.mean'), picker=5)
            self.stats_ax.plot(frequencies, means_minus_3std, 'o-', color='red', linewidth=1, markersize=4, alpha=0.7, label=t('fastthreshold.mean_minus_3sigma'), picker=5)
            self.stats_ax.plot(frequencies, means_plus_3std, 'o-', color='green', linewidth=1, markersize=4, alpha=0.7, label=t('fastthreshold.mean_plus_3sigma'), picker=5)
            
            # Adiciona legenda
            self.stats_ax.legend(bbox_to_anchor=(1.05, 1), loc='upper left', fontsize=8)
            
            # Atualiza o canvas
            self.stats_canvas.draw()
            
            fc_log("fast_threshold", f"📈 Curvas estatísticas plotadas: {len(frequencies)} frequências")
            
        except Exception as e:
            fc_log("fast_threshold", f"❌ Erro ao plotar curvas estatísticas: {e}")

    def _setup_threshold_hover(self):
        """Configura hover para o gráfico principal de threshold (valores ao passar o mouse)."""
        try:
            self.threshold_annot = None
            self.threshold_canvas.mpl_connect('motion_notify_event', self._on_threshold_hover)
        except Exception as e:
            fc_log("fast_threshold", f"❌ Erro ao configurar hover do gráfico de threshold: {e}")

    def _on_threshold_hover(self, event):
        """Evento de hover no gráfico principal de threshold."""
        try:
            if event.inaxes != self.threshold_ax:
                if hasattr(self, 'threshold_annot') and self.threshold_annot is not None:
                    try:
                        self.threshold_annot.remove()
                    except Exception:
                        pass
                    self.threshold_annot = None
                    self.threshold_canvas.draw_idle()
                return
            for line in self.threshold_ax.lines:
                cont, ind = line.contains(event)
                if cont:
                    pos = line.get_xydata()[ind["ind"][0]]
                    x_coord, y_coord = pos[0], pos[1]
                    label = line.get_label()
                    tooltip_text = f"{label}\nFreq: {x_coord:.1f} MHz\nThreshold: {y_coord:.1f} dBm"
                    self._position_threshold_tooltip_smartly(event, x_coord, y_coord, tooltip_text)
                    return
            if hasattr(self, 'threshold_annot') and self.threshold_annot is not None:
                try:
                    self.threshold_annot.remove()
                except Exception:
                    pass
                self.threshold_annot = None
                self.threshold_canvas.draw_idle()
        except Exception as e:
            fc_log("fast_threshold", f"❌ Erro no hover do gráfico de threshold: {e}")

    def _position_threshold_tooltip_smartly(self, event, x_pos, y_pos, tooltip_text):
        """Posiciona o tooltip do gráfico de threshold ao passar o mouse."""
        try:
            if hasattr(self, 'threshold_annot') and self.threshold_annot is not None:
                try:
                    self.threshold_annot.remove()
                except Exception:
                    pass
            self.threshold_annot = self.threshold_ax.annotate(
                tooltip_text,
                xy=(x_pos, y_pos),
                xytext=(20, 20),
                textcoords="offset points",
                bbox=dict(boxstyle="round,pad=0.5",
                         facecolor="lightyellow",
                         alpha=0.9,
                         edgecolor="gray",
                         linewidth=0.5),
                fontsize=9,
                ha='left',
                va='bottom',
                color="black"
            )
            self.threshold_canvas.draw_idle()
        except Exception as e:
            fc_log("fast_threshold", f"❌ Erro ao posicionar tooltip do gráfico de threshold: {e}")

    def _setup_stats_hover(self):
        """Configura hover para o gráfico de Análise Estatística"""
        try:
            fc_log("fast_threshold", "🔧 Iniciando configuração do hover para gráfico estatístico...")
            
            # Inicializa variável para armazenar anotação atual
            self.stats_annot = None
            
            # Conecta evento de movimento do mouse
            self.stats_canvas.mpl_connect('motion_notify_event', self._on_stats_hover)
            fc_log("fast_threshold", "✅ Hover configurado para gráfico de Análise Estatística")
            
        except Exception as e:
            fc_log("fast_threshold", f"❌ Erro ao configurar hover do gráfico estatístico: {e}")
            import traceback
            traceback.print_exc()

    def _on_stats_hover(self, event):
        """Evento de hover no gráfico de Análise Estatística"""
        try:
            # Verifica se está dentro do gráfico estatístico
            if event.inaxes != self.stats_ax:
                if hasattr(self, 'stats_annot') and self.stats_annot is not None:
                    try:
                        self.stats_annot.remove()
                    except:
                        pass
                    self.stats_annot = None
                    self.stats_canvas.draw_idle()
                return
            
            # Verifica se há linhas no gráfico
            lines = self.stats_ax.lines
            
            # Verifica se o mouse está sobre uma linha da curva
            for i, line in enumerate(lines):
                cont, ind = line.contains(event)
                if cont:
                    # Mouse está sobre um ponto da linha
                    pos = line.get_xydata()[ind["ind"][0]]
                    x_coord, y_coord = pos[0], pos[1]
                    
                    # Formata o texto do tooltip
                    label = line.get_label()  # Pega o label da linha (ex: "Média")
                    tooltip_text = f"{label}\nFreq: {x_coord:.1f} MHz\nThreshold: {y_coord:.1f} dBm"
                    
                    # Posiciona o tooltip
                    self._position_stats_tooltip_smartly(event, x_coord, y_coord, tooltip_text)
                    return
            
            # Se chegou aqui, mouse não está sobre nenhuma linha
            if hasattr(self, 'stats_annot') and self.stats_annot is not None:
                try:
                    self.stats_annot.remove()
                except:
                    pass
                self.stats_annot = None
                self.stats_canvas.draw_idle()
                
        except Exception as e:
            fc_log("fast_threshold", f"❌ Erro no hover do gráfico estatístico: {e}")
            import traceback
            traceback.print_exc()

    def _position_stats_tooltip_smartly(self, event, x_pos, y_pos, tooltip_text):
        """Posiciona o tooltip do gráfico estatístico de forma inteligente"""
        try:
            # Remove anotação anterior se existir
            if hasattr(self, 'stats_annot') and self.stats_annot is not None:
                try:
                    self.stats_annot.remove()
                except:
                    pass
            
            # Cria nova anotação
            self.stats_annot = self.stats_ax.annotate(
                tooltip_text, 
                xy=(x_pos, y_pos), 
                xytext=(20, 20), 
                textcoords="offset points",
                bbox=dict(boxstyle="round,pad=0.5", 
                         facecolor="yellow", 
                         alpha=0.9,
                         edgecolor="black",
                         linewidth=0.5),
                fontsize=9, 
                ha='left',
                va='bottom',
                color="black"
            )
            
            # Força o redesenho do canvas
            self.stats_canvas.draw_idle()
            
        except Exception as e:
            fc_log("fast_threshold", f"❌ Erro ao posicionar tooltip do gráfico estatístico: {e}")
            import traceback
            traceback.print_exc()

    def _export_to_excel(self):
        """Exporta histórico de testes e dados estatísticos para Excel"""
        try:
            if not self.test_history:
                messagebox.showwarning(t('fastthreshold.warning'), t('fastthreshold.no_tests_to_export'))
                return
            
            # Gera nome do arquivo
            now = datetime.now()
            filename = f"Quick_Threshold_Export {now.strftime('%d.%m.%y_%H.%M.%S')}.xlsx"
            
            # Diálogo para salvar arquivo
            filepath = filedialog.asksaveasfilename(
                defaultextension=".xlsx",
                filetypes=[(t('fastthreshold.excel_files'), "*.xlsx"), (t('fastthreshold.excel_2003'), "*.xls")],
                initialfile=filename,
                title=t('fastthreshold.export_excel_title')
            )
            
            if not filepath:
                return
            
            self.status_label.config(text=t('fastthreshold.exporting_excel'), fg="#f39c12")
            self.update()
            
            # Importa openpyxl
            try:
                from openpyxl import Workbook
                from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
                from openpyxl.utils import get_column_letter
            except ImportError:
                messagebox.showerror(t('fastthreshold.error_generic'), t('fastthreshold.openpyxl_not_found'))
                return
            
            # Cria workbook
            wb = Workbook()
            ws = wb.active
            ws.title = "Histórico de Testes"
            
            # Estilos
            header_fill = PatternFill(start_color="34495E", end_color="34495E", fill_type="solid")
            header_font = Font(bold=True, color="FFFFFF", size=11)
            border = Border(left=Side(style='thin'), right=Side(style='thin'), 
                           top=Side(style='thin'), bottom=Side(style='thin'))
            
            # Cabeçalho
            headers = ['EPC', 'Freq 1 (dBm)', 'Freq 2 (dBm)', 'Freq 3 (dBm)', 'Freq 4 (dBm)', 'Freq 5 (dBm)', 'Data/Hora']
            for col_num, header in enumerate(headers, 1):
                cell = ws.cell(row=1, column=col_num)
                cell.value = header
                cell.fill = header_fill
                cell.font = header_font
                cell.alignment = Alignment(horizontal='center', vertical='center')
                cell.border = border
            
            # Dados dos testes
            for row_num, entry in enumerate(self.test_history, 2):
                epc = entry.get('epc', 'N/A')
                results = entry.get('results', [])
                timestamp = entry.get('timestamp', 'N/A')
                
                # EPC
                cell = ws.cell(row=row_num, column=1)
                cell.value = epc
                cell.border = border
                
                # Frequências
                for col_num in range(2, 7):
                    cell = ws.cell(row=row_num, column=col_num)
                    freq_idx = col_num - 2
                    if freq_idx < len(results):
                        result = results[freq_idx]
                        if isinstance(result, dict):
                            threshold = result.get('threshold', '--')
                        else:
                            threshold = result
                        
                        if isinstance(threshold, (int, float)):
                            cell.value = round(threshold, 2)
                        else:
                            cell.value = str(threshold)
                    else:
                        cell.value = '--'
                    
                    cell.alignment = Alignment(horizontal='center')
                    cell.border = border
                
                # Data/Hora
                cell = ws.cell(row=row_num, column=7)
                cell.value = timestamp
                cell.border = border
            
            # Ajusta largura das colunas
            ws.column_dimensions['A'].width = 30
            for col in ['B', 'C', 'D', 'E', 'F']:
                ws.column_dimensions[col].width = 14
            ws.column_dimensions['G'].width = 20
            
            # Aba 2: Dados Estatísticos
            if hasattr(self, 'stats_ax') and len(self.stats_ax.get_lines()) > 0:
                ws_stats = wb.create_sheet(t('fastthreshold.statistical_analysis'))
                
                # Cabeçalho da aba de estatísticas
                headers_stats = [t('fastthreshold.freq_mhz_label'), t('fastthreshold.mean_dbm_label'), t('fastthreshold.mean_minus_3sigma_label'), t('fastthreshold.mean_plus_3sigma_label')]
                for col_num, header in enumerate(headers_stats, 1):
                    cell = ws_stats.cell(row=1, column=col_num)
                    cell.value = header
                    cell.fill = header_fill
                    cell.font = header_font
                    cell.alignment = Alignment(horizontal='center', vertical='center')
                    cell.border = border
                
                # Coleta dados dos gráficos de estatística
                lines = self.stats_ax.get_lines()
                if len(lines) >= 3:
                    try:
                        # Média (primeira linha - azul)
                        freq_data = lines[0].get_xdata()
                        means = lines[0].get_ydata()
                        means_minus_3std = lines[1].get_ydata()
                        means_plus_3std = lines[2].get_ydata()
                        
                        # Adiciona dados
                        for row_num, (freq, mean, mean_minus, mean_plus) in enumerate(
                            zip(freq_data, means, means_minus_3std, means_plus_3std), 2):
                            
                            ws_stats.cell(row=row_num, column=1).value = round(freq, 2)
                            ws_stats.cell(row=row_num, column=2).value = round(mean, 2)
                            ws_stats.cell(row=row_num, column=3).value = round(mean_minus, 2)
                            ws_stats.cell(row=row_num, column=4).value = round(mean_plus, 2)
                            
                            for col in range(1, 5):
                                cell = ws_stats.cell(row=row_num, column=col)
                                cell.alignment = Alignment(horizontal='center')
                                cell.border = border
                        
                        # Ajusta largura das colunas
                        ws_stats.column_dimensions['A'].width = 18
                        for col in ['B', 'C', 'D']:
                            ws_stats.column_dimensions[col].width = 18
                    except Exception as e:
                        fc_log("fast_threshold", f"⚠️ Erro ao exportar dados estatísticos: {e}")
            
            # Salva o workbook
            wb.save(filepath)
            
            self.status_label.config(text=t('fastthreshold.excel_export_completed'), fg="#27ae60")
            messagebox.showinfo(t('fastthreshold.success'), 
                              t('fastthreshold.excel_exported').format(filepath=filepath))
            
            fc_log("fast_threshold", f"✅ Dados exportados para Excel: {filepath}")
            
        except Exception as e:
            self.status_label.config(text=t('fastthreshold.error_exporting_excel_status'), fg="#c0392b")
            messagebox.showerror(t('fastthreshold.error_generic'), t('fastthreshold.error_exporting_excel').format(error=str(e)))
            fc_log("fast_threshold", f"❌ Erro ao exportar para Excel: {e}")
            import traceback
            traceback.print_exc()