#!/usr/bin/env php
<?php
/**
 * SLA Refresher CLI
 *
 * Uso:
 *   php bin/check-sla
 *   php bin/check-sla --actor-user-id=1
 *   php bin/check-sla --tenant=academico
 *   php bin/check-sla --dry-run
 *   php bin/check-sla --help
 */

$basePath = dirname(__DIR__);
define('BASE_PATH', $basePath . '/');

require $basePath . '/core/helpers/Env.php';
Env::load($basePath . '/.env');

$args = array_slice($argv, 1);

if (in_array('--help', $args, true) || in_array('-h', $args, true)) {
    echo "\nKlee SLA Refresher\n";
    echo "Uso:\n";
    echo "  php bin/check-sla\n";
    echo "  php bin/check-sla --actor-user-id=1\n";
    echo "  php bin/check-sla --tenant=academico\n";
    echo "  php bin/check-sla --dry-run\n\n";
    echo "Opciones:\n";
    echo "  --actor-user-id=ID   Usuario actor para eventos/auditoría (opcional)\n";
    echo "  --tenant=KEY         Tenant a procesar (opcional, usa KLEE_TENANT)\n";
    echo "  --dry-run            Solo calcula y muestra resumen; no actualiza SLA\n";
    exit(0);
}

$actorUserId = null;
$tenantKey = '';
$dryRun = in_array('--dry-run', $args, true);

foreach ($args as $arg) {
    if (strpos($arg, '--actor-user-id=') === 0) {
        $parsed = (int)substr($arg, 16);
        if ($parsed > 0) {
            $actorUserId = $parsed;
        }
    } elseif (strpos($arg, '--tenant=') === 0) {
        $tenantKey = trim((string)substr($arg, 9));
    }
}

if ($tenantKey !== '') {
    putenv('KLEE_TENANT=' . $tenantKey);
    $_ENV['KLEE_TENANT'] = $tenantKey;
    $_SERVER['KLEE_TENANT'] = $tenantKey;
}

if (file_exists($basePath . '/vendor/autoload.php')) {
    require $basePath . '/vendor/autoload.php';
}

$fallbackAutoloadSearchPaths = array(
    'core/',
    'core/traits/',
    'core/db/',
    'core/middleware/',
    'core/attributes/',
    'core/contracts/',
    'app/models/',
    'app/controllers/',
    'core/helpers/',
    'app/config/',
);

$fallbackClassFileMap = array(
    'DB' => 'core/Db.php',
    'Database' => 'core/Db.php',
    'FORM_VALIDATE' => 'core/Formvalidate.php',
    'FormValidator' => 'core/Formvalidate.php',
);

spl_autoload_register(function ($class) use ($basePath, $fallbackAutoloadSearchPaths, $fallbackClassFileMap) {
    if (isset($fallbackClassFileMap[$class])) {
        $mappedPath = $basePath . '/' . $fallbackClassFileMap[$class];
        if (file_exists($mappedPath)) {
            require_once $mappedPath;
            return;
        }
    }

    foreach ($fallbackAutoloadSearchPaths as $relativePath) {
        $classPath = $basePath . '/' . $relativePath . $class . '.php';
        if (file_exists($classPath)) {
            require_once $classPath;
            return;
        }
    }
}, true, true);

if (file_exists($basePath . '/app/config/Config.php')) {
    require $basePath . '/app/config/Config.php';
}
if (file_exists($basePath . '/app/config/ConfigEnv.php')) {
    require $basePath . '/app/config/ConfigEnv.php';
}

if (class_exists('TenantContext')) {
    TenantContext::bootstrap();
}

if (class_exists('Controller')) {
    Controller::syncConfigFromEnv();
}

if (class_exists('Config')) {
    @setlocale(LC_ALL, Config::getLocale());
    @setlocale(LC_MONETARY, Config::getLocaleMonetary());
    @setlocale(LC_TIME, Config::getLocaleTime());
    @date_default_timezone_set(Config::getTimezone());
}

if (session_status() === PHP_SESSION_NONE) {
    @session_start();
}

if (!class_exists('TicketsModel')) {
    echo "[error] TicketsModel no disponible. Verifica autoload de Composer.\n";
    exit(2);
}

$getCount = function ($criteria) {
    $row = TicketsModel::getQuantity($criteria, array());
    if (!is_array($row) || !isset($row['Numero'])) {
        return 0;
    }

    return (int)$row['Numero'];
};

$buildBaseCriteria = function ($closedStateIds) {
    $criteria = array(
        'WHERE' => array(
            array('name' => 'Estado', 'value' => 1),
        ),
    );

    if (!empty($closedStateIds)) {
        $criteria['WHERE'][] = array(
            'name' => 'EstadoId',
            'operator' => 'NOT IN',
            'value' => array_values($closedStateIds),
        );
    }

    return $criteria;
};

