"""
AGRO PLAN MAPS - MOTOR PRINCIPAL COM ML INTEGRADO
Versão: 2.0 (ML Engine)
"""

import requests
import random
import time
import json
from datetime import datetime, timedelta
import pytz
from collections import deque

# Importa o Motor de ML
from kairos_ml_engine import KairosMLEngine

# --- BIBLIOTECAS VISUAIS (RICH) ---
try:
    from rich.console import Console
    from rich.table import Table
    from rich.panel import Panel
    from rich.layout import Layout
    from rich.live import Live
    from rich.text import Text
    from rich import box
    from rich.align import Align
except ImportError:
    print("Instalando biblioteca visual...")
    import os
    os.system('pip install rich')
    from rich.console import Console
    from rich.table import Table
    from rich.panel import Panel
    from rich.layout import Layout
    from rich.live import Live
    from rich.text import Text
    from rich import box
    from rich.align import Align

# --- 1. CONFIGURAÇÕES ---
SUPABASE_URL = "https://mhbappxhnlpurfqhxpwa.supabase.co"
SUPABASE_KEY = "sb_publishable_XgU3v47C8GjZO7E3RURXYA_abPUYDzD"
SUPABASE_ENDPOINT = f"{SUPABASE_URL}/rest/v1/leituras"

LAT, LON = -19.8654, -47.9876
console = Console()

# --- 2. INTEGRAÇÕES ---
def get_clima():
    """
    Versão robusta que busca a previsão estendida (7 dias)
    """
    try:
        url = f"https://api.open-meteo.com/v1/forecast?latitude={LAT}&longitude={LON}&current=wind_speed_10m&daily=precipitation_sum,temperature_2m_max&timezone=America/Sao_Paulo"
        r = requests.get(url, timeout=5)

        if r.status_code != 200:
            return {"chuva": 0.0, "vento": 0.0, "grafico": [], "erro": True}

        d = r.json()
        chuva_hoje = float(d['daily']['precipitation_sum'][0])

        graf = [{"dia": t[8:10]+"/"+t[5:7], "max": mx, "chuva": ch} for t, mx, ch in zip(d['daily']['time'], d['daily']['temperature_2m_max'], d['daily']['precipitation_sum'])]
        return {"chuva": chuva_hoje, "vento": d['current']['wind_speed_10m'], "grafico": graf, "erro": False}
    except: 
        return {"chuva": 0.0, "vento": 0.0, "grafico": [], "erro": True}

def get_preco_soja():
    try:
        return round(float(requests.get("https://economia.awesomeapi.com.br/last/USD-BRL", timeout=3).json()['USDBRL']['bid']) * 26.50, 2)
    except: 
        return 135.00

# --- 3. GESTÃO DE ENERGIA ---
class GestaoEnergia:
    def __init__(self):
        self.voltagem = 12.60
        self.queda_por_ciclo = 0.05
        self.limite_alerta = 12.20
        self.limite_sobrevivencia = 11.80

    def atualizar(self):
        self.voltagem -= self.queda_por_ciclo
        if self.voltagem < 11.0: 
            self.voltagem = 12.60

        status = "NOMINAL"
        acao = "Monitorar"
        cor = "green"
        modo_4g = True

        ciclos_restantes = (self.voltagem - 11.5) / self.queda_por_ciclo
        dias_virtuais = int(ciclos_restantes)

        if self.voltagem <= self.limite_sobrevivencia:
            status = "SOBREVIVÊNCIA (48H)"
            acao = "CORTE 4G IMEDIATO"
            cor = "red blink"
            modo_4g = False
        elif self.voltagem <= self.limite_alerta:
            status = "ALERTA (PREDITIVO)"
            acao = f"AGENDAR TROCA ({dias_virtuais} dias rest.)"
            cor = "yellow"
            modo_4g = True

        return {
            "v": round(self.voltagem, 2),
            "status": status,
            "acao": acao,
            "cor": cor,
            "dias_rest": dias_virtuais,
            "4g_on": modo_4g
        }

