#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Gerador de gráficos para Antenna Check usando matplotlib
Baseado no image_chart_generator.py do Noise Check
"""
import os
import base64
import io
import matplotlib.pyplot as plt
import matplotlib
matplotlib.use('Agg')  # Backend sem GUI

# Importa sistema de tradução
try:
    from .i18n import t
except ImportError:
    from i18n import t

def _create_continuous_segments(frequencies, return_loss_values, excluded_ranges=None):
    """
    Cria segmentos contínuos de pontos, separando onde há gaps de frequência
    Baseado na lógica do _create_continuous_segments do antenna_module.py
    
    Args:
        frequencies: Lista de frequências
        return_loss_values: Lista de valores correspondentes
        
    Returns:
        Lista de tuplas (freq_segment, value_segment) para cada segmento contínuo
    """
    if not frequencies or not return_loss_values:
        return []
    
    # Ordena os pontos por frequência
    sorted_points = sorted(zip(frequencies, return_loss_values))
    freq_sorted = [point[0] for point in sorted_points]
    value_sorted = [point[1] for point in sorted_points]
    
    segments = []
    current_segment_freq = [freq_sorted[0]]
    current_segment_value = [value_sorted[0]]
    
    # Gap threshold básico (usado quando não recebemos os gaps explicitamente)
    gap_threshold = 8.0
    
    excluded_ranges = excluded_ranges or []
    for i in range(1, len(freq_sorted)):
        prev_freq = freq_sorted[i-1]
        curr_freq = freq_sorted[i]
        
        # Se atravessa um gap conhecido, quebra o segmento
        crossed_known_gap = False
        for excl_min, excl_max in excluded_ranges:
            if (prev_freq <= excl_min and curr_freq >= excl_max) or (prev_freq < excl_max <= curr_freq) or (prev_freq <= excl_min < curr_freq):
                crossed_known_gap = True
                break
        
        # Se há gap significativo OU cruzou um gap conhecido, inicia novo segmento
        if crossed_known_gap or (curr_freq - prev_freq) >= gap_threshold:
            # Salva o segmento atual
            if len(current_segment_freq) > 0:
                segments.append((current_segment_freq.copy(), current_segment_value.copy()))
            
            # Inicia novo segmento
            current_segment_freq = [curr_freq]
            current_segment_value = [value_sorted[i]]
        else:
            # Adiciona ao segmento atual
            current_segment_freq.append(curr_freq)
            current_segment_value.append(value_sorted[i])
    
    # Adiciona o último segmento
    if len(current_segment_freq) > 0:
        segments.append((current_segment_freq, current_segment_value))
    
    return segments

def _calculate_vswr_from_powers(p_inc_dbm, p_ref_dbm):
    """Calcula VSWR a partir das potências incidente e refletida (igual ao módulo)"""
    try:
        # Converte para float para evitar problemas de tipo
        p_inc = float(p_inc_dbm)
        p_ref = float(p_ref_dbm)
        
        # Calcula o Return Loss em dB (deve ser negativo)
        # Return Loss = -20 × log₁₀(|Γ|) onde |Γ| é o coeficiente de reflexão
        if p_ref >= p_inc:
            return 3.5  # VSWR alto quando potência refletida >= incidente
        
        # Calcula o coeficiente de reflexão a partir das potências
        # |Γ|² = P_ref / P_inc
        # Para potências em dBm, converte para mW primeiro
        p_inc_mw = 10**(p_inc / 10)
        p_ref_mw = 10**(p_ref / 10)
        
        reflection_coeff_squared = p_ref_mw / p_inc_mw
        reflection_coeff = reflection_coeff_squared ** 0.5
        
        # Calcula VSWR: VSWR = (1 + |Γ|) / (1 - |Γ|)
        if abs(reflection_coeff - 1.0) < 1e-10:
            return 3.5  # VSWR alto quando |Γ| ≈ 1
        else:
            vswr = (1 + reflection_coeff) / (1 - reflection_coeff)
            # Limita VSWR a um valor máximo plotável
            return min(vswr, 3.5)
            
    except Exception as e:
        print(f"⚠️ Erro no cálculo de VSWR: {e}")
        return 3.5

def generate_antenna_chart_image(frequencies, return_loss_values, test_name, plot_type="Return Loss", test_power=25, excluded_ranges=None):
    """
    Gera uma imagem do gráfico de antena usando matplotlib
    
    Args:
        frequencies: Lista de frequências
        return_loss_values: Lista de valores de return loss
        test_name: Nome do teste
        plot_type: Tipo de plot ("Return Loss", "VSWR", "Impedance")
        
    Returns:
        String base64 da imagem PNG
    """
    if not frequencies or not return_loss_values or len(frequencies) != len(return_loss_values):
        return None
    
    # Configuração da figura - formato fixo que cabe no PDF
    plt.figure(figsize=(12, 4))  # Dimensões fixas que cabem no PDF
    plt.style.use('default')
    
    # Converte dados se necessário baseado no tipo de plot
    if plot_type == "VSWR" or "VSWR" in plot_type:
        # Converte usando potências (igual ao módulo)
        # Os dados armazenados são potências refletidas, não Return Loss
        # Usa potência do teste como potência incidente
        vswr_values = [_calculate_vswr_from_powers(test_power, rl) for rl in return_loss_values]
        plot_values = vswr_values
        print(f"🔍 Gráfico {test_name} (VSWR): {len(frequencies)} pontos convertidos de potências")
    else:
        plot_values = return_loss_values
        print(f"🔍 Gráfico {test_name} (Return Loss): {len(frequencies)} pontos")
    
    # Cria segmentos separados (igual ao módulo)
    segments = _create_continuous_segments(frequencies, plot_values, excluded_ranges)
    print(f"🔍 Gráfico {test_name}: {len(frequencies)} pontos, {len(segments)} segmentos")
    
    # Plota cada segmento separadamente
    for i, (seg_freqs, seg_values) in enumerate(segments):
        print(f"   Segmento {i+1}: {len(seg_freqs)} pontos, faixa {min(seg_freqs):.1f}-{max(seg_freqs):.1f} MHz")
        if len(seg_freqs) >= 1:  # Plota mesmo com 1 ponto
            # Usa label apenas no primeiro segmento
            label = test_name if i == 0 else None
            if len(seg_freqs) == 1:
                # Para pontos únicos, plota apenas o marcador
                plt.plot(seg_freqs, seg_values, 'o', color='#1f77b4', markersize=4, 
                         markerfacecolor='#1f77b4', markeredgecolor='white', markeredgewidth=1, label=label)
            else:
                # Para múltiplos pontos, plota linha conectada
                plt.plot(seg_freqs, seg_values, 'o-', color='#1f77b4', linewidth=2, markersize=4, 
                         markerfacecolor='#1f77b4', markeredgecolor='white', markeredgewidth=1, label=label)
    
    # Configurações do gráfico
    plt.title(f'{t("pdf.antenna_chart_title")} - {test_name}', fontsize=14, fontweight='bold', color='#2c3e50')
    plt.xlabel(t('antenna.x_axis_label'), fontsize=12)
    
    # Configura o eixo Y baseado no tipo de plot
    if plot_type == "VSWR" or "VSWR" in plot_type:
        plt.ylabel(t('antenna.y_axis_vswr'), fontsize=12)
    elif "Return Loss" in plot_type:
        plt.ylabel(t('antenna.y_axis_return_loss'), fontsize=12)  # Usa dBm como no módulo
    else:  # Impedance
        plt.ylabel(t('antenna.y_axis_impedance'), fontsize=12)
    
    # Configurações dos eixos
    plt.grid(True, alpha=0.3, linestyle='--')
    
    # Aplica a mesma lógica do "Fit to Data" do Antenna Check
    if frequencies and plot_values:
        x_min, x_max = min(frequencies), max(frequencies)
        y_min, y_max = min(plot_values), max(plot_values)
        unit = "VSWR" if (plot_type == "VSWR" or "VSWR" in plot_type) else "dBm"
        print(f"🔍 Limites dos dados: X({x_min:.1f}-{x_max:.1f} MHz), Y({y_min:.1f}-{y_max:.1f} {unit})")
        
        # Calcula margens inteligentes (mesma lógica do _fit_to_data)
        x_range = x_max - x_min
        y_range = y_max - y_min
        
        # Margem para eixo X
        if x_range < 10:  # Menos de 10 MHz de range
            x_margin = max(0.5, x_range * 0.1)  # pelo menos 0.5 MHz
        else:
            x_margin = x_range * 0.05  # 5% para ranges maiores
            
        # Margem para eixo Y
        if y_range < 5:  # Menos de 5 dB de range
            y_margin = 0.5  # 0.5 dB de margem
        else:
            y_margin = y_range * 0.05  # 5% de margem
        
        # Define novos limites com margem
        new_x_min = max(0, x_min - x_margin)
        new_x_max = x_max + x_margin
        new_y_min = y_min - y_margin
        new_y_max = y_max + y_margin
        
        # Para VSWR, força início em 1.0 (igual ao módulo)
        if plot_type == "VSWR" or "VSWR" in plot_type:
            new_y_min = 1.0
            # Garante um topo minimamente acima de 1.0 para visualização
            new_y_max = max(new_y_max, 1.1)
        
        # Para Return Loss, não força limite superior (deixa os dados determinarem)
        # Remove a limitação de 0 dB para mostrar todos os dados

        plt.xlim(new_x_min, new_x_max)
        plt.ylim(new_y_min, new_y_max)
        print(f"🔍 Limites do gráfico: X({new_x_min:.1f}-{new_x_max:.1f} MHz), Y({new_y_min:.1f}-{new_y_max:.1f} {unit})")
    else:
        # Fallback para valores padrão se não houver dados
        if plot_type == "VSWR" or "VSWR" in plot_type:
            plt.ylim(1.0, 3.5)  # Faixa padrão de VSWR (igual ao módulo)
        elif "Return Loss" in plot_type:
            plt.ylim(-10, 5)  # Faixa padrão de return loss (igual ao módulo)
        else:  # Impedance
            plt.ylim(0, 200)  # Faixa típica de impedância

        if frequencies:
            plt.xlim(min(frequencies), max(frequencies))
    
    # Configurações de layout - garante que tudo seja capturado
    plt.tight_layout(pad=1.5)
    
    # Salva como string base64
    buffer = io.BytesIO()
    plt.savefig(buffer, format='png', dpi=150, facecolor='white', edgecolor='none', pad_inches=0.2)
    buffer.seek(0)
    
    # Converte para base64
    image_base64 = base64.b64encode(buffer.getvalue()).decode()
    buffer.close()
    plt.close()
    
    return image_base64

def generate_all_antenna_charts(tests, plot_type="Return Loss"):
    """
    Gera todas as imagens dos gráficos de antena
    
    Args:
        tests: Lista de testes de antena
        plot_type: Tipo de plotagem ("Return Loss" ou "VSWR")
        
    Returns:
        Lista de tuplas (test_name, image_base64)
    """
    charts = []
    
    for test in tests:
        test_name = test.get('description', test.get('test_name', f"{t('threshold.test')} sem nome"))
        test_power = test.get('power', 25)  # Potência do teste
        
        # Extrai dados do teste
        frequencies = []
        return_loss_values = []
        
        # Processa os dados de frequência e return loss
        data_points = test.get('data_points', {})
        if isinstance(data_points, dict):
            # Ordena por frequência
            sorted_items = sorted(data_points.items(), key=lambda x: float(x[0]))
            for freq_str, return_loss in sorted_items:
                try:
                    freq = float(freq_str)
                    return_loss_val = float(return_loss)
                    
                    frequencies.append(freq)
                    return_loss_values.append(return_loss_val)
                except (ValueError, TypeError):
                    continue
        
        # Gera o gráfico se houver dados válidos
        if frequencies and return_loss_values:
            image_base64 = generate_antenna_chart_image(frequencies, return_loss_values, test_name, plot_type, test_power)
            if image_base64:
                charts.append((test_name, image_base64))
    
    return charts

if __name__ == '__main__':
    # Teste do gerador
    test_data = [
        {
            'test_name': 'Teste Antena 1',
            'plot_type': 'Return Loss',
            'frequency_data': {
                '860': {'return_loss': -15.2},
                '870': {'return_loss': -18.5},
                '880': {'return_loss': -12.8},
                '890': {'return_loss': -20.1},
                '900': {'return_loss': -16.7}
            }
        }
    ]
    
    charts = generate_all_antenna_charts(test_data)
    print(f"Gerados {len(charts)} gráficos de teste")