$getSummary = function () use ($buildBaseCriteria, $getCount) {
    $estadoResuelto = (int)TicketsModel::getEstadoIdByNombre('Resuelto');
    $estadoCerrado = (int)TicketsModel::getEstadoIdByNombre('Cerrado');

    $closedStateIds = array();
    if ($estadoResuelto > 0) {
        $closedStateIds[] = $estadoResuelto;
    }
    if ($estadoCerrado > 0) {
        $closedStateIds[] = $estadoCerrado;
    }

    $closedStateIds = array_values(array_unique($closedStateIds));

    $base = $buildBaseCriteria($closedStateIds);

    $alerts = $base;
    $alerts['WHERE'][] = array(
        'type' => 'internal',
        'conditions' => array(
            array('name' => 'SlaPrimeraRespuestaAlerta', 'value' => 1),
            array('name' => 'SlaResolucionAlerta', 'value' => 1, 'operator_logic' => 'OR'),
        ),
    );

    $breaches = $base;
    $breaches['WHERE'][] = array(
        'type' => 'internal',
        'conditions' => array(
            array('name' => 'SlaPrimeraRespuestaIncumplido', 'value' => 1),
            array('name' => 'SlaResolucionIncumplido', 'value' => 1, 'operator_logic' => 'OR'),
        ),
    );

    $firstResponseBreaches = $base;
    $firstResponseBreaches['WHERE'][] = array('name' => 'SlaPrimeraRespuestaIncumplido', 'value' => 1);

    $resolutionBreaches = $base;
    $resolutionBreaches['WHERE'][] = array('name' => 'SlaResolucionIncumplido', 'value' => 1);

    return array(
        'openTickets' => $getCount($base),
        'alertsAny' => $getCount($alerts),
        'breachesAny' => $getCount($breaches),
        'firstResponseBreaches' => $getCount($firstResponseBreaches),
        'resolutionBreaches' => $getCount($resolutionBreaches),
        'closedStateIds' => $closedStateIds,
    );
};

$tenantContext = class_exists('TenantContext') ? TenantContext::current() : array('key' => 'default', 'tenant_id' => null);
$tenantLabel = isset($tenantContext['key']) ? (string)$tenantContext['key'] : 'default';
$tenantId = isset($tenantContext['tenant_id']) ? (int)$tenantContext['tenant_id'] : null;

$start = microtime(true);

try {
    $before = $getSummary();

    if (!$dryRun) {
        TicketsModel::refreshSlaIndicators($actorUserId);
    }

    $after = $getSummary();
} catch (Exception $e) {
    echo '[error] Falló check-sla: ' . $e->getMessage() . "\n";
    exit(2);
}

$elapsedMs = (int)round((microtime(true) - $start) * 1000);

$diffAlerts = $after['alertsAny'] - $before['alertsAny'];
$diffBreaches = $after['breachesAny'] - $before['breachesAny'];
$diffFirstResponseBreaches = $after['firstResponseBreaches'] - $before['firstResponseBreaches'];
$diffResolutionBreaches = $after['resolutionBreaches'] - $before['resolutionBreaches'];

if ($dryRun) {
    echo "[ok] SLA check ejecutado en modo dry-run.\n";
} else {
    echo "[ok] SLA refresh ejecutado correctamente.\n";
}

echo '  tenant: ' . $tenantLabel;
if ($tenantId !== null) {
    echo ' (id=' . $tenantId . ')';
}
echo "\n";

echo '  actor_user_id: ' . ($actorUserId !== null ? (string)$actorUserId : 'null') . "\n";
echo '  tiempo_ms: ' . $elapsedMs . "\n";
echo '  abiertos: ' . $before['openTickets'] . ' -> ' . $after['openTickets'] . "\n";
echo '  alertas_sla: ' . $before['alertsAny'] . ' -> ' . $after['alertsAny'] . ' (delta=' . $diffAlerts . ")\n";
echo '  incumplidos_sla: ' . $before['breachesAny'] . ' -> ' . $after['breachesAny'] . ' (delta=' . $diffBreaches . ")\n";
echo '  incumplidos_primera_respuesta: ' . $before['firstResponseBreaches'] . ' -> ' . $after['firstResponseBreaches'] . ' (delta=' . $diffFirstResponseBreaches . ")\n";
echo '  incumplidos_resolucion: ' . $before['resolutionBreaches'] . ' -> ' . $after['resolutionBreaches'] . ' (delta=' . $diffResolutionBreaches . ")\n";

exit(0);