# --- 4. DASHBOARD VISUAL ---
def gerar_dashboard(dados_energia, dados_sensores, recomendacao_ml, log_envio, clima_atual):
    """
    Dashboard atualizado com informações do ML
    """
    # 1. PAINEL DE INFRAESTRUTURA
    painel_infra = Table(box=None, expand=True, padding=(0,1))
    painel_infra.add_column("Indicador", style="bold white")
    painel_infra.add_column("Status", justify="right")

    painel_infra.add_row("🔋 Bateria", f"[{dados_energia['cor']}]{dados_energia['v']}V")
    painel_infra.add_row("📅 Autonomia", f"[{dados_energia['cor']}]{dados_energia['dias_rest']} dias")
    painel_infra.add_row("📡 Modem 4G", "🟢 ONLINE" if dados_energia['4g_on'] else "🔴 OFF")
    painel_infra.add_row("💾 SD Card", "🟢 PRONTO" if dados_energia['4g_on'] else "🟡 BUFFER")

    status_box = Panel(
        Align.center(f"[bold {dados_energia['cor']}]ESTADO: {dados_energia['status']}\nAÇÃO: {dados_energia['acao']}[/]"),
        title="🛡️ RESILIÊNCIA", 
        border_style=dados_energia['cor']
    )

    # 2. PAINEL DE ML + AGRONOMIA
    painel_agro = Table(title="KAIROS ML ENGINE v2.0", box=box.SIMPLE, expand=True)
    painel_agro.add_column("Métrica/Decisão")
    painel_agro.add_column("Valor")

    # Clima
    if clima_atual['grafico']:
        hoje = clima_atual['grafico'][0]
        painel_agro.add_row("📅 Hoje", f"🌧️ {hoje['chuva']}mm | 🌡️ {hoje['max']}°C")
        
        previsao_texto = ""
        for dia in clima_atual['grafico'][1:]:
            icone = "🌧️" if dia['chuva'] > 5 else "⛅" if dia['chuva'] > 0 else "☀️"
            previsao_texto += f"{dia['dia']}: {icone} {dia['chuva']}mm\n"
        painel_agro.add_row("📅 Próx. 7 Dias", f"[dim]{previsao_texto.strip()}[/dim]")

    # Sensores
    painel_agro.add_row("☢️ pH Solo", f"{dados_sensores['ph']}")
    painel_agro.add_row("💧 Umidade", f"{dados_sensores['umid']}%")
    painel_agro.add_row("🌡️ Temperatura", f"{dados_sensores['temp']}°C")
    painel_agro.add_row("🧪 NPK", f"{dados_sensores['npk']}")

    # Recomendação ML
    if recomendacao_ml and 'acao_principal' in recomendacao_ml:
        painel_agro.add_row("─" * 40, "─" * 40)
        painel_agro.add_row("🧠 DECISÃO ML", f"[bold cyan]{recomendacao_ml['acao_principal']}[/]")
        painel_agro.add_row("📊 Motivo", f"[dim]{recomendacao_ml['motivo']}[/dim]")
        painel_agro.add_row("🌾 Produção Est.", f"{recomendacao_ml['producao_estimada_sc_ha']} sc/ha")
        painel_agro.add_row("🎯 Confiança IA", f"{recomendacao_ml['confianca_ia']}%")
        
        if recomendacao_ml['recomendacoes_npk']:
            npk_texto = "\n".join([f"• {r}" for r in recomendacao_ml['recomendacoes_npk']])
            painel_agro.add_row("💊 NPK Recom.", f"[yellow]{npk_texto}[/]")

    # 3. LOG
    log_text = Text()
    log_text.append(f"[{datetime.now().strftime('%H:%M:%S')}] ", style="dim")
    if dados_energia['4g_on']:
        log_text.append(f"☁️ {log_envio}", style="blue")
    else:
        log_text.append("💾 MODO OFFLINE (BUFFER SD)", style="yellow")

    # MONTAGEM
    layout = Layout()
    layout.split_column(
        Layout(name="header", size=3),
        Layout(name="body", ratio=1),
        Layout(name="footer", size=3)
    )

    layout["header"].update(Panel(
        Align.center("[bold white]AGRO PLAN MAPS - ML ENGINE v2.0[/]"), 
        style="on blue"
    ))

    body_layout = Layout()
    body_layout.split_row(
        Layout(name="infra", ratio=1),
        Layout(name="agro", ratio=1)
    )

    body_layout["infra"].split_column(status_box, Panel(painel_infra, title="HARDWARE"))
    body_layout["agro"].update(Panel(painel_agro, title="TELEMETRIA ML"))

    layout["body"].update(body_layout)
    layout["footer"].update(Panel(log_text, title="SYSTEM LOG"))

    return layout

