"""
Módulo de Correção de Dados RFID
Usa a nova tabela de correção em formato CSV
"""
import pandas as pd
import numpy as np
from typing import Dict, Optional

# Carrega a tabela de correção
def load_correction_table() -> pd.DataFrame:
    """
    Carrega a tabela de correção do arquivo CSV
    
    Returns:
        DataFrame com frequências e fatores de correção
    """
    try:
        df = pd.read_csv('Tabela de Correção.txt')
        # Silencia mensagem para reduzir poluição
        return df
    except Exception as e:
        print(f"❌ Erro ao carregar tabela de correção: {e}")
        return pd.DataFrame()

# Variável global para armazenar a tabela
_correction_table = None

def get_correction_table() -> pd.DataFrame:
    """
    Retorna a tabela de correção (carrega se necessário)
    
    Returns:
        DataFrame com a tabela de correção
    """
    global _correction_table
    if _correction_table is None:
        _correction_table = load_correction_table()
    return _correction_table

def get_correction_factor(frequency_mhz: float) -> float:
    """
    Obtém o fator de correção para uma frequência específica
    
    Args:
        frequency_mhz: Frequência em MHz
        
    Returns:
        Fator de correção em dB
    """
    df = get_correction_table()
    if df.empty:
        return 0.0
    
    # Busca a frequência mais próxima
    freq_column = df.iloc[:, 0]
    correction_column = df.iloc[:, 1]
    
    # Se a frequência exata existe
    if frequency_mhz in freq_column.values:
        return correction_column[freq_column == frequency_mhz].iloc[0]
    
    # Interpolação linear para frequências intermediárias
    freq_values = freq_column.values
    correction_values = correction_column.values
    
    # Encontra os índices para interpolação
    if frequency_mhz < freq_values.min():
        return correction_values[0]
    elif frequency_mhz > freq_values.max():
        return correction_values[-1]
    else:
        # Encontra os dois pontos mais próximos
        idx = np.searchsorted(freq_values, frequency_mhz)
        if idx == 0:
            return correction_values[0]
        elif idx == len(freq_values):
            return correction_values[-1]
        else:
            # Interpolação linear
            x1, x2 = freq_values[idx-1], freq_values[idx]
            y1, y2 = correction_values[idx-1], correction_values[idx]
            return y1 + (y2 - y1) * (frequency_mhz - x1) / (x2 - x1)

def calculate_rcs(freq_mhz: float, distance: float, irradiated_power: float, backscatter: float, antenna_gain_db: float = 6.0) -> float:
    """
    Calcula o Radar Cross Section (RCS) usando a equação do radar
    
    Args:
        freq_mhz: Frequência em MHz
        distance: Distância em metros
        irradiated_power: Potência irradiada em dBm
        backscatter: Potência de backscatter em dBm
        antenna_gain_db: Ganho das antenas em dB (padrão: 6.0 dB)
        
    Returns:
        RCS em dBm² (decibéis relativos a 1 m²)
    """
    try:
        # Converte dBm para Watts
        pt_watts = 10**((irradiated_power - 30) / 10)  # dBm para Watts
        pr_watts = 10**((backscatter - 30) / 10)       # dBm para Watts
        
        # Calcula comprimento de onda
        c = 3e8  # Velocidade da luz em m/s
        freq_hz = freq_mhz * 1e6
        wavelength = c / freq_hz
        
        # Ganho das antenas (assumindo ganho igual para transmissão e recepção)
        gt = 10**(antenna_gain_db / 10)
        gr = 10**(antenna_gain_db / 10)
        
        # Fórmula do RCS: RCS = (4π)³ × R⁴ × Pr / (Pt × Gt × Gr × λ²)
        rcs_m2 = ((4 * 3.14159)**3 * (distance**4) * pr_watts) / (pt_watts * gt * gr * (wavelength**2))
        
        # Converte para dBm²: RCS_dBm2 = 10 * log10(RCS_m2)
        if rcs_m2 > 0:
            rcs_dbm2 = 10 * np.log10(rcs_m2)
        else:
            rcs_dbm2 = -999.0  # Valor para RCS zero ou inválido
        
        return rcs_dbm2
        
    except Exception as e:
        print(f"⚠️ Erro no cálculo do RCS: {e}")
        return -999.0

