#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Gerador de PDF para o módulo Simulador
Baseado nas imagens fornecidas pelo usuário
"""

import os
import json
from datetime import datetime
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import inch, cm
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, Image, PageBreak
from reportlab.lib import colors
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_RIGHT
from reportlab.graphics.shapes import Drawing, Rect, Line
from reportlab.graphics.charts.linecharts import HorizontalLineChart
from reportlab.graphics.charts.textlabels import Label
from reportlab.graphics import renderPDF
from .pdf_pagination_utils import create_smart_pagination, get_height_estimate
from .i18n import get_translator, t
from .embedded_images import get_risk_image_bytes, get_logo_image_bytes
import tempfile
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import numpy as np

class SimuladorPDFGenerator:
    def __init__(self):
        self.styles = getSampleStyleSheet()
        self._setup_custom_styles()
    
    def _setup_custom_styles(self):
        """Configura estilos personalizados para o relatório"""
        # Título principal
        self.title_style = ParagraphStyle(
            'CustomTitle',
            parent=self.styles['Heading1'],
            fontSize=24,
            spaceAfter=30,
            alignment=TA_CENTER,
            textColor=colors.HexColor('#2c3e50'),
            fontName='Helvetica-Bold'
        )
        
        # Subtítulos
        self.heading_style = ParagraphStyle(
            'CustomHeading',
            parent=self.styles['Heading2'],
            fontSize=16,
            spaceAfter=12,
            textColor=colors.HexColor('#2c3e50'),
            fontName='Helvetica-Bold'
        )
        
        # Texto normal
        self.normal_style = ParagraphStyle(
            'CustomNormal',
            parent=self.styles['Normal'],
            fontSize=10,
            spaceAfter=6,
            fontName='Helvetica'
        )
        
        # Tabela de cabeçalho
        self.table_header_style = ParagraphStyle(
            'TableHeader',
            parent=self.styles['Normal'],
            fontSize=10,
            textColor=colors.white,
            fontName='Helvetica-Bold',
            alignment=TA_CENTER
        )

    def generate_pdf_report(self, simulador_data, output_path):
        """
        Gera o relatório PDF completo do simulador
        
        Args:
            simulador_data: Dados do simulador (slot_data, parâmetros globais, etc.)
            output_path: Caminho onde salvar o PDF
        """
        temp_files = []  # Lista para armazenar arquivos temporários
        try:
            # Cria o documento PDF
            doc = SimpleDocTemplate(
                output_path, 
                pagesize=A4,
                rightMargin=2*cm, 
                leftMargin=2*cm, 
                topMargin=2*cm, 
                bottomMargin=2*cm
            )
            
            # Constrói o conteúdo com paginação inteligente
            pagination = create_smart_pagination()
            
            # Página 1: Cabeçalho e informações do sistema
            header_elements = self._create_header_page(simulador_data)
            for element in header_elements:
                pagination.add_element(element)
            
            # Página 2: Tabela de risco e gráficos
            pagination.add_with_break_if_needed(Paragraph("Tabela de Risco", self.heading_style), get_height_estimate('heading'), force_break=True)
            risk_elements = self._create_risk_and_charts_page(simulador_data, temp_files)
            for element in risk_elements:
                pagination.add_element(element)
            
            # Páginas 3-4: Gráficos individuais dos slots
            chart_elements = self._create_individual_charts_pages(simulador_data, temp_files)
            for element in chart_elements:
                pagination.add_element(element)
            
            # Página final: Rodapé com informações adicionais
            footer_elements = self._create_footer_page()
            for element in footer_elements:
                pagination.add_element(element)
            
            story = pagination.get_story()
            
            # Gera o PDF
            doc.build(story)
            print(f"✅ Relatório PDF do Simulator gerado: {output_path}")
            return True
            
        except Exception as e:
            print(f"❌ Erro ao gerar PDF do Simulator: {e}")
            return False
        finally:
            # Remove arquivos temporários
            for temp_file in temp_files:
                try:
                    if os.path.exists(temp_file):
                        os.remove(temp_file)
                except:
                    pass

    def _create_header_page(self, simulador_data):
        """Cria a primeira página com cabeçalho e informações do sistema"""
        story = []
        
        # Logo Fasttag - carrega do módulo embedded_images
        try:
            logo_bytes = get_logo_image_bytes()
            
            if logo_bytes:
                # Cria arquivo temporário com o logo
                with tempfile.NamedTemporaryFile(suffix='.png', delete=False) as tmp_file:
                    tmp_file.write(logo_bytes)
                    tmp_path = tmp_file.name
                
                try:
                    # Mantém proporção circular (1:1) - logo redondo
                    logo_size = 1.5*inch
                    logo_img = Image(tmp_path, width=logo_size, height=logo_size)
                    story.append(logo_img)
                    story.append(Spacer(1, 10))
                    print("✅ Logo Fasttag adicionado ao PDF do Simulator (embutido)")
                finally:
                    # Remove o arquivo temporário após o PDF ser gerado
                    try:
                        os.unlink(tmp_path)
                    except:
                        pass
            else:
                print("⚠️ Logo Fasttag não encontrado")
        except Exception as e:
            print(f"⚠️ Erro ao adicionar logo: {e}")
        
        # Título
        story.append(Paragraph("FASTTAG", self.title_style))
        story.append(Spacer(1, 5))
        story.append(Paragraph("Relatório do Simulator", self.title_style))
        story.append(Spacer(1, 30))
        
        # Informações do sistema
        story.append(Paragraph("Informações do Sistema", self.heading_style))
        
        # Importa configuração de versão centralizada
        try:
            from .version_config import get_software_info
            software_info = get_software_info()
            software_version = software_info['software']
        except ImportError:
            software_version = "2.0.0"
        
        # Formata data conforme idioma
        translator = get_translator()
        if translator.get_language() == 'en':
            generated_at = datetime.now().strftime("%m/%d/%y %I:%M:%S %p")
        else:
            generated_at = datetime.now().strftime("%d/%m/%Y %H:%M:%S")
        
        system_info = [
            ["Software:", software_version],
            ["Hardware:", "v7.0"],
            ["Firmware:", "v1.3.5"],
            ["Número de Série:", "N/A"],
            ["Licença:", "Modo Browser"],
            [t('pdf.generated_at'), generated_at]
        ]
        
        system_table = Table(system_info, colWidths=[3*cm, 4*cm])
        system_table.setStyle(TableStyle([
            ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
            ('FONTNAME', (0, 0), (0, -1), 'Helvetica-Bold'),
            ('FONTNAME', (1, 0), (1, -1), 'Helvetica'),
            ('FONTSIZE', (0, 0), (-1, -1), 10),
            ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
            ('LEFTPADDING', (0, 0), (-1, -1), 6),
            ('RIGHTPADDING', (0, 0), (-1, -1), 6),
            ('TOPPADDING', (0, 0), (-1, -1), 4),
            ('BOTTOMPADDING', (0, 0), (-1, -1), 4),
        ]))
        
        story.append(system_table)
        story.append(Spacer(1, 5))
        
        # Configuração do teste
        story.append(Paragraph("Configuração do Teste", self.heading_style))
        
        test_config = [
            ["Parâmetro", "Valor"],
            ["Potência Irradiada (dBm)", str(simulador_data.get('reader_power', 36))],
            ["Sensibilidade (dBm)", str(simulador_data.get('reader_sensitivity', -70))],
            ["Margem (dB)", str(simulador_data.get('margin_db', 3.0))]
        ]
        
        config_table = Table(test_config, colWidths=[6*cm, 4*cm])
        config_table.setStyle(TableStyle([
            ('BACKGROUND', (0, 0), (-1, 0), colors.HexColor('#1f4e79')),
            ('TEXTCOLOR', (0, 0), (-1, 0), colors.white),
            ('ALIGN', (0, 0), (-1, -1), 'CENTER'),
            ('FONTNAME', (0, 0), (-1, -1), 'Helvetica-Bold'),
            ('FONTSIZE', (0, 0), (-1, -1), 10),
            ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
            ('LEFTPADDING', (0, 0), (-1, -1), 6),
            ('RIGHTPADDING', (0, 0), (-1, -1), 6),
            ('TOPPADDING', (0, 0), (-1, -1), 6),
            ('BOTTOMPADDING', (0, 0), (-1, -1), 6),
            ('GRID', (0, 0), (-1, -1), 1, colors.black),
        ]))
        
        story.append(config_table)
        story.append(Spacer(1, 5))
        
        # Dados dos testes
        story.append(Paragraph("Dados dos Testes", self.heading_style))
        
        test_data = self._prepare_test_data_table(simulador_data)
        test_table = Table(test_data, colWidths=[2*cm, 4*cm, 2.5*cm, 2.5*cm, 2.5*cm, 2.5*cm, 2.5*cm])
        test_table.setStyle(TableStyle([
            ('BACKGROUND', (0, 0), (-1, 0), colors.HexColor('#1f4e79')),
            ('TEXTCOLOR', (0, 0), (-1, 0), colors.white),
            ('ALIGN', (0, 0), (-1, -1), 'CENTER'),
            ('FONTNAME', (0, 0), (-1, -1), 'Helvetica-Bold'),
            ('FONTSIZE', (0, 0), (-1, -1), 8),
            ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
            ('LEFTPADDING', (0, 0), (-1, -1), 3),
            ('RIGHTPADDING', (0, 0), (-1, -1), 3),
            ('TOPPADDING', (0, 0), (-1, -1), 3),
            ('BOTTOMPADDING', (0, 0), (-1, -1), 3),
            ('GRID', (0, 0), (-1, -1), 1, colors.black),
        ]))
        
        story.append(test_table)
        story.append(Spacer(1, 5))
        
        # Tabela de Risco (título)
        story.append(Paragraph("Tabela de Risco", self.heading_style))
        
        return story

    def _create_risk_and_charts_page(self, simulador_data, temp_files):
        """Cria a segunda página com tabelas de risco e gráficos"""
        story = []
        
        # Tabela de Risco - Usando imagem embutida (sem título duplicado)
        
        # Carrega a imagem de risco do módulo embedded_images
        try:
            translator = get_translator()
            current_lang = translator.get_language()
            risk_image_bytes = get_risk_image_bytes(current_lang)
            
            if risk_image_bytes:
                # Cria arquivo temporário com a imagem
                with tempfile.NamedTemporaryFile(suffix='.png', delete=False) as tmp_file:
                    tmp_file.write(risk_image_bytes)
                    tmp_path = tmp_file.name
                
                try:
                    # Adiciona a imagem de risco
                    story.append(Image(tmp_path, width=7*cm, height=8*cm))
                    story.append(Spacer(1, 5))
                    print(f"✅ Imagem de risco carregada (idioma: {current_lang})")
                finally:
                    # Remove o arquivo temporário após o PDF ser gerado
                    try:
                        os.unlink(tmp_path)
                    except:
                        pass
            else:
                # Fallback para texto se a imagem não for carregada
                story.append(Paragraph("Imagem de risco não disponível", self.normal_style))
                story.append(Spacer(1, 5))
                print(f"❌ Imagem de risco não disponível")
        except Exception as e:
            print(f"❌ Erro ao carregar imagem de risco: {e}")
            # Fallback para tabela de texto se a imagem falhar
            story.append(Paragraph("Imagem de risco não disponível", self.normal_style))
            story.append(Spacer(1, 5))
        
        
        # Gráfico do Slot 1
        if simulador_data.get('slot_data') and simulador_data['slot_data'][0]:
            # Título do gráfico
            story.append(Paragraph("Gráficos dos Testes", self.heading_style))
            story.append(Spacer(1, 1))
            story.append(Paragraph("Slot 1: T1", self.heading_style))
            story.append(Spacer(1, 1))
            
            chart_path = self._create_frequency_chart(simulador_data['slot_data'][0], "Slot 1: T1")
            if chart_path and os.path.exists(chart_path):
                story.append(Image(chart_path, width=15*cm, height=8*cm))
                temp_files.append(chart_path)  # Adiciona à lista de arquivos temporários
        
        return story

    def _create_individual_charts_pages(self, simulador_data, temp_files):
        """Cria as páginas com gráficos individuais dos slots com paginação inteligente"""
        story = []
        
        slot_data = simulador_data.get('slot_data', [])
        
        # Página 1: Slots 2 e 3 (se existirem)
        if len(slot_data) > 1 and slot_data[1]:
            # Título do gráfico
            story.append(Paragraph("Slot 2: T10", self.heading_style))
            story.append(Spacer(1, 1))
            
            chart_path = self._create_frequency_chart(slot_data[1], "Slot 2: T10")
            if chart_path and os.path.exists(chart_path):
                story.append(Image(chart_path, width=15*cm, height=8*cm))
                temp_files.append(chart_path)
        
        # Slot 3 na mesma página (se existir)
        if len(slot_data) > 2 and slot_data[2]:
            # Título do gráfico
            story.append(Spacer(1, 1))
            story.append(Paragraph("Slot 3: Média de 10 testes", self.heading_style))
            story.append(Spacer(1, 1))
            
            chart_path = self._create_frequency_chart(slot_data[2], "Slot 3: Média de 10 testes")
            if chart_path and os.path.exists(chart_path):
                story.append(Image(chart_path, width=15*cm, height=8*cm))
                temp_files.append(chart_path)
        
        # Página 2: Slot 4 (se existir)
        if len(slot_data) > 3 and slot_data[3]:
            story.append(PageBreak())
            # Título do gráfico
            story.append(Paragraph("Slot 4: Limite Máximo de 10 testes", self.heading_style))
            story.append(Spacer(1, 1))
            
            chart_path = self._create_frequency_chart(slot_data[3], "Slot 4: Limite Máximo de 10 testes")
            if chart_path and os.path.exists(chart_path):
                story.append(Image(chart_path, width=15*cm, height=8*cm))
                temp_files.append(chart_path)
        
        return story

    def _create_frequency_chart(self, slot_data, title):
        """Cria gráfico de distância vs frequência para um slot"""
        try:
            if not slot_data or 'data' not in slot_data or slot_data['data'].empty:
                return None
            
            df = slot_data['data']
            
            # Cria figura com proporção adequada
            fig, ax = plt.subplots(figsize=(14, 8))
            
            # Dados para o gráfico
            frequency = df['Frequência'].values if hasattr(df['Frequência'], 'values') else df['Frequência']
            forward_link = df['Forward Link'].values if hasattr(df['Forward Link'], 'values') else df['Forward Link']
            reverse_link = df['Reverse Link'].values if hasattr(df['Reverse Link'], 'values') else df['Reverse Link']
            link_final = df['Link Final'].values if hasattr(df['Link Final'], 'values') else df['Link Final']
            link_final_margin_data = df.get('Link Final (Margem 3.0 dB)', link_final * 0.7)
            link_final_margin = link_final_margin_data.values if hasattr(link_final_margin_data, 'values') else link_final_margin_data
            
            # Plota as linhas
            ax.plot(frequency, forward_link, 'b-', linewidth=2, label='Forward Link')
            ax.plot(frequency, reverse_link, 'r-', linewidth=2, label='Reverse Link')
            ax.plot(frequency, link_final, 'g-', linewidth=2, label='Link Final')
            ax.plot(frequency, link_final_margin, 'g--', linewidth=2, label='Link Final (Margem 3.0 dB)')
            
            # Configurações do gráfico
            ax.set_xlabel('Frequência (MHz)', fontsize=10)
            ax.set_ylabel('Distância (m)', fontsize=10)
            ax.set_title(title, fontsize=12, fontweight='bold')
            ax.grid(True, alpha=0.3)
            ax.legend(loc='upper right', fontsize=9)
            
            # Define limites dos eixos - escala automática como "fit to graph"
            ax.set_xlim(800, 1000)
            
            # Calcula limites do Y baseado nos dados para ajuste automático
            all_values = np.concatenate([forward_link, reverse_link, link_final, link_final_margin])
            
            # Remove valores inválidos (NaN, inf, etc.)
            valid_values = all_values[np.isfinite(all_values)]
            
            if len(valid_values) > 0:
                y_min = np.min(valid_values)
                y_max = np.max(valid_values)
                
                # Adiciona margem de 5% acima e abaixo dos dados
                y_range = y_max - y_min
                margin = y_range * 0.05
                
                # Garante que o mínimo seja pelo menos 0
                y_min = max(0, y_min - margin)
                y_max = y_max + margin
                
                ax.set_ylim(y_min, y_max)
            else:
                # Fallback se não houver dados válidos
                ax.set_ylim(0, 16)
            
            # Adiciona faixas de frequência destacadas
            frequency_bands = [(860, 865), (870, 875), (900, 905), (915, 920), (925, 930)]
            for start, end in frequency_bands:
                ax.axvspan(start, end, alpha=0.2, color='lightblue')
            
            # Salva em arquivo temporário
            temp_path = tempfile.mktemp(suffix='.png')
            plt.tight_layout()
            plt.savefig(temp_path, dpi=300, bbox_inches='tight')
            plt.close()
            
            return temp_path
            
        except Exception as e:
            print(f"❌ Erro ao criar gráfico: {e}")
            return None

    def _prepare_test_data_table(self, simulador_data):
        """Prepara dados para a tabela de testes"""
        headers = ["Slot", "Nome do Teste", "Distância (m)", "Atenuador (dB)", "Forward Link (m)", "Reverse Link (m)", "Link Final (m)"]
        data = [headers]
        
        slot_data = simulador_data.get('slot_data', [])
        
        for i, slot in enumerate(slot_data):
            if slot and 'data' in slot and not slot['data'].empty:
                df = slot['data']
                test_name = slot.get('test_description', f'T{i+1}')
                distance = slot.get('params', {}).get('d_med', 'N/A')
                attenuator = slot.get('params', {}).get('atenuador', 'N/A')
                
                forward_max = f"{df['Forward Link'].max():.1f}" if 'Forward Link' in df.columns else "N/A"
                reverse_max = f"{df['Reverse Link'].max():.1f}" if 'Reverse Link' in df.columns else "N/A"
                link_final_max = f"{df['Link Final'].max():.1f}" if 'Link Final' in df.columns else "N/A"
                
                data.append([
                    f"Slot {i+1}",
                    test_name,
                    str(distance) if distance != 'N/A' else 'N/A',
                    str(attenuator) if attenuator != 'N/A' else 'N/A',
                    forward_max,
                    reverse_max,
                    link_final_max
                ])
            else:
                data.append([
                    f"Slot {i+1}",
                    "N/A",
                    "N/A",
                    "N/A",
                    "N/A",
                    "N/A",
                    "N/A"
                ])
        
        return data

    def _create_footer_page(self):
        """Cria página final com rodapé e informações adicionais"""
        story = []
        
        # Nova página para o rodapé
        story.append(PageBreak())
        story.append(Spacer(1, 30))
        
        # Título da seção
        story.append(Paragraph("Informações Adicionais", self.heading_style))
        story.append(Spacer(1, 20))
        
        # Texto do rodapé
        footer_text = """
        Este relatório foi gerado automaticamente pelo FastChecker II.<br/>
        Sistema de análise e teste RFID profissional.<br/>
        Para suporte técnico, consulte a documentação do sistema.
        """
        story.append(Paragraph(footer_text, self.normal_style))
        story.append(Spacer(1, 20))
        
        # Timestamp de geração - formata conforme idioma
        translator = get_translator()
        current_lang = translator.get_language()
        if current_lang == 'en':
            timestamp = datetime.now().strftime("%m/%d/%y at %I:%M:%S %p")
        else:
            timestamp = datetime.now().strftime("%d/%m/%Y às %H:%M:%S")
        story.append(Paragraph(f"<b>{t('pdf.document_generated_at')}</b> {timestamp}", self.normal_style))
        
        return story
