executeRulesForEvent method

Future<List<RulesExecutionResult>> executeRulesForEvent({
  1. required String eventType,
  2. required Map<String, dynamic> context,
  3. Map<String, dynamic>? specificRule,
})

UNIFIED METHOD: Execute all applicable rules for an event

Implementation

Future<List<RulesExecutionResult>> executeRulesForEvent({
  required String eventType,
  required Map<String, dynamic> context,
  Map<String, dynamic>? specificRule,
}) async {
  final results = <RulesExecutionResult>[];

  if (_rulesController == null) {
    ObslyLogger.debug('⚠️ No rules controller available');
    return results;
  }

  try {
    List<Map<String, dynamic>> rulesToExecute;

    if (specificRule != null) {
      // Manual rule execution - use the provided rule
      rulesToExecute = [specificRule];
      ObslyLogger.log('🎯 Executing specific rule: ${specificRule['key']}');
    } else {
      // Get applicable rules from consolidated list
      rulesToExecute = getRulesByEventType(eventType);
      ObslyLogger.log(
          '🎯 Executing ${rulesToExecute.length} rules for $eventType');
    }

    // Build base context once for reuse across all rules
    Map<String, dynamic> baseContext;
    Map<String, dynamic> mutableContext;

    if (specificRule == null) {
      // For event-based execution, optimize context reuse
      baseContext = Map<String, dynamic>.from(context);
      mutableContext = Map<String, dynamic>.from(baseContext);
    } else {
      // For manual execution, use simple context
      baseContext = {};
      mutableContext = {};
    }

    for (final rule in rulesToExecute) {
      final ruleKey = rule['key']?.toString() ?? 'unknown';
      final ruleName = rule['name']?.toString() ?? ruleKey;
      final ruleSource = rule['_source']?.toString() ?? 'unknown';

      try {
        ObslyLogger.verboseDetails('RULES', 'πŸ”„ Executing rule: $ruleName [$ruleSource]');

        // Notify execution started
        notifyRuleExecutionStarted(ruleKey, context);

        // Execute rule using the SAME method for ALL rules
        dynamic result;
        if (specificRule != null) {
          // Manual execution: use executeRule method
          result = await _rulesController?.executeRule(rule);
        } else {
          // Event-based execution: use executeCustomRules method with optimized context
          final ruleContext = {
            ...mutableContext, // Reuse accumulated context
            'ruleDefinition': rule,
          };
          result = await _rulesController?.executeCustomRules(ruleContext);

          // Update mutable context with any variables from this rule
          _updateMutableContext(mutableContext, result);
        }

        // Create unified execution result
        final executionResult = RulesExecutionResult(
          ruleKey: ruleKey,
          ruleName: ruleName,
          success: result != null,
          context: context,
          timestamp: DateTime.now(),
          eventType: specificRule != null ? 'manual' : eventType,
          originalEvent: specificRule ?? context,
          rawResult: result?.rawResult, // Extract raw result from RulesResult
        );

        results.add(executionResult);

        // Notify completion
        notifyRuleExecutionCompleted(executionResult);

        ObslyLogger.verboseDetails('RULES', 'βœ… Rule "$ruleName" [$ruleSource] executed');
      } catch (e) {
        ObslyLogger.error('   ❌ Error executing rule "$ruleKey": $e');

        // Create error result
        final errorResult = RulesExecutionResult(
          ruleKey: ruleKey,
          ruleName: ruleName,
          success: false,
          error: e.toString(),
          context: context,
          timestamp: DateTime.now(),
          eventType: specificRule != null ? 'manual' : eventType,
          originalEvent: specificRule ?? context,
          rawResult: null,
        );

        results.add(errorResult);
        notifyRuleExecutionCompleted(errorResult);
      }
    }
  } catch (e) {
    ObslyLogger.error('Error in executeRulesForEvent: $e');
    notifyRulesExecutionError(e.toString(), context);
  }

  return results;
}