# gui/main_window.py
import os
import json
import numpy as np
from PyQt6.QtWidgets import (QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
                             QPushButton, QListWidget, QLabel, QFileDialog,
                             QTextEdit, QGridLayout, QMessageBox)

# Importações do Matplotlib para PyQt6
from matplotlib.backends.backend_qtagg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure

# Importação do SciPy
from scipy.signal import savgol_filter
from scipy.stats import pearsonr

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Wood Analysis Tool - Resistograph (PyQt6)")
        self.resize(1200, 800)

        self.current_folder = ""
        self.setup_ui()

    def setup_ui(self):
        # Widget Central
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        main_layout = QHBoxLayout(central_widget)

        # ==========================================
        # PAINEL ESQUERDO (Navegação e Scripts)
        # ==========================================
        left_panel = QVBoxLayout()

        # 1. Seleção de Pasta
        self.btn_select_folder = QPushButton("1. Selecionar Pasta (.rgp)")
        self.btn_select_folder.clicked.connect(self.select_folder)
        left_panel.addWidget(self.btn_select_folder)

        self.lbl_folder = QLabel("Nenhuma pasta selecionada")
        self.lbl_folder.setWordWrap(True)
        left_panel.addWidget(self.lbl_folder)

        # 2. Lista de Arquivos
        left_panel.addWidget(QLabel("2. Navegador de Arquivos:"))
        self.file_list = QListWidget()
        self.file_list.itemClicked.connect(self.on_file_selected)
        left_panel.addWidget(self.file_list)

        # 3. Os 12 Botões de Script em Grid
        left_panel.addWidget(QLabel("3. Executar Scripts (Geração de .xlsx):"))
        grid_scripts = QGridLayout()
        for i in range(1, 13):
            btn = QPushButton(f"Script {i}")
            btn.clicked.connect(lambda checked, idx=i: self.run_script(idx))
            row = (i - 1) // 2
            col = (i - 1) % 2
            grid_scripts.addWidget(btn, row, col)

        left_panel.addLayout(grid_scripts)

        # Adiciona o painel esquerdo ao layout principal com largura fixa
        left_widget = QWidget()
        left_widget.setLayout(left_panel)
        left_widget.setFixedWidth(350)
        main_layout.addWidget(left_widget)

        # ==========================================
        # PAINEL DIREITO (Visualização de Dados)
        # ==========================================
        right_panel = QVBoxLayout()

        # Texto do Header (JSON formatado)
        right_panel.addWidget(QLabel("Metadados (Header):"))
        self.text_header = QTextEdit()
        self.text_header.setReadOnly(True)
        self.text_header.setMaximumHeight(220)
        # Fonte monoespaçada para manter o alinhamento
        self.text_header.setStyleSheet("font-family: monospace;")
        right_panel.addWidget(self.text_header)

        # Canvas do Matplotlib
        self.figure = Figure(tight_layout=True)
        self.canvas = FigureCanvas(self.figure)
        self.ax_drill = self.figure.add_subplot(211)
        self.ax_feed = self.figure.add_subplot(212)
        right_panel.addWidget(self.canvas)

        main_layout.addLayout(right_panel)

    def select_folder(self):
        # Lógica Flexível para buscar o diretório inicial
        base_dir = os.getcwd() # Começa de onde o app.py foi executado

        # Tenta voltar um nível para acessar a raiz do projeto (Ex: ~/Development/FUNPINUS UFPR Madeira/)
        parent_dir = os.path.dirname(base_dir)

        # Procura se a pasta 'Dados resistógrafo' existe no nível acima
        alvo_resistografo = os.path.join(parent_dir, "Dados resistógrafo")

        if os.path.exists(alvo_resistografo):
            start_dir = alvo_resistografo
        else:
            start_dir = base_dir # Fallback: se não achar, abre na pasta atual

        folder = QFileDialog.getExistingDirectory(self, "Selecione a pasta com arquivos .rgp", start_dir)

        if folder:
            self.current_folder = folder
            self.lbl_folder.setText(f"Pasta: {os.path.basename(folder)}")
            self.file_list.clear()

            # Lê a pasta e organiza em ordem alfabética de A a Z
            arquivos_ordenados = sorted(os.listdir(folder))

            # Popula a lista apenas com arquivos .rgp
            for file in arquivos_ordenados:
                if file.lower().endswith('.rgp'):
                    self.file_list.addItem(file)

            if self.file_list.count() == 0:
                QMessageBox.warning(self, "Aviso", "Nenhum arquivo .rgp encontrado nesta pasta.")

    def on_file_selected(self, item):
        filepath = os.path.join(self.current_folder, item.text())

        try:
            # Lógica ROBUSTA de leitura do .rgp
            with open(filepath, 'r', encoding='utf-8') as f:
                raw_text = f.read()

            # Encontra onde o JSON realmente começa (ignora lixo no início do arquivo)
            start_idx = raw_text.find('{')
            if start_idx == -1:
                raise ValueError("Nenhum bloco JSON ({) encontrado no arquivo.")

            clean_text = raw_text[start_idx:]
            data = json.loads(clean_text)

            # Extração baseada no seu modelo Measurement105.rgp
            header = data.get("header", {})
            profile = data.get("profile", {})

            drill_data = np.array(profile.get("drill", []))
            feed_data = np.array(profile.get("feed", []))

            # --- CÁLCULO DA CORRELAÇÃO DE PEARSON ---
            pearson_r = 0.0
            p_value = 0.0
            # Garante que os arrays não estão vazios e têm o mesmo tamanho
            if len(drill_data) > 0 and len(feed_data) > 0:
                min_len = min(len(drill_data), len(feed_data))
                # Corta os arrays para o mesmo tamanho, caso haja disparidade
                drill_corr = drill_data[:min_len]
                feed_corr = feed_data[:min_len]

                # Usando scipy.stats.pearsonr para calcular r e o valor-p
                pearson_r, p_value = pearsonr(drill_corr, feed_corr)

            # --- FORMATAÇÃO DOS METADADOS (HEADER) ---
            dia = f"{header.get('dateDay', 0):02d}"
            mes = f"{header.get('dateMonth', 0):02d}"
            ano = header.get('dateYear', 0)
            hora = f"{header.get('timeHour', 0):02d}"
            minuto = f"{header.get('timeMinute', 0):02d}"
            segundo = f"{header.get('timeSecond', 0):02d}"
            data_hora = f"{dia}/{mes}/{ano} {hora}:{minuto}:{segundo}"

            wi_set = header.get("wi", {}).get("std", {}).get("set", {})
            ssd = wi_set.get("ssd", {})
            dd = wi_set.get("dd", {})

            texto_formatado = f"""=== IDENTIFICAÇÃO ===
Amostra (ID)      : {header.get('idNumber', 'N/A')}
Anotação (Remark) : {header.get('remark', 'N/A')}
Data da Medição   : {data_hora}

=== ESTATÍSTICA (Drill x Feed) ===
Correlação Pearson: r = {pearson_r:.4f} (p-value = {p_value:.4e})

=== PARÂMETROS FÍSICOS ===
Prof. Selecionada : {header.get('depthPresel', 0)} mm
Prof. Medida      : {header.get('depthMsmt', 0)} mm
Ângulo de Perf.   : {header.get('tiltAngle', 0)}°
Veloc. Avanço     : {header.get('speedFeed', 0)}
Veloc. Rotação    : {header.get('speedDrill', 0)} RPM
Amp Max Feed      : {header.get('ampMaxFeed', 0)}
Amp Max Drill     : {header.get('ampMaxDrill', 0)}

=== CONFIGURAÇÕES DO EQUIPAMENTO ===
Resolution Feed   : {header.get('resolutionFeed', 0)}
Resolution Amp    : {header.get('resolutionAmp', 0)}
Device Length     : {header.get('deviceLength', 0)}
Offset Feed       : {header.get('offsetFeed', 0)}
Offset Drill      : {header.get('offsetDrill', 0)}
Abort State       : {header.get('abortState', 0)}
"""
            # Atualiza o Header na UI
            self.text_header.setText(texto_formatado)

            # --- PROCESSAMENTO DOS GRÁFICOS ---
            # Aplica o Filtro Savitzky-Golay (Janela de 51, polinômio de ordem 3)
            window = 51
            poly = 3
            if len(drill_data) > window and len(feed_data) > window:
                drill_sg = savgol_filter(drill_data, window, poly)
                feed_sg = savgol_filter(feed_data, window, poly)
            else:
                drill_sg = drill_data
                feed_sg = feed_data

            # Atualiza os Gráficos
            self.ax_drill.clear()
            self.ax_feed.clear()

            # Plota Drill
            self.ax_drill.plot(drill_data, color='#cccccc', label='Bruto', alpha=0.7)
            self.ax_drill.plot(drill_sg, color='#1f77b4', label='Filtro SG (Estimativa DB)', linewidth=1.5)
            self.ax_drill.set_title(f"Perfil de Resistência (drill) - {item.text()}")
            self.ax_drill.set_ylabel("Amplitude")
            self.ax_drill.set_xlabel("Profundidade (Pontos de Medição)")
            self.ax_drill.legend()
            self.ax_drill.grid(True, linestyle='--', alpha=0.5)

            # Plota Feed
            self.ax_feed.plot(feed_data, color='#cccccc', label='Bruto', alpha=0.7)
            self.ax_feed.plot(feed_sg, color='#d62728', label='Filtro SG', linewidth=1.5)
            self.ax_feed.set_title("Sinal de Avanço feed (proporcional à velocidade de penetração da broca)")
            self.ax_feed.set_ylabel("Amplitude")
            self.ax_feed.set_xlabel("Profundidade (Pontos de Medição)")
            self.ax_feed.legend()
            self.ax_feed.grid(True, linestyle='--', alpha=0.5)

            # Desenha na tela
            self.canvas.draw()

        except json.JSONDecodeError as e:
            QMessageBox.critical(self, "Erro de JSON", f"O arquivo está corrompido ou mal formatado:\n{str(e)}")
        except Exception as e:
            QMessageBox.critical(self, "Erro de Leitura", f"Erro ao processar o arquivo:\n{str(e)}")

    def run_script(self, script_id):
        if not self.current_folder:
            QMessageBox.warning(self, "Aviso", "Selecione uma pasta com arquivos .rgp primeiro.")
            return

        # Lógica de integração dos scripts da pasta scripts/
        QMessageBox.information(self, "Processamento em Lote",
                                f"Script {script_id} acionado!\nEle varrerá a pasta:\n{self.current_folder}\n\n(Conecte suas funções do pandas aqui)")
