<?php
// Depto de Engenharia e Automacao - Master Automacao - Autor: Derlivon Silva
//
// SENTINEL — varre todos clientes em storage/ e detecta:
//   1) SILENCIO: cliente nao reporta ha mais que (intervalo_esperado + tolerancia)
//      Pode ser: maquina desligada, sem internet, BI travado, processo morto
//   2) FALHA ULTIMA: cliente reportou mas com status='falha' nas tentativas finais
//
// Manda email pros enderecos em emails.php (so um email a cada 12h por cliente — anti-spam)
//
// Rode via Windows Task Scheduler do servidor 24h a cada 1 hora:
//   schtasks /Create /SC HOURLY /TN PainelBackup-Sentinel /TR "C:\PHP\php.exe C:\path\sentinel.php"

require_once __DIR__ . '/SmtpClient.php';
require_once __DIR__ . '/crypto.php';

$base = __DIR__;
$cfgFile      = $base . '/config.php';
$emailFile    = $base . '/emails.php';     // Gerado pela tela /config-email.php (senha criptografada)
$throttleDir  = $base . '/.sentinel-throttle';
$logFile      = $base . '/sentinel.log';

if (!is_file($cfgFile))   { die("ERRO: config.php nao encontrado\n"); }
if (!is_file($emailFile)) { die("ERRO: emails.php nao configurado — acesse /config-email.php no painel pra configurar\n"); }
$cfg   = include $cfgFile;
$email = include $emailFile;

// Descriptografa a senha (criptografada com token do painel + hostname da maquina)
if (!empty($email['smtp_pass_enc'])) {
    $email['smtp_pass'] = cryptoDecrypt((string)$email['smtp_pass_enc'], (string)($cfg['token'] ?? ''));
}
if (empty($email['smtp_pass'])) {
    die("ERRO: senha SMTP nao configurada — acesse /config-email.php no painel\n");
}

if (!is_dir($throttleDir)) @mkdir($throttleDir, 0777, true);

function _logSentinel(string $msg): void {
    global $logFile;
    @file_put_contents($logFile, '[' . date('c') . '] ' . $msg . "\n", FILE_APPEND);
}

function _throttleOk(string $tipoCli, string $throttleDir, int $horas = 12): bool {
    $f = $throttleDir . '/' . preg_replace('/[^a-zA-Z0-9_-]/', '', $tipoCli) . '.txt';
    if (is_file($f) && (time() - (int)@filemtime($f)) < ($horas * 3600)) return false;
    @touch($f);
    return true;
}

function _limpaThrottle(string $tipoCli, string $throttleDir): void {
    $f = $throttleDir . '/' . preg_replace('/[^a-zA-Z0-9_-]/', '', $tipoCli) . '.txt';
    if (is_file($f)) @unlink($f);
}

function _idade(string $em): array {
    $ts = strtotime($em);
    if (!$ts) return ['seg' => PHP_INT_MAX, 'txt' => 'desconhecida'];
    $seg = time() - $ts;
    if ($seg < 60)     return ['seg' => $seg, 'txt' => "$seg segundos"];
    if ($seg < 3600)   return ['seg' => $seg, 'txt' => floor($seg / 60) . ' minutos'];
    if ($seg < 86400)  return ['seg' => $seg, 'txt' => floor($seg / 3600) . ' horas'];
    return ['seg' => $seg, 'txt' => floor($seg / 86400) . ' dias'];
}

function _limiteSilencioSeg(array $c): int {
    $intervalo = (int)($c['intervalo_esperado_horas'] ?? 0);
    if ($intervalo > 0) return ($intervalo + 4) * 3600;
    return 28 * 3600;
}

// ── Le todos os clientes ─────────────────────────────────────────────────
$dirStorage = $base . '/storage';
$clientes = [];
foreach (glob($dirStorage . '/*.json') ?: [] as $f) {
    $j = @json_decode((string)@file_get_contents($f), true);
    if (is_array($j)) $clientes[] = $j;
}

_logSentinel('Iniciando sentinel. Clientes lidos: ' . count($clientes));

$emailsEnviados = 0;
$silencios = [];
$falhas    = [];

