import os
import json
from datetime import datetime

from matplotlib.backends.backend_pdf import PdfPages
import matplotlib.pyplot as plt
from matplotlib.figure import Figure


from .app_console import fc_log
def _load_noise_history():
    current_dir = os.path.dirname(os.path.abspath(__file__))
    db_path = os.path.join(current_dir, 'noise_db.json')
    if not os.path.exists(db_path):
        return []
    try:
        with open(db_path, 'r', encoding='utf-8') as f:
            data = json.load(f)
        return data.get('test_history', [])
    except Exception:
        return []


def _load_logo_ax(ax):
    try:
        from PIL import Image
        # Caminho do logo - usa caminho absoluto para funcionar no standalone
        root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))
        logo_path = os.path.join(root, 'assets', 'images', 'fasttag_logo.png')
        fc_log("noise_pdf_report", f"🔍 DEBUG LOGO PDF: Tentando carregar logo de: {logo_path}")
        
        if os.path.exists(logo_path):
            fc_log("noise_pdf_report", f"✅ DEBUG LOGO PDF: Logo encontrado, carregando...")
            img = Image.open(logo_path)
            ax.imshow(img)
            ax.axis('off')
            fc_log("noise_pdf_report", f"✅ DEBUG LOGO PDF: Logo carregado com sucesso!")
        else:
            fc_log("noise_pdf_report", f"❌ DEBUG LOGO PDF: Logo não encontrado em: {logo_path}")
            # Fallback: logo estilizado em texto
            ax.text(0.5, 0.5, '🏷️ FastTag', ha='center', va='center', fontsize=24, 
                   fontweight='bold', color='#2c3e50')
            ax.axis('off')
    except Exception as e:
        fc_log("noise_pdf_report", f"❌ DEBUG LOGO PDF: Erro ao carregar logo: {e}")
        # Fallback: logo estilizado em texto
        ax.text(0.5, 0.5, '🏷️ FastTag', ha='center', va='center', fontsize=24, 
               fontweight='bold', color='#2c3e50')
        ax.axis('off')


def _get_system_info():
    """Coleta informações do sistema/soft para o cabeçalho do relatório."""
    # Versão do software: usa valor do README ou hardcode simples
    sw_version = 'FastChecker II'
    try:
        readme_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', 'README.md'))
        if os.path.exists(readme_path):
            with open(readme_path, 'r', encoding='utf-8') as f:
                for line in f:
                    if 'Versão' in line or 'Version' in line:
                        sw_version = line.strip()
                        break
    except Exception:
        pass

    # Informações de licença (resumo)
    licenses_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', 'licenses.json'))
    license_summary = 'N/A'
    try:
        if os.path.exists(licenses_path):
            with open(licenses_path, 'r', encoding='utf-8') as f:
                lic = json.load(f)
            license_summary = f"Entradas: {len(lic)}"
    except Exception:
        pass

    # Formata data conforme idioma
    try:
        from .i18n import get_translator
    except ImportError:
        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': sw_version,
        'hardware': 'RFID Reader (resumo)',
        'firmware': '-',
        'license': license_summary,
        'generated_at': datetime.now().strftime(date_format)
    }


def _calculate_severity(max_noise, avg_noise):
    """Calcula a severidade baseada na diferença entre ruído máximo e médio"""
    try:
        from .i18n import t
    except ImportError:
        from i18n import t
    
    diff = max_noise - avg_noise
    if diff <= 3:
        return t('noise.severity_low')
    elif 3 < diff <= 6:
        return t('noise.severity_medium')
    elif 6 < diff <= 9:
        return t('noise.severity_high')
    else:
        return t('noise.severity_very_high')


