"""
Modelo e persistência do perfil de calibração (CalibrationProfile).
Formato JSON compatível com FastChecker II 3.0; medições FC II sem calibração são tratadas como "sem calibração".
"""
import json
import os
from datetime import datetime
from typing import Any, Dict, List, Optional

from .app_console import fc_log
# Chave que indica que um arquivo de medição foi feito sob calibração (FC II 3.0)
CALIBRATION_ACTIVE_KEY = "calibration_profile_id"
# Chave que indica ausência de calibração (ex.: medição importada do FC II)
NO_CALIBRATION_FLAG = "no_calibration"


def build_profile(
    corrections: List[Dict[str, float]],
    freq_min_mhz: int,
    freq_max_mhz: int,
    distance_m: float,
    attenuator_db: float = 0.0,
    antenna_info: Optional[str] = None,
    environment_info: Optional[str] = None,
    tag_epc: str = "000000000000000588937124",
    freq_step_mhz: int = 1,
) -> Dict[str, Any]:
    """
    Monta um dicionário de perfil de calibração para salvar em JSON.
    corrections: lista de {"freq_mhz", "correction_forward_dbm", "correction_reverse_dbm"}
    """
    return {
        "version": 1,
        "tag_epc": tag_epc,
        "freq_min_mhz": freq_min_mhz,
        "freq_max_mhz": freq_max_mhz,
        "freq_step_mhz": freq_step_mhz,
        "distance_m": distance_m,
        "attenuator_db": attenuator_db,
        "antenna_info": antenna_info or "",
        "environment_info": environment_info or "",
        "created_utc": datetime.utcnow().isoformat() + "Z",
        "corrections": corrections,
    }


def save_profile(profile: Dict[str, Any], path: str) -> bool:
    """Salva o perfil em arquivo JSON."""
    try:
        with open(path, "w", encoding="utf-8") as f:
            json.dump(profile, f, indent=2, ensure_ascii=False)
        return True
    except Exception as e:
        fc_log("calibration_profile", f"[Calibration] Erro ao salvar perfil: {e}")
        return False


def load_profile(path: str) -> Optional[Dict[str, Any]]:
    """Carrega perfil de calibração de um arquivo JSON."""
    try:
        if not os.path.isfile(path):
            return None
        with open(path, "r", encoding="utf-8") as f:
            return json.load(f)
    except Exception as e:
        fc_log("calibration_profile", f"[Calibration] Erro ao carregar perfil: {e}")
        return None


def get_correction_at_freq(profile: Dict[str, Any], freq_mhz: float) -> tuple:
    """
    Retorna (correction_forward_dbm, correction_reverse_dbm) para a frequência.
    Interpola linearmente entre os pontos do perfil.
    """
    corrections = profile.get("corrections", [])
    if not corrections:
        return (0.0, 0.0)
    freqs = [p["freq_mhz"] for p in corrections]
    fwd = [p["correction_forward_dbm"] for p in corrections]
    rev = [p["correction_reverse_dbm"] for p in corrections]
    if freq_mhz <= freqs[0]:
        return (fwd[0], rev[0])
    if freq_mhz >= freqs[-1]:
        return (fwd[-1], rev[-1])
    for i in range(len(freqs) - 1):
        if freqs[i] <= freq_mhz <= freqs[i + 1]:
            t = (freq_mhz - freqs[i]) / (freqs[i + 1] - freqs[i]) if freqs[i + 1] != freqs[i] else 0
            return (
                fwd[i] + t * (fwd[i + 1] - fwd[i]),
                rev[i] + t * (rev[i + 1] - rev[i]),
            )
    return (fwd[-1], rev[-1])
