<?php
/**
 * ASISMA CRM - Cron: Rotación en cascada de leads
 * Ejecutar cada 1-5 minutos: php cron/rotacion_leads.php
 *
 * Lógica:
 *  1. Busca asignaciones con estado='pendiente' cuyo plazo (asignado_at + timeout_segundos) expiró.
 *  2. Marca esa asignación como 'timeout'.
 *  3. Reasigna al siguiente franquiciado calificado vía RotacionHelper (misma región y
 *     vertical, por prioridad, con vendedores en cola, sin repetir intentados).
 *  4. Si nadie califica, devuelve el lead a la matriz y registra la alerta.
 *  5. Además, intenta asignar leads 'nuevo' sin asignación pendiente (p. ej. creados vía API
 *     o devueltos a matriz cuando ya hay franquiciados disponibles nuevamente).
 */

define('CRON_MODE', true);

$rootDir = dirname(__DIR__);
require $rootDir . '/config/config.php'; // Carga .env, constantes y config/database.php (clase Database)
require $rootDir . '/app/helpers/AlcanceHelper.php'; // RotacionHelper la usa (el cron no tiene autoload)
require $rootDir . '/app/helpers/SessionHelper.php'; // AuditHelper la usa (en CLI devuelve null, seguro)
require $rootDir . '/app/helpers/AuditHelper.php';   // Auditoria de a quien se notifica cada lead
require $rootDir . '/app/helpers/RotacionHelper.php';

function cron_log($msg) {
    $linea = '[' . date('Y-m-d H:i:s') . '] ' . $msg . PHP_EOL;
    echo $linea;
    file_put_contents(dirname(__DIR__) . '/logs/rotacion_leads.log', $linea, FILE_APPEND);
}

try {
    $db = Database::getInstance();
    $procesadas = 0;

    // ── Fase 1: asignaciones pendientes expiradas ────────────────────────────
    $expiradas = $db->fetchAll(
        "SELECT al.id AS asignacion_id, al.franquiciado_id, l.id AS lead_id, l.region_id, l.vertical_interes, l.marca_interes, l.producto_interes
         FROM asignaciones_lead al
         INNER JOIN leads l ON al.lead_id = l.id
         WHERE al.estado = 'pendiente'
           AND al.respondido_at IS NULL
           AND DATE_ADD(al.asignado_at, INTERVAL al.timeout_segundos SECOND) < NOW()
           AND l.activo = 1
           AND l.estado_embudo NOT IN ('ganado', 'perdido', 'invalido')"
    );

    foreach ($expiradas as $asig) {
        $leadId = (int)$asig['lead_id'];

        $db->beginTransaction();
        try {
            $db->update('asignaciones_lead', array(
                'estado'        => 'timeout',
                'respondido_at' => date('Y-m-d H:i:s')
            ), "id = :id", array('id' => $asig['asignacion_id']));

            cron_log("Lead #$leadId: asignación #{$asig['asignacion_id']} expirada (franquiciado #{$asig['franquiciado_id']}).");

            $nueva = RotacionHelper::asignarSiguiente($leadId, (int)$asig['region_id'], (int)$asig['vertical_interes'], $asig['marca_interes'], $asig['producto_interes']);
            if ($nueva) {
                cron_log("Lead #$leadId: reasignado → franquiciado #{$nueva['franquiciado_id']}, vendedor #{$nueva['usuario_id']}.");
            } else {
                RotacionHelper::devolverAMatriz($leadId);
                cron_log("Lead #$leadId: cascada agotada. Devuelto a matriz (requiere gestión manual).");
            }
            $db->commit();
            $procesadas++;
        } catch (Exception $e) {
            $db->rollBack();
            cron_log("Lead #$leadId: ERROR en rotación - " . $e->getMessage());
        }
    }

    // ── Fase 2: leads nuevos sin asignación pendiente (entrada por API o devueltos) ──
    $sinAsignar = $db->fetchAll(
        "SELECT l.id AS lead_id, l.region_id, l.vertical_interes, l.marca_interes, l.producto_interes
         FROM leads l
         WHERE l.estado_embudo = 'nuevo'
           AND l.activo = 1
           AND l.franquiciado_id IS NULL
           AND l.region_id IS NOT NULL
           AND l.vertical_interes IS NOT NULL
           AND NOT EXISTS (
               SELECT 1 FROM asignaciones_lead al
               WHERE al.lead_id = l.id AND al.estado = 'pendiente'
           )"
    );

    foreach ($sinAsignar as $lead) {
        $leadId = (int)$lead['lead_id'];
        $db->beginTransaction();
        try {
            $nueva = RotacionHelper::asignarSiguiente($leadId, (int)$lead['region_id'], (int)$lead['vertical_interes'], $lead['marca_interes'], $lead['producto_interes']);
            if ($nueva) {
                cron_log("Lead #$leadId: asignación inicial → franquiciado #{$nueva['franquiciado_id']}, vendedor #{$nueva['usuario_id']}.");
                $procesadas++;
            }
            $db->commit();
        } catch (Exception $e) {
            $db->rollBack();
            cron_log("Lead #$leadId: ERROR en asignación inicial - " . $e->getMessage());
        }
    }

    if ($procesadas === 0 && empty($expiradas)) {
        cron_log("Sin asignaciones expiradas ni leads pendientes. Nada que procesar.");
    } else {
        cron_log("Proceso completado. Operaciones: $procesadas.");
    }

} catch (Exception $e) {
    cron_log("ERROR FATAL: " . $e->getMessage());
    exit(1);
}
