<?php

declare(strict_types=1);

// Runner de sincronização das integrações de Realizado (CLI)
// Agora verifica back.integracao_horarios para determinar quais sincronizações executar
// O schedule da hospedagem deve chamar este script A CADA 1 MINUTO
// Exemplo cron: */1 * * * * php /var/www/html/orcamento/public/run_integracoes_schedule.php
//
// Observação: este script NÃO depende de usuário logado e É APENAS CLI

if (PHP_SAPI !== 'cli') {
	http_response_code(403);
	echo "Este endpoint é apenas para CLI.\n";
	exit(1);
}

require_once dirname(__DIR__) . '/app/config/db.php';

// Importa funções de sincronização sem executar o switch do realized_actions
define('HOME_ACTIONS_LOADING', true);
require_once dirname(__DIR__) . '/app/modules/realizado_actions.php';

function acquireLock(string $lockFile) {
	$dir = dirname($lockFile);
	if (!is_dir($dir)) {
		@mkdir($dir, 0777, true);
	}
	$fp = @fopen($lockFile, 'c+');
	if (!$fp) return null;
	if (!flock($fp, LOCK_EX | LOCK_NB)) {
		@fclose($fp);
		return null;
	}
	return $fp;
}

function releaseLock($fp): void {
	if (!$fp) return;
	@flock($fp, LOCK_UN);
	@fclose($fp);
}

$now = new DateTimeImmutable('now');
$minuteKey = $now->format('Y-m-d H:i');

$lockDir = dirname(__DIR__) . DIRECTORY_SEPARATOR . 'app' . DIRECTORY_SEPARATOR . 'logs' . DIRECTORY_SEPARATOR . 'scheduler';

// Garante que o diretório de logs existe
if (!is_dir($lockDir)) {
	if (!@mkdir($lockDir, 0777, true)) {
		echo "ERRO: Não foi possível criar o diretório de logs: {$lockDir}\n";
		exit(1);
	}
}

echo "[" . $now->format('Y-m-d H:i:s') . "] Iniciando runner de sincronização...\n";
echo "[" . $now->format('Y-m-d H:i:s') . "] Diretório de logs: {$lockDir}\n";

$rootLockFile = $lockDir . DIRECTORY_SEPARATOR . 'integracoes_schedule_runner.lock';
$rootLock = acquireLock($rootLockFile);
if (!$rootLock) {
	fwrite(STDERR, "[" . $now->format('Y-m-d H:i:s') . "] Runner já está em execução (lock ativo).\n");
	exit(0);
}

try {
	echo "[" . $now->format('Y-m-d H:i:s') . "] Buscando integrações agendadas...\n";
	
	$hora_atual = (int)$now->format('H');
	$minuto_atual = (int)$now->format('i');
	
	// Query simplificada: buscar APENAS integrações com horário agendado para AGORA
	$sql = "
		SELECT DISTINCT 
			i.cdintegracao, 
			i.dsintegracao
		FROM back.integracao i
		INNER JOIN back.integracao_horarios ih 
			ON i.cdintegracao = ih.cdintegracao
		WHERE 
			i.flativo = true
			AND ih.flativo = true
			AND ih.hora = :hora
			AND ih.minuto = :minuto
		ORDER BY i.cdintegracao
	";

	$stmt = $pdo->prepare($sql);
	$stmt->execute([':hora' => $hora_atual, ':minuto' => $minuto_atual]);
	$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

	if (!$rows) {
		echo "[" . $now->format('Y-m-d H:i:s') . "] Nenhuma integração agendada para este horário ({$hora_atual}:{$minuto_atual}).\n";
		exit(0);
	}
	
	echo "[" . $now->format('Y-m-d H:i:s') . "] Encontradas " . count($rows) . " integração(ões) para executar\n";

	$executadas = 0;
	$totalInseridos = 0;
	$totalIgnorados = 0;
	$totalErros = 0;

	foreach ($rows as $r) {
		$id = (int)($r['cdintegracao'] ?? 0);
		if ($id <= 0) continue;

		$nome = (string)($r['dsintegracao'] ?? ('Integração ' . $id));

		// Anti-repetição no mesmo minuto por integração
		$stateFile = $lockDir . DIRECTORY_SEPARATOR . 'integracao_' . $id . '_last_run.txt';
		$last = '';
		if (file_exists($stateFile)) {
			$last = @file_get_contents($stateFile);
			$last = is_string($last) ? trim($last) : '';
		}
		if ($last === $minuteKey) {
			echo "[" . $now->format('Y-m-d H:i:s') . "] Integração #{$id} já executada neste minuto, pulando\n";
			continue;
		}

		// Lock por integração
		$intLockFile = $lockDir . DIRECTORY_SEPARATOR . 'integracao_' . $id . '.lock';
		$intLock = acquireLock($intLockFile);
		if (!$intLock) {
			echo "[" . $now->format('Y-m-d H:i:s') . "] Integração #{$id} já está em execução (lock), pulando\n";
			continue;
		}

		try {
			echo "[" . $now->format('Y-m-d H:i:s') . "] Executando integração #{$id} ({$nome})...\n";

			// Executa sem restrição de empresa (sincroniza todas as empresas vinculadas)
			// skipRefresh=true porque faremos o refresh uma única vez ao final (mais eficiente)
			$res = sincronizarIntegracaoAgora($id, null, null, null, 'automatica', true);

			$ins = (int)($res['total'] ?? 0);
			$ign = (int)($res['ignorados'] ?? 0);
			$err = (int)($res['erros'] ?? 0);

			$executadas++;
			$totalInseridos += $ins;
			$totalIgnorados += $ign;
			$totalErros += $err;

			// Salva timestamp da última execução
			if (@file_put_contents($stateFile, $minuteKey) === false) {
				echo "  -> Aviso: Não foi possível salvar state file\n";
			}

			echo "  -> OK (inseridos={$ins}, ignorados={$ign}, erros={$err})\n";
		} catch (Throwable $e) {
			echo "  -> ERRO: " . $e->getMessage() . "\n";
			fwrite(STDERR, "[" . $now->format('Y-m-d H:i:s') . "] ERRO na integração #{$id}: " . $e->getMessage() . "\n");
		} finally {
			releaseLock($intLock);
		}
	}

	if ($executadas > 0) {
		echo "[" . $now->format('Y-m-d H:i:s') . "] Consolidando views...\n";
		$consol = refreshMaterializedViewsRealizado($pdo);
		if (!($consol['ok'] ?? false)) {
			echo "  -> Consolidação falhou\n";
			fwrite(STDERR, "[" . $now->format('Y-m-d H:i:s') . "] Consolidação falhou.\n");
		} else {
			echo "  -> Consolidação OK (views_atualizadas=" . (int)($consol['views_atualizadas'] ?? 0) . ")\n";
		}
	}

	echo "[" . $now->format('Y-m-d H:i:s') . "] Finalizado. Executadas={$executadas}, inseridos={$totalInseridos}, ignorados={$totalIgnorados}, erros={$totalErros}\n";
} catch (Throwable $e) {
	echo "[" . $now->format('Y-m-d H:i:s') . "] ERRO FATAL: " . $e->getMessage() . "\n";
	fwrite(STDERR, "[" . $now->format('Y-m-d H:i:s') . "] ERRO FATAL: " . $e->getMessage() . "\n");
} finally {
	releaseLock($rootLock);
}