def _generate_analysis_summary(tests):
    """Gera um resumo analítico dos resultados dos testes"""
    if not tests:
        return "Nenhum teste disponível para análise."
    
    # Coleta estatísticas
    total_tests = len(tests)
    total_duration = sum(t.get('duration', 0) for t in tests)
    
    all_noise_levels = []
    severity_counts = {"Baixa": 0, "Média": 0, "Alta": 0, "Muito Alta": 0}
    
    for test in tests:
        noise_data = test.get('noise_data', {})
        if isinstance(noise_data, dict) and noise_data:
            first_val = next(iter(noise_data.values()))
            if isinstance(first_val, dict) and 'value' in first_val:
                values = [v['value'] for v in noise_data.values()]
            else:
                values = list(noise_data.values())
            
            if values:
                avg_v = sum(values) / len(values)
                max_v = max(values)
                min_v = min(values)
                all_noise_levels.extend(values)
                
                severity = _calculate_severity(max_v, avg_v)
                severity_counts[severity] += 1
    
    # Análise estatística
    if all_noise_levels:
        global_avg = sum(all_noise_levels) / len(all_noise_levels)
        global_min = min(all_noise_levels)
        global_max = max(all_noise_levels)
        noise_range = global_max - global_min
    else:
        global_avg = global_min = global_max = noise_range = 0
    
    # Gera resumo
    summary = f"""
ANÁLISE DOS RESULTADOS - NOISE CHECK

RESUMO GERAL:
• Total de testes analisados: {total_tests}
• Duração total de monitoramento: {total_duration} segundos
• Ruído médio geral: {global_avg:.1f} dBm
• Faixa de ruído observada: {global_min:.1f} a {global_max:.1f} dBm (amplitude: {noise_range:.1f} dBm)

DISTRIBUIÇÃO DE SEVERIDADE:
• Baixa: {severity_counts['Baixa']} testes ({severity_counts['Baixa']/total_tests*100:.1f}%)
• Média: {severity_counts['Média']} testes ({severity_counts['Média']/total_tests*100:.1f}%)
• Alta: {severity_counts['Alta']} testes ({severity_counts['Alta']/total_tests*100:.1f}%)
• Muito Alta: {severity_counts['Muito Alta']} testes ({severity_counts['Muito Alta']/total_tests*100:.1f}%)

INTERPRETAÇÃO:
"""
    
    if severity_counts['Muito Alta'] > 0:
        summary += "⚠️ ALERTA: Detectados testes com severidade muito alta, indicando variações extremas de ruído que podem comprometer a operação do sistema RFID.\n"
    
    if severity_counts['Alta'] > total_tests * 0.3:
        summary += "⚠️ ATENÇÃO: Mais de 30% dos testes apresentam severidade alta, sugerindo ambiente com interferência significativa.\n"
    
    if severity_counts['Baixa'] > total_tests * 0.5:
        summary += "✅ POSITIVO: Mais de 50% dos testes apresentam baixa severidade, indicando ambiente relativamente estável.\n"
    
    if global_avg > -50:
        summary += "⚠️ ATENÇÃO: Ruído médio elevado (>-50 dBm), pode afetar o alcance de leitura das tags RFID.\n"
    elif global_avg < -70:
        summary += "✅ EXCELENTE: Ruído médio baixo (<-70 dBm), ambiente ideal para operação RFID.\n"
    
    if noise_range > 15:
        summary += "⚠️ ATENÇÃO: Grande variação de ruído detectada, recomenda-se investigar fontes de interferência.\n"
    elif noise_range < 5:
        summary += "✅ ESTÁVEL: Baixa variação de ruído, ambiente consistente para operação RFID.\n"
    
    summary += f"\nRECOMENDAÇÕES:\n"
    if severity_counts['Muito Alta'] > 0:
        summary += "• Investigar e eliminar fontes de interferência identificadas\n"
    if global_avg > -50:
        summary += "• Considerar ajuste de potência do leitor ou uso de filtros\n"
    if noise_range > 10:
        summary += "• Monitorar continuamente o ambiente para identificar padrões de interferência\n"
    summary += "• Manter monitoramento regular para detectar mudanças no ambiente\n"
    summary += "• Documentar testes em horários diferentes para identificar variações temporais\n"
    
    return summary


def generate_noise_report(output_pdf_path: str, title: str = 'Relatório de Testes - Noise Check') -> str:
    """Gera um PDF de exemplo com os testes atuais do Noise Check.

    Args:
        output_pdf_path: Caminho completo do arquivo PDF a ser gerado.
        title: Título do relatório.

    Returns:
        Caminho do PDF gerado.
    """
    os.makedirs(os.path.dirname(output_pdf_path), exist_ok=True)

    tests = _load_noise_history()
    sysinfo = _get_system_info()

    with PdfPages(output_pdf_path) as pdf:
        # Capa
        fig: Figure = plt.figure(figsize=(8.27, 11.69))  # A4 portrait em inches
        fig.suptitle(title, fontsize=16, y=0.95)
        gs = fig.add_gridspec(3, 1, height_ratios=[2, 1, 2])
        ax_logo = fig.add_subplot(gs[0, 0])
        _load_logo_ax(ax_logo)

        ax_info = fig.add_subplot(gs[1, 0])
        ax_info.axis('off')
        
        # Descrição do teste
        test_description = "Este relatório contém os resultados dos testes de ruído realizados pelo FastChecker II. " \
                          "Os testes avaliam o nível de interferência no ambiente RFID e fornecem informações " \
                          "importantes para otimização do sistema."
        
        ax_info.text(0.02, 0.8, "Descrição do Teste:", fontsize=12, fontweight='bold', va='top', ha='left')
        ax_info.text(0.02, 0.65, test_description, fontsize=10, va='top', ha='left', 
                    bbox=dict(boxstyle="round,pad=0.5", facecolor="lightgray", alpha=0.3))
        
        # Informações do sistema
        system_text = (
            f"Software: {sysinfo['software']}\n"
            f"Hardware: {sysinfo['hardware']}\n"
            f"Firmware: {sysinfo['firmware']}\n"
            f"Licença: {sysinfo['license']}\n"
            f"Gerado em: {sysinfo['generated_at']}"
        )
        ax_info.text(0.02, 0.4, system_text, fontsize=11, va='top', ha='left')

        ax_footer = fig.add_subplot(gs[2, 0])
        ax_footer.axis('off')
        
        # Rodapé com informações adicionais
        footer_text = (
            "Relatório automático gerado pelo FastChecker II\n"
            "Sistema de análise e teste RFID profissional\n"
            "Para suporte técnico, consulte a documentação do sistema"
        )
        ax_footer.text(0.5, 0.7, footer_text, ha='center', va='center', fontsize=10, 
                      bbox=dict(boxstyle="round,pad=0.5", facecolor="lightblue", alpha=0.2))
        
        # Data e hora de geração - formata conforme idioma
        from datetime import datetime
        try:
            from .i18n import get_translator, t
        except ImportError:
            from i18n import get_translator, t
        translator = get_translator()
        if translator.get_language() == 'en':
            timestamp = datetime.now().strftime("%m/%d/%y at %I:%M:%S %p")
            footer_text = f"Document generated at: {timestamp}"
        else:
            timestamp = datetime.now().strftime("%d/%m/%Y às %H:%M:%S")
            footer_text = f"Documento gerado em: {timestamp}"
        ax_footer.text(0.5, 0.3, footer_text, ha='center', va='center', fontsize=9)
        pdf.savefig(fig); plt.close(fig)

        # Sumário de testes - TABELA IGUAL AO PRINT
        fig = plt.figure(figsize=(8.27, 11.69))
        fig.suptitle('Sumário dos Testes - Noise Check', fontsize=14, fontweight='bold', y=0.95)
        ax = fig.add_subplot(111)
        ax.axis('off')
        
        if not tests:
            ax.text(0.5, 0.5, 'Nenhum teste encontrado no histórico.', ha='center', va='center', 
                   fontsize=12, style='italic')
        else:
            # Cabeçalho igual ao print
            headers = ['Plot', 'Nome do Teste', 'Duração (s)', 'Ruído Médio (dBm)', 'Ruído Mínimo (dBm)', 'Ruído Máximo (dBm)', 'Hora Ruído Máximo', 'Data/Hora', 'Severidade']
            col_widths = [0.06, 0.15, 0.08, 0.12, 0.12, 0.12, 0.12, 0.15, 0.08]
            
            start_x = 0.03
            header_y = 0.88
            header_height = 0.04
            
            # Fundo do cabeçalho cinza claro
            ax.add_patch(plt.Rectangle((start_x, header_y-header_height), 0.94, header_height, 
                                     facecolor='#F5F5F5', edgecolor='none'))
            
            # Desenha cabeçalho
            for i, (header, width) in enumerate(zip(headers, col_widths)):
                x_pos = start_x + sum(col_widths[:i]) + 0.005
                ax.text(x_pos, header_y-0.02, header, fontsize=9, fontweight='bold', ha='left', va='center')
            
            # Linhas verticais do cabeçalho
            for i in range(len(headers)):
                x_line = start_x + sum(col_widths[:i])
                ax.plot([x_line, x_line], [header_y-header_height, header_y], '#E0E0E0', linewidth=0.5)
            
            # Linha horizontal do cabeçalho
            ax.plot([start_x, start_x + 0.94], [header_y-header_height, header_y-header_height], '#E0E0E0', linewidth=0.5)
            
            y_pos = header_y - header_height - 0.01
            row_height = 0.03
            
            # Dados da tabela
            for idx, t in enumerate(tests[-10:]):
                name = t.get('test_name', '-')
                ts = t.get('timestamp', '-')
                noise_data = t.get('noise_data', {})
                
                values = []
                max_time = ''
                if isinstance(noise_data, dict) and noise_data:
                    first_val = next(iter(noise_data.values()))
                    if isinstance(first_val, dict) and 'value' in first_val:
                        values = [v['value'] for v in noise_data.values()]
                        times = list(noise_data.keys())
                        max_idx = values.index(max(values))
                        max_time = times[max_idx]
                    else:
                        values = list(noise_data.values())
                
                if values:
                    avg_v = sum(values) / len(values)
                    min_v = min(values)
                    max_v = max(values)
                    severity = _calculate_severity(max_v, avg_v)
                else:
                    avg_v = min_v = max_v = 0
                    severity = '-'
                
                # Dados da linha
                row_data = [
                    '☐',  # checkbox vazio
                    name,
                    str(t.get('duration', 0)),
                    f"{avg_v:.1f}",
                    f"{min_v:.1f}",
                    f"{max_v:.1f}",
                    max_time,
                    ts,
                    severity
                ]
                
                # Linhas verticais
                for i in range(len(headers)):
                    x_line = start_x + sum(col_widths[:i])
                    ax.plot([x_line, x_line], [y_pos-row_height, y_pos], '#E0E0E0', linewidth=0.5)
                
                # Desenha linha
                for i, (data, width) in enumerate(zip(row_data, col_widths)):
                    x_pos = start_x + sum(col_widths[:i]) + 0.005
                    
                    # Alinhamento
                    if i in [2, 3, 4, 5]:  # colunas numéricas
                        ha = 'right'
                    else:
                        ha = 'left'
                    
                    # Cor da severidade
                    if i == 8:  # Coluna de severidade
                        if severity == 'Baixa':
                            text_color = 'green'
                        elif severity == 'Média':
                            text_color = 'orange'
                        elif severity == 'Alta':
                            text_color = 'red'
                        elif severity == 'Muito Alta':
                            text_color = 'darkred'
                        else:
                            text_color = 'black'
                    else:
                        text_color = 'black'
                    
                    ax.text(x_pos, y_pos-0.015, data, fontsize=8, ha=ha, va='center', color=text_color)
                
                y_pos -= row_height
                
                if y_pos < 0.05:
                    break
        
        pdf.savefig(fig); plt.close(fig)

        # Resumo analítico
        fig = plt.figure(figsize=(8.27, 11.69))
        fig.suptitle('Análise dos Resultados', fontsize=14, y=0.97)
        ax = fig.add_subplot(111)
        ax.axis('off')
        
        analysis_text = _generate_analysis_summary(tests)
        ax.text(0.05, 0.95, analysis_text, fontsize=10, va='top', ha='left', 
               family='monospace', wrap=True)
        
        pdf.savefig(fig); plt.close(fig)

        # Gráficos por teste (proporção corrigida)
        for t in tests[-8:]:  # reduzido para 8 gráficos
            fig = plt.figure(figsize=(8.27, 6.0))  # Proporção mais adequada
            name = t.get('test_name', f"Teste {t.get('id','')}")
            fig.suptitle(f"Noise Check - {name}", fontsize=12, y=0.95)
            ax = fig.add_subplot(111)
            ax.set_xlabel('Tempo (s)', fontsize=10)
            ax.set_ylabel('Intensidade (dBm)', fontsize=10)
            
            noise_data = t.get('noise_data', {})
            if isinstance(noise_data, dict) and noise_data:
                times = [float(k) for k in noise_data.keys()]
                first_val = next(iter(noise_data.values()))
                if isinstance(first_val, dict) and 'value' in first_val:
                    values = [v['value'] for v in noise_data.values()]
                else:
                    values = list(noise_data.values())
                
                if times and values:
                    # Linha marrom avermelhada igual ao print
                    ax.plot(times, values, '-', marker='o', markersize=3, linewidth=1.2, 
                           color='#8B4513', alpha=0.8)  # cor marrom avermelhada
                    
                    # Grade tracejada igual ao print
                    ax.grid(True, linestyle='--', linewidth=0.5, alpha=0.7, color='gray')
                    
                    # Eixos iguais ao print
                    ax.set_xlim(0, max(times))
                    ax.set_ylim(-80, -40)  # faixa padrão de -80 a -40 dBm
                    
                    # Legenda igual ao print
                    ax.legend([name], loc='upper right', fontsize=10)
                    
                else:
                    ax.text(0.5, 0.5, 'Sem dados para plotar', ha='center', va='center')
            else:
                ax.text(0.5, 0.5, 'Sem dados para plotar', ha='center', va='center')
            
            pdf.savefig(fig); plt.close(fig)

    return output_pdf_path


if __name__ == '__main__':
    root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))
    out = os.path.join(root, 'docs', 'Report.pdf')
    path = generate_noise_report(out)
    fc_log("noise_pdf_report", f'Relatório gerado em: {path}')