# --- 5. MOTOR PRINCIPAL ---
def main():
    print("Inicializando KAIROS ML ENGINE...")
    
    # Instancia o Motor de ML
    ml_engine = KairosMLEngine()
    
    # Tenta carregar modelo existente
    if not ml_engine.carregar_modelos():
        console.print("[yellow]⚠️ Modelo ML não encontrado. Treinando novo modelo...[/]")
        df_historico = ml_engine.coletar_dados_supabase(limite=500)
        features, target_prod, target_corr = ml_engine.preparar_dataset(df_historico)
        ml_engine.treinar_modelos(features, target_prod, target_corr)
    
    energia = GestaoEnergia()
    cache_clima = {"chuva": 0.0, "vento": 0.0, "grafico": [], "erro": False}
    cache_preco = 135.0
    contagem = 0
    recomendacao_atual = {}

    with Live(Panel("Sistemas Inicializados..."), refresh_per_second=1, screen=True) as live:
        while True:
            try:
                # 1. ATUALIZA ENERGIA
                status_energia = energia.atualizar()

                # 2. LEITURA DE SENSORES
                sensores = {
                    "ph": round(random.uniform(4.8, 6.5), 1),
                    "umid": round(random.uniform(30, 60), 1),
                    "temp": round(random.uniform(24, 29), 1),
                    "npk": f"{random.randint(20,40)}/{random.randint(10,20)}/{random.randint(80,120)}"
                }

                # 3. CLIMA (a cada 30 ciclos = ~60s)
                if status_energia['4g_on'] and contagem % 30 == 0:
                    novo_clima = get_clima()
                    if not novo_clima['erro']:
                        cache_clima = novo_clima
                    cache_preco = get_preco_soja()

                # 4. ANÁLISE ML (a cada 10 ciclos = ~20s)
                if contagem % 10 == 0:
                    try:
                        n_val, p_val, k_val = map(int, sensores['npk'].split('/'))
                    except:
                        n_val, p_val, k_val = 30, 15, 100
                    
                    # Calcula chuva dos próximos 3 dias
                    chuva_3dias = sum([d['chuva'] for d in cache_clima['grafico'][:3]]) if cache_clima['grafico'] else 0
                    
                    dados_para_ml = {
                        'ph_solo': sensores['ph'],
                        'n_solo': n_val,
                        'p_solo': p_val,
                        'k_solo': k_val,
                        'temperatura_solo': sensores['temp'],
                        'umidade_solo': sensores['umid'],
                        'chuva_prevista': chuva_3dias
                    }
                    
                    recomendacao_atual = ml_engine.analisar_solo(dados_para_ml)

                # 5. ENVIO PARA SUPABASE
                msg_envio = "..."
                if status_energia['4g_on']:
                    try:
                        n_val, p_val, k_val = map(int, sensores['npk'].split('/'))
                    except:
                        n_val, p_val, k_val = 0, 0, 0

                    payload = {
                        "device_id": "MESH_ML_01",
                        "created_at": datetime.now().isoformat(),
                        "ph_solo": sensores['ph'],
                        "n_solo": n_val,
                        "p_solo": p_val,
                        "k_solo": k_val,
                        "temperatura_solo": sensores['temp'],
                        "umidade_solo": sensores['umid'],
                        "bateria_v": status_energia['v'],
                        "status_backup": "ONLINE",
                        "recomendacao_ia_json": json.dumps(recomendacao_atual),
                        "grafico_clima": json.dumps(cache_clima['grafico'])
                    }

                    try:
                        headers = {
                            "apikey": SUPABASE_KEY,
                            "Authorization": f"Bearer {SUPABASE_KEY}",
                            "Content-Type": "application/json",
                            "Prefer": "return=minimal"
                        }
                        r = requests.post(SUPABASE_ENDPOINT, json=payload, headers=headers, timeout=2)
                        if r.status_code in [200, 201]:
                            msg_envio = "SUPABASE OK (ML v2.0) ☁️"
                        else:
                            msg_envio = f"ERRO: {r.status_code}"
                    except Exception as e:
                        msg_envio = f"FALHA: {str(e)[:15]}"
                else:
                    msg_envio = "OFFLINE (ECONOMIA)"

                # 6. ATUALIZA DASHBOARD
                live.update(gerar_dashboard(
                    status_energia, 
                    sensores, 
                    recomendacao_atual, 
                    msg_envio, 
                    cache_clima
                ))

                contagem += 1
                time.sleep(2)

            except KeyboardInterrupt:
                console.print("\n[yellow]⚠️ Sistema encerrado pelo usuário[/]")
                break
            except Exception as e:
                console.print(f"[red]❌ Erro: {e}[/]")
                time.sleep(5)

if __name__ == "__main__":
    main()
