<?php
/**
 * ASISMA CRM - Helper de Rotación en Cascada
 *
 * Lógica compartida entre el cron de rotación (cron/rotacion_leads.php),
 * la API de captación de leads y la creación manual.
 */
class RotacionHelper {

    /**
     * Busca el siguiente destino en la cascada para un lead y crea la asignación.
     *
     * Cascada según spec: Usuario 1 (Franq A) → Usuario 2 (Franq A) → ... →
     * Usuario 1 (Franq B) → ... → matriz. Los franquiciados califican por
     * región + vertical del lead Y por lo que pueden VENDER:
     *   - si el lead tiene PRODUCTO de interés, deben poder vender ESE producto
     *     (marca completa autorizada o el producto suelto en franquiciado_productos);
     *   - si solo tiene MARCA (lead generico, el default de la API), SOLO
     *     califican los franquiciados con la marca COMPLETA: los que venden
     *     productos sueltos reciben leads unicamente por producto.
     * Se recorren por prioridad (mayor número = más prioritario); dentro de cada
     * uno, por orden de cola, saltando a los vendedores ya intentados.
     *
     * Actualiza el lead (franquiciado, vendedor, estado 'asignado'), rota la cola
     * y registra la actividad. NO abre transacción: el llamador decide.
     *
     * @return array|null Datos de la asignación creada o null si nadie califica.
     */
    public static function asignarSiguiente($leadId, $regionId, $verticalId, $marcaId = null, $productoId = null) {
        $db = Database::getInstance();

        $filtroVenta = '';
        $params = array('rid' => $regionId, 'vid' => $verticalId);
        if ($productoId) {
            // La restricción manda a nivel de PRODUCTO
            $filtroVenta = " AND " . AlcanceHelper::condicionPuedeVenderProducto('f');
            $params['pid_marca']  = (int)$productoId;
            $params['pid_suelto'] = (int)$productoId;
        } elseif ($marcaId) {
            $filtroVenta = " AND " . AlcanceHelper::condicionPuedeVenderMarca('f');
            $params['mid_completa'] = (int)$marcaId;
        }

        $candidatos = $db->fetchAll(
            "SELECT f.id, f.tiempo_toma_lead
             FROM franquiciados f
             WHERE f.estado = 'activo'
               AND f.region_id = :rid
               AND f.vertical_id = :vid
               {$filtroVenta}
             ORDER BY f.prioridad DESC, f.id ASC",
            $params
        );

        foreach ($candidatos as $franq) {
            $franqId = (int)$franq['id'];

            // Primer vendedor activo en cola que aún no haya sido intentado para este lead
            $vendedor = $db->fetchOne(
                "SELECT c.usuario_id FROM cola_asignacion c
                 INNER JOIN usuarios u ON c.usuario_id = u.id
                 WHERE c.franquiciado_id = :fid AND c.activo = 1 AND u.activo = 1
                   AND c.usuario_id NOT IN (
                       SELECT al.usuario_id FROM asignaciones_lead al WHERE al.lead_id = :lid
                   )
                 ORDER BY c.orden ASC
                 LIMIT 1",
                array('fid' => $franqId, 'lid' => $leadId)
            );

            if (!$vendedor) {
                continue; // franquiciado sin vendedores disponibles no intentados
            }

            $vendedorId = (int)$vendedor['usuario_id'];
            $timeout    = (int)$franq['tiempo_toma_lead'];
            if ($timeout <= 0) $timeout = 300;

            $db->insert('asignaciones_lead', array(
                'lead_id'          => $leadId,
                'franquiciado_id'  => $franqId,
                'usuario_id'       => $vendedorId,
                'estado'           => 'pendiente',
                'timeout_segundos' => $timeout
            ));

            $db->update('leads', array(
                'franquiciado_id'     => $franqId,
                'usuario_asignado_id' => $vendedorId,
                'estado_embudo'       => ESTADO_ASIGNADO
            ), "id = :id", array('id' => $leadId));

            // Rotar la cola: el vendedor asignado pasa al final
            $maxOrd = $db->fetchOne(
                "SELECT MAX(orden) as mx FROM cola_asignacion WHERE franquiciado_id = :fid",
                array('fid' => $franqId)
            );
            $db->update('cola_asignacion',
                array('orden' => (int)$maxOrd['mx'] + 1),
                "franquiciado_id = :fid AND usuario_id = :uid",
                array('fid' => $franqId, 'uid' => $vendedorId)
            );

            $db->insert('actividades_crm', array(
                'lead_id'    => $leadId,
                'usuario_id' => null,
                'tipo'       => 'sistema',
                'direccion'  => 'interna',
                'asunto'     => 'Asignación automática (rotación)',
                'detalles'   => "Lead asignado por cascada al franquiciado #$franqId, vendedor #$vendedorId (timeout {$timeout}s)."
            ));

            // Auditoria: queda registrado A QUIEN se le notifico la llegada del
            // lead — franquicia y usuario exactos, con nombre (exigencia 20-07).
            $franquiciaFila = $db->fetchOne(
                "SELECT ef.nombre_fantasia FROM empresas_franquiciados ef
                 INNER JOIN franquiciados fr ON fr.empresa_madre_id = ef.id
                 WHERE fr.id = :fid",
                array('fid' => $franqId)
            );
            $vendedorFila = $db->fetchOne(
                "SELECT nombre, email FROM usuarios WHERE id = :id",
                array('id' => $vendedorId)
            );
            AuditHelper::log('notificacion_lead', 'asignaciones_lead', $leadId, null, array(
                'lead_id'          => $leadId,
                'franquiciado_id'  => $franqId,
                'franquicia'       => $franquiciaFila ? $franquiciaFila['nombre_fantasia'] : null,
                'usuario_id'       => $vendedorId,
                'usuario'          => $vendedorFila ? $vendedorFila['nombre'] : null,
                'usuario_email'    => $vendedorFila ? $vendedorFila['email'] : null,
                'timeout_segundos' => $timeout
            ));

            return array(
                'franquiciado_id' => $franqId,
                'usuario_id'      => $vendedorId,
                'timeout'         => $timeout
            );
        }

        return null;
    }

    /**
     * Devuelve el lead a la matriz (sin franquiciado) y registra la alerta.
     */
    public static function devolverAMatriz($leadId) {
        $db = Database::getInstance();

        $db->update('leads', array(
            'franquiciado_id'     => null,
            'usuario_asignado_id' => null,
            'estado_embudo'       => ESTADO_NUEVO
        ), "id = :id", array('id' => $leadId));

        $db->insert('actividades_crm', array(
            'lead_id'    => $leadId,
            'usuario_id' => null,
            'tipo'       => 'sistema',
            'direccion'  => 'interna',
            'asunto'     => 'ALERTA: sin franquiciados disponibles',
            'detalles'   => 'La cascada de asignación se agotó sin que ningún franquiciado tomara el lead. Requiere gestión manual de la matriz.'
        ));
    }
}