def apply_corrections_to_result(result: Dict, attenuator: float = 0.0, distance: float = 1.0) -> Dict:
    """
    Aplica correções aos resultados de teste
    
    A correção é aplicada ao Module Power para calcular o Irradiated Power.
    O RSSI permanece inalterado.
    
    Args:
        result: Dicionário com resultados do teste
        attenuator: Valor do atenuador em dB
        distance: Distância em metros
        
    Returns:
        Dicionário com resultados corrigidos
    """
    if not result:
        return result
    
    freq_mhz = result.get('freq_mhz', 0)
    # CORREÇÃO: Preserva dados originais do threshold
    module_power = result.get('threshold_power', result.get('module_power', 0))
    rssi = result.get('threshold_rssi', result.get('rssi', 0))
    
    # Obtém fator de correção da tabela
    correction_factor = get_correction_factor(freq_mhz)
    
    # Cálculos baseados nas fórmulas corretas
    irradiated_power = module_power - attenuator + correction_factor
    backscatter = rssi + (2 * attenuator)  # Nova fórmula: Backscatter = RSSI + (2 × Atenuador)
    
    # Power on Tag calculations
    # Calcula path loss baseado na frequência e distância
    wavelength = 300 / freq_mhz  # Comprimento de onda em metros
    path_loss = 20 * np.log10(4 * np.pi * distance / wavelength)
    
    power_on_tag_forward = irradiated_power - path_loss
    power_on_tag_reversed = backscatter + path_loss
    
    # Conversion Loss
    conversion_loss = power_on_tag_reversed - power_on_tag_forward
    
    # FCC Link calculations
    wavelength = 300 / freq_mhz  # Comprimento de onda em metros
    fcc_power = 36.02  # dBm (FCC limit)
    min_tag_power = -10  # dBm
    reader_sensitivity = -82  # dBm
    
    # Max FCC Link Forward
    max_path_loss_forward = fcc_power - power_on_tag_forward
    max_distance_forward = (10 ** (max_path_loss_forward / 20)) * wavelength / (4 * 3.14159)
    
    # Max FCC Link Reversed
    max_path_loss_reversed = power_on_tag_reversed - reader_sensitivity
    max_distance_reversed = (10 ** (max_path_loss_reversed / 20)) * wavelength / (4 * 3.14159)
    
    # Cálculo do RCS (Radar Cross Section)
    rcs = calculate_rcs(freq_mhz, distance, irradiated_power, backscatter)
    
    # Retorna resultado com todas as correções
    return {
        'freq_mhz': freq_mhz,
        # CORREÇÃO: Preserva dados originais do threshold
        'threshold_power': result.get('threshold_power', module_power),  # Dados originais
        'threshold_rssi': result.get('threshold_rssi', rssi),  # Dados originais
        'module_power': module_power,  # Module Power original
        'rssi': rssi,  # RSSI original (não corrigido)
        'irradiated_power': irradiated_power,  # Calculado com Module Power corrigido
        'backscatter': backscatter,
        'power_on_tag_forward': power_on_tag_forward,
        'power_on_tag_reversed': power_on_tag_reversed,
        'conversion_loss': conversion_loss,
        'max_fcc_link_forward': max_distance_forward,
        'max_fcc_link_reversed': max_distance_reversed,
        'rcs': rcs,  # NOVO: Radar Cross Section
        'correction_factor': correction_factor,  # Fator aplicado ao Module Power
        'attenuator': attenuator,
        'distance': distance
    }

def print_correction_info():
    """
    Imprime informações sobre a tabela de correção
    """
    df = get_correction_table()
    if not df.empty:
        print(f"📊 TABELA DE CORREÇÃO:")
        print(f"   Pontos: {len(df)}")
        print(f"   Faixa: {df.iloc[:, 0].min():.0f} - {df.iloc[:, 0].max():.0f} MHz")
        print(f"   Correção: {df.iloc[:, 1].min():.2f} a {df.iloc[:, 1].max():.2f} dB")
        print(f"   Média: {df.iloc[:, 1].mean():.2f} dB")
    else:
        print("❌ Tabela de correção não disponível")

# Teste do módulo
if __name__ == "__main__":
    print("🧪 TESTE DO MÓDULO DE CORREÇÃO")
    print("=" * 40)
    
    print_correction_info()
    
    # Testa algumas frequências
    test_freqs = [800, 850, 900, 950, 1000]
    for freq in test_freqs:
        correction = get_correction_factor(freq)
        print(f"   {freq:4.0f} MHz: {correction:6.2f} dB")
    
    # Testa aplicação de correção
    test_result = {
        'freq_mhz': 850,
        'module_power': 20.0,
        'rssi': -45.0
    }
    
    corrected = apply_corrections_to_result(test_result, attenuator=2.0, distance=1.0)
    print(f"\n📊 EXEMPLO DE CORREÇÃO:")
    print(f"   Frequência: {corrected['freq_mhz']} MHz")
    print(f"   Module Power Original: {test_result['module_power']} dBm")
    print(f"   Module Power Corrigido: {test_result['module_power'] + corrected['correction_factor']} dBm")
    print(f"   Irradiated Power: {corrected['irradiated_power']} dBm")
    print(f"   RSSI: {corrected['rssi']} dB (não corrigido)")
    print(f"   Backscatter: {corrected['backscatter']} dBm")
    print(f"   RCS: {corrected['rcs']:.1f} dBm²")
    print(f"   Fator Aplicado: {corrected['correction_factor']} dB")