foreach ($clientes as $c) {
    $nome  = $c['cliente'] ?? '?';
    $jobId = $c['job_id']  ?? '?';
    $host  = $c['host_cliente'] ?? '?';
    $em    = (string)($c['em'] ?? '');
    $idade = _idade($em);
    $limite = _limiteSilencioSeg($c);

    // ── (1) SILENCIO: cliente parou de reportar ─────────────────────────
    if ($idade['seg'] > $limite) {
        $silencios[] = $c + ['_idade_txt' => $idade['txt'], '_limite_h' => $limite / 3600];

        $key = 'silencio_' . $jobId;
        if (_throttleOk($key, $throttleDir, 12)) {
            $assunto = "🔴 [BACKUP SILENCIOSO] $nome nao reporta ha {$idade['txt']}";
            $html = "<h2 style='color:#dc2626'>Backup silencioso</h2>"
                  . "<p><strong>Cliente:</strong> " . htmlspecialchars($nome) . "</p>"
                  . "<p><strong>Maquina:</strong> " . htmlspecialchars($host) . "</p>"
                  . "<p><strong>Ultimo backup reportado:</strong> " . htmlspecialchars($em) . " (" . $idade['txt'] . " atras)</p>"
                  . "<p><strong>Limite esperado:</strong> " . (int)($limite / 3600) . " horas</p>"
                  . "<h3>Causas possiveis (em ordem):</h3>"
                  . "<ol>"
                  . "<li><strong>Maquina desligada</strong> — pediu pra ligar o PC do cliente?</li>"
                  . "<li><strong>Sem internet</strong> — BI roda o backup local mas nao consegue notificar o painel</li>"
                  . "<li><strong>BI travado / Apache parado</strong> — testar acesso ao painel local do cliente</li>"
                  . "<li><strong>Task Scheduler desativado</strong> — rodar schtasks /Query /TN PremiumExpressBI-Agendador</li>"
                  . "</ol>"
                  . "<p><a href='http://177.23.184.123:8085/'>Ver painel central</a></p>"
                  . "<p><small>Proximo aviso desse cliente: so daqui 12h ou apos voltar a reportar — Painel Central de Backups</small></p>";
            $r = SmtpClient::enviar($email, $assunto, $html);
            if ($r['ok']) $emailsEnviados++;
            _logSentinel(($r['ok'] ? 'ENVIADO' : 'FALHA ENVIO') . " silencio: $nome ({$idade['txt']}) — " . ($r['erro'] ?? 'ok'));
        }
        continue;
    }

    // Cliente voltou a reportar — limpa throttle (proximo silencio dispara email logo)
    _limpaThrottle('silencio_' . $jobId, $throttleDir);

    // ── (2) FALHA FINAL: status=falha + tentativas esgotadas ────────────
    $status      = $c['status'] ?? '';
    $tentativa   = (int)($c['tentativa_atual'] ?? 0);
    $maxTent     = (int)($c['max_tentativas']  ?? 3);
    $proxRetry   = $c['proxima_tentativa_em'] ?? null;

    if ($status === 'falha' && $tentativa >= $maxTent && !$proxRetry) {
        $falhas[] = $c;

        $key = 'falha_' . $jobId;
        if (_throttleOk($key, $throttleDir, 12)) {
            $erroMsg = (string)($c['erro'] ?? 'erro desconhecido');
            $log     = (string)($c['log']  ?? '');
            $assunto = "🔴 [BACKUP FALHOU 3x] $nome";
            $html = "<h2 style='color:#dc2626'>Backup falhou apos $maxTent tentativas</h2>"
                  . "<p><strong>Cliente:</strong> " . htmlspecialchars($nome) . "</p>"
                  . "<p><strong>Maquina:</strong> " . htmlspecialchars($host) . "</p>"
                  . "<p><strong>Quando:</strong> " . htmlspecialchars(date('d/m/Y H:i', strtotime($em))) . "</p>"
                  . "<p><strong>Erro:</strong></p>"
                  . "<pre style='background:#fee;padding:10px;border-left:3px solid #dc2626;font-size:12px'>" . htmlspecialchars($erroMsg) . "</pre>";
            if ($log !== '') {
                $html .= "<p><strong>Log do gbak (final):</strong></p>"
                       . "<pre style='background:#222;color:#eee;padding:10px;font-size:11px;max-height:300px;overflow:auto'>" . htmlspecialchars(mb_strimwidth($log, max(0, mb_strlen($log) - 3000), 3000, '…inicio truncado')) . "</pre>";
            }
            $html .= "<p><a href='http://177.23.184.123:8085/'>Ver painel central</a></p>"
                   . "<p><small>Proximo aviso desse cliente: so daqui 12h ou apos sucesso — Painel Central de Backups</small></p>";
            $r = SmtpClient::enviar($email, $assunto, $html);
            if ($r['ok']) $emailsEnviados++;
            _logSentinel(($r['ok'] ? 'ENVIADO' : 'FALHA ENVIO') . " falha-final: $nome — " . ($r['erro'] ?? 'ok'));
        }
        continue;
    }

    if ($status === 'sucesso') {
        _limpaThrottle('falha_' . $jobId, $throttleDir);
    }
}

_logSentinel(sprintf(
    'Sentinel concluido. Silencios=%d falhas=%d emails=%d',
    count($silencios), count($falhas), $emailsEnviados
));

echo "Sentinel rodou: " . count($silencios) . " silencios, " . count($falhas) . " falhas, $emailsEnviados emails enviados.\n";
