<?php
/**
 * processar_fila.php
 * Consome a fila_mensagens.json em pequenos blocos, simulando comportamento
 * humano com sleep(rand(15,35)) entre cada envio, para reduzir o risco de
 * bloqueio do número de WhatsApp. Deve ser agendado via cron a cada minuto:
 *
 *   * * * * * /usr/bin/php /caminho/projeto/cron/processar_fila.php >> /caminho/projeto/logs/fila.log 2>&1
 *
 * Se houver mais de uma instância de WhatsApp ativa em config.json, revezamos
 * o envio entre elas (round-robin) a cada mensagem processada.
 */

require_once __DIR__ . '/../core/db_helper.php';

const TAMANHO_LOTE = 5; // quantas mensagens processar por execução (a cada minuto)

$config = db_read('config');
$instancias = array_values(array_filter(
    $config['whatsapp']['instancias'] ?? [],
    fn($i) => $i['ativa'] ?? false
));

if (empty($instancias)) {
    fwrite(STDERR, "[" . date('Y-m-d H:i:s') . "] Nenhuma instância de WhatsApp ativa configurada.\n");
    exit(1);
}

$minEspera = (int) ($config['whatsapp']['intervalo_min_segundos'] ?? 15);
$maxEspera = (int) ($config['whatsapp']['intervalo_max_segundos'] ?? 35);

/**
 * Envia uma mensagem através da API HTTP da instância de WhatsApp (formato
 * genérico compatível com WPPConnect / Baileys / Evolution API — ajuste o
 * payload conforme o gateway realmente utilizado).
 */
function enviar_via_instancia(array $instancia, string $numero, string $mensagem): bool
{
    $ch = curl_init(rtrim($instancia['url_api'], '/') . '/send-message');
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST => true,
        CURLOPT_TIMEOUT => 20,
        CURLOPT_HTTPHEADER => [
            'Content-Type: application/json',
            'Authorization: Bearer ' . $instancia['token'],
        ],
        CURLOPT_POSTFIELDS => json_encode([
            'number' => $numero,
            'message' => $mensagem,
        ]),
    ]);
    $resp = curl_exec($ch);
    $codigo = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    return $codigo >= 200 && $codigo < 300;
}

// Pega até TAMANHO_LOTE mensagens pendentes, marcando-as como "processando"
// dentro de uma única trava para evitar que duas execuções concorrentes do
// cron peguem a mesma mensagem.
$lote = db_update('fila_mensagens', function (&$fila) {
    $selecionadas = [];
    foreach ($fila as &$item) {
        if ($item['status'] === 'pendente') {
            $item['status'] = 'processando';
            $selecionadas[] = &$item;
            if (count($selecionadas) >= TAMANHO_LOTE) {
                break;
            }
        }
    }
    return $selecionadas;
});

if (empty($lote)) {
    exit(0); // nada a fazer
}

$indiceInstancia = 0;
foreach ($lote as $i => $item) {
    $instancia = $instancias[$indiceInstancia % count($instancias)];
    $indiceInstancia++;

    $sucesso = enviar_via_instancia($instancia, $item['whatsapp'], $item['mensagem']);

    db_update('fila_mensagens', function (&$fila) use ($item, $sucesso) {
        foreach ($fila as &$f) {
            if ($f['id'] === $item['id']) {
                $f['tentativas'] = ($f['tentativas'] ?? 0) + 1;
                if ($sucesso) {
                    $f['status'] = 'enviado';
                    $f['enviado_em'] = date('Y-m-d H:i:s');
                } else {
                    // volta para pendente se ainda não esgotou tentativas
                    $f['status'] = $f['tentativas'] >= 3 ? 'erro' : 'pendente';
                }
                break;
            }
        }
    });

    auditoria_log_seguro($instancia['nome'] ?? 'whatsapp', $sucesso ? 'WPP_ENVIADO' : 'WPP_FALHA', $item['whatsapp']);

    // Atraso aleatório entre envios para emular atividade humana (anti-bloqueio)
    if ($i < count($lote) - 1) {
        sleep(rand($minEspera, $maxEspera));
    }
}

/** Wrapper defensivo para não quebrar o cron caso auditoria falhe. */
function auditoria_log_seguro(string $origem, string $acao, string $detalhes): void
{
    try {
        auditoria_log($origem, $acao, $detalhes);
    } catch (\Throwable $e) {
        // ignora falha de log para não interromper o envio
    }
}
