<?php
/**
 * Ubiquiti Poller — executa via cron a cada 60s
 * Coleta SNMP, detecta alertas de velocidade e queda de clientes, envia WhatsApp
 */
require_once __DIR__ . '/../config.php';
require_once __DIR__ . '/../db.php';
require_once __DIR__ . '/../includes/functions.php';
require_once __DIR__ . '/includes/ubiquiti_snmp.php';

$pdo = db();
$now = date('Y-m-d H:i:s');

$stmt = $pdo->query("SELECT * FROM ubiquiti_panels WHERE active = TRUE ORDER BY id ASC");
$panels = $stmt->fetchAll(PDO::FETCH_ASSOC);

if (empty($panels)) {
    echo "[" . date('H:i:s') . "] Nenhum painel Ubiquiti ativo.\n";
    exit(0);
}

foreach ($panels as $panel) {
    $panelId = (int)$panel['id'];
    $userId  = (int)$panel['user_id'];

    echo "[" . date('H:i:s') . "] Polling: {$panel['name']} ({$panel['hostname']})\n";

    // ── 1. Coleta via SNMP ─────────────────────────────────────────────────
    $data = ubnt_poll_panel($panel);

    // ── 2. Atualiza estado atual do painel ────────────────────────────────
    $pdo->prepare("
        UPDATE ubiquiti_panels SET
            last_status       = ?,
            last_client_count = ?,
            last_iface_speed  = ?,
            last_iface_status = ?,
            last_ccq          = ?,
            last_signal       = ?,
            last_check_at     = ?
        WHERE id = ?
    ")->execute([
        $data['status'],
        $data['client_count'],
        $data['iface_speed'],
        $data['iface_status'],
        $data['ccq'],
        $data['signal_dbm'],
        $now,
        $panelId,
    ]);

    if ($data['status'] === 'offline') {
        ubnt_maybe_alert($pdo, $panel, 'iface_down', 'critical', [
            'msg' => 'Painel sem resposta SNMP',
        ], $userId, $now);
        echo "  → OFFLINE\n";
        continue;
    }

    // ── 3. Registra histórico ─────────────────────────────────────────────
    $pdo->prepare("
        INSERT INTO ubiquiti_client_logs (panel_id, client_count, ccq, signal_dbm, recorded_at)
        VALUES (?, ?, ?, ?, ?)
    ")->execute([$panelId, $data['client_count'] ?? 0, $data['ccq'], $data['signal_dbm'], $now]);

    $pdo->prepare("
        INSERT INTO ubiquiti_link_logs (panel_id, iface_speed, iface_status, recorded_at)
        VALUES (?, ?, ?, ?)
    ")->execute([$panelId, $data['iface_speed'], $data['iface_status'], $now]);

    // ── 4. Detecta queda de velocidade de interface ───────────────────────
    if ($panel['alert_iface_speed'] && $data['iface_speed'] !== null && $panel['last_iface_speed'] !== null) {
        $prevSpd = (int)$panel['last_iface_speed'];
        $currSpd = (int)$data['iface_speed'];
        if ($currSpd < $prevSpd) {
            $severity = ($currSpd <= 10) ? 'critical' : 'warning';
            ubnt_maybe_alert($pdo, $panel, 'iface_speed', $severity, [
                'prev_speed' => $prevSpd,
                'curr_speed' => $currSpd,
                'msg'        => "Interface degradou de {$prevSpd}M para {$currSpd}M",
            ], $userId, $now);

            ubnt_send_whatsapp($panel, "[ALERTA] Interface {$panel['name']}: {$prevSpd}M → {$currSpd}M\nHost: {$panel['hostname']}");
        }
    }

    // Guarda velocidade anterior
    $pdo->prepare("UPDATE ubiquiti_panels SET prev_iface_speed = ? WHERE id = ?")
        ->execute([$data['iface_speed'], $panelId]);

    // ── 5. Detecta queda de clientes ──────────────────────────────────────
    if ($panel['alert_clients'] && $data['client_count'] !== null && $panel['last_client_count'] !== null) {
        $prevCount = (int)$panel['last_client_count'];
        $currCount = (int)$data['client_count'];
        $threshold = (int)$panel['alert_client_threshold'];
        $mode      = $panel['alert_client_mode'];
        $window    = (int)$panel['alert_client_window'];

        // Calcula queda
        $drop = $prevCount - $currCount;

        $triggered = false;
        if ($mode === 'absolute' && $drop >= $threshold) {
            $triggered = true;
        } elseif ($mode === 'percent' && $prevCount > 0) {
            $pct = ($drop / $prevCount) * 100;
            if ($pct >= $threshold) $triggered = true;
        }

        if ($triggered) {
            // Janela de confirmação: só alerta se a queda persistir por N minutos
            $pendingSince = $panel['alert_pending_since'];
            if (!$pendingSince) {
                // Primeira detecção: marca início da janela
                $pdo->prepare("UPDATE ubiquiti_panels SET alert_pending_since = ? WHERE id = ?")
                    ->execute([$now, $panelId]);
            } else {
                $elapsed = (time() - strtotime($pendingSince)) / 60;
                if ($elapsed >= $window) {
                    // Confirmado: gera alerta
                    ubnt_maybe_alert($pdo, $panel, 'client_drop', 'warning', [
                        'prev_count' => $prevCount,
                        'curr_count' => $currCount,
                        'drop'       => $drop,
                        'mode'       => $mode,
                        'threshold'  => $threshold,
                    ], $userId, $now);

                    $dropStr = $mode === 'percent'
                        ? round(($drop / $prevCount) * 100) . '%'
                        : $drop . ' cliente(s)';

                    ubnt_send_whatsapp($panel,
                        "[ALERTA] Queda de clientes em {$panel['name']}\n" .
                        "Anterior: {$prevCount} | Atual: {$currCount} | Queda: {$dropStr}\n" .
                        "Host: {$panel['hostname']}"
                    );

                    // Limpa janela de pending
                    $pdo->prepare("UPDATE ubiquiti_panels SET alert_pending_since = NULL WHERE id = ?")
                        ->execute([$panelId]);
                }
            }
        } else {
            // Queda não confirmada: limpa janela
            if ($panel['alert_pending_since']) {
                $pdo->prepare("UPDATE ubiquiti_panels SET alert_pending_since = NULL WHERE id = ?")
                    ->execute([$panelId]);
            }
        }
    }

    // Atualiza contagem anterior
    $pdo->prepare("UPDATE ubiquiti_panels SET prev_client_count = ? WHERE id = ?")
        ->execute([$data['client_count'], $panelId]);

    echo "  → online | clientes: " . ($data['client_count'] ?? 'N/A')
        . " | link: " . ($data['iface_speed'] ?? '?') . "M"
        . " | CCQ: " . ($data['ccq'] ?? '?') . "%\n";
}

echo "[" . date('H:i:s') . "] Ubiquiti Poller concluído. " . count($panels) . " painel(is) processado(s).\n";

// ── Funções auxiliares ────────────────────────────────────────────────────────

/**
 * Insere alerta apenas se não houver alerta idêntico nos últimos 10 minutos (anti-spam)
 */
function ubnt_maybe_alert(PDO $pdo, array $panel, string $type, string $severity, array $details, int $userId, string $now): void {
    $recent = $pdo->prepare("
        SELECT id FROM ubiquiti_alerts
        WHERE panel_id = ? AND type = ?
          AND created_at >= NOW() - INTERVAL '10 minutes'
        LIMIT 1
    ");
    $recent->execute([(int)$panel['id'], $type]);
    if ($recent->fetchColumn()) return;

    $pdo->prepare("
        INSERT INTO ubiquiti_alerts (panel_id, user_id, type, severity, details, notified, created_at)
        VALUES (?, ?, ?, ?, ?, FALSE, ?)
    ")->execute([(int)$panel['id'], $userId, $type, $severity, json_encode($details), $now]);
}

/**
 * Envia mensagem WhatsApp se o painel tiver phone configurado
 */
function ubnt_send_whatsapp(array $panel, string $message): void {
    if (empty($panel['alert_phone'])) return;

    $whats = get_whatsapp_settings();
    if (empty($whats['webhook_url'])) return;

    $phone = preg_replace('/\D/', '', $panel['alert_phone']);
    if (strlen($phone) >= 10 && !str_starts_with($phone, '55')) {
        $phone = '55' . $phone;
    }

    $payload = json_encode([
        'phone' => $phone,
        'host'  => $panel['hostname'],
        'label' => $panel['name'],
        'status'=> 'offline',
        'msg'   => $message,
        'token' => $whats['token'] ?? '',
    ]);

    $ctx = stream_context_create(['http' => [
        'method'  => 'POST',
        'header'  => "Content-Type: application/json\r\nContent-Length: " . strlen($payload),
        'content' => $payload,
        'timeout' => 10,
        'ignore_errors' => true,
    ]]);
    @file_get_contents($whats['webhook_url'], false, $ctx);
}
