<?php
	
	namespace Dashboard\Core\Jobs;
	
	use Exception;
	
	class JobDispatcher
	{
		private static function checkExecAvailability(): bool
		{
			if (!function_exists('exec')) {
				return false;
			}
			
			$disabledFunctions = explode(',', ini_get('disable_functions'));
			$disabledFunctions = array_map('trim', $disabledFunctions);
			
			if (in_array('exec', $disabledFunctions)) {
				return false;
			}
			
			$phpBinFile = PHP_BINDIR . '/php';
			return !(!file_exists($phpBinFile) || !is_executable($phpBinFile));
		}
		
		public static function dispatch(Job $job): bool
		{
			if (self::checkExecAvailability()) {
				return self::dispatchAsync($job);
			}
			
			return self::dispatchSync($job);
		}
		
		public static function dispatchAsync(Job $job): bool
		{
			$workerPath = $_SERVER["DOCUMENT_ROOT"] . "/apps/cli/worker.php";
			$phpBinFile = PHP_BINDIR . '/php';
			
			$payload = serialize($job);
			$encodedPayload = base64_encode($payload);
			
			$command = "$phpBinFile -f $workerPath " . escapeshellarg($job->getName()) . " " . escapeshellarg($encodedPayload);
			
			if (PHP_OS_FAMILY === 'Windows') {
				$command = "start /B $command > NUL 2>&1";
			} else {
				$command = "$command > /dev/null 2>&1 &";
			}
			
			exec($command, $output, $returnVar);
			
			return $returnVar === 0;
		}
		
		public static function dispatchSync(Job $job): bool
		{
			try {
				$job->handle();
				return true;
			} catch (Exception $e) {
				FailedJobsManager::addFailedJob(
					$job->getName(),
					serialize($job),
					$e->getMessage(),
					$job->getMaxAttempts()
				);
				return false;
			}
		}
	}