Skip to main content

rust_rule_engine/engine/
engine.rs

1use crate::engine::{
2    agenda::{ActivationGroupManager, AgendaManager},
3    analytics::RuleAnalytics,
4    facts::Facts,
5    knowledge_base::KnowledgeBase,
6    plugin::{PluginConfig, PluginInfo, PluginManager, PluginStats},
7    workflow::WorkflowEngine,
8};
9use crate::errors::{Result, RuleEngineError};
10use crate::types::{ActionType, Operator, Value};
11use chrono::{DateTime, Utc};
12use log::info;
13use std::collections::HashMap;
14use std::time::{Duration, Instant};
15
16/// Type for custom function implementations
17pub type CustomFunction = Box<dyn Fn(&[Value], &Facts) -> Result<Value> + Send + Sync>;
18
19/// Type for custom action handlers
20pub type ActionHandler = Box<dyn Fn(&HashMap<String, Value>, &Facts) -> Result<()> + Send + Sync>;
21
22/// Configuration options for the rule engine
23#[derive(Debug, Clone)]
24pub struct EngineConfig {
25    /// Maximum number of execution cycles
26    pub max_cycles: usize,
27    /// Execution timeout
28    pub timeout: Option<Duration>,
29    /// Enable performance statistics collection
30    pub enable_stats: bool,
31    /// Enable debug mode with verbose logging
32    pub debug_mode: bool,
33}
34
35impl Default for EngineConfig {
36    fn default() -> Self {
37        Self {
38            max_cycles: 100,
39            timeout: Some(Duration::from_secs(30)),
40            enable_stats: true,
41            debug_mode: false,
42        }
43    }
44}
45
46/// Result of rule engine execution
47#[derive(Debug, Clone)]
48pub struct GruleExecutionResult {
49    /// Number of execution cycles
50    pub cycle_count: usize,
51    /// Number of rules evaluated
52    pub rules_evaluated: usize,
53    /// Number of rules that fired
54    pub rules_fired: usize,
55    /// Total execution time
56    pub execution_time: Duration,
57}
58
59/// Rust Rule Engine - High-performance rule execution engine
60pub struct RustRuleEngine {
61    knowledge_base: KnowledgeBase,
62    config: EngineConfig,
63    custom_functions: HashMap<String, CustomFunction>,
64    action_handlers: HashMap<String, ActionHandler>,
65    analytics: Option<RuleAnalytics>,
66    agenda_manager: AgendaManager,
67    activation_group_manager: ActivationGroupManager,
68    /// Track rules that have fired globally (for no-loop support)
69    fired_rules_global: std::collections::HashSet<String>,
70    /// Workflow engine for rule chaining and sequential execution
71    workflow_engine: WorkflowEngine,
72    /// Plugin manager for extensible functionality
73    plugin_manager: PluginManager,
74}
75
76#[allow(dead_code)]
77impl RustRuleEngine {
78    /// Execute all rules and call callback when a rule is fired
79    pub fn execute_with_callback<F>(
80        &mut self,
81        facts: &Facts,
82        mut on_rule_fired: F,
83    ) -> Result<GruleExecutionResult>
84    where
85        F: FnMut(&str, &Facts),
86    {
87        use chrono::Utc;
88        let timestamp = Utc::now();
89        let start_time = std::time::Instant::now();
90        let mut cycle_count = 0;
91        let mut rules_evaluated = 0;
92        let mut rules_fired = 0;
93
94        self.sync_workflow_agenda_activations();
95
96        for cycle in 0..self.config.max_cycles {
97            cycle_count = cycle + 1;
98            let mut any_rule_fired = false;
99            let mut fired_rules_in_cycle = std::collections::HashSet::new();
100            self.activation_group_manager.reset_cycle();
101
102            if let Some(timeout) = self.config.timeout {
103                if start_time.elapsed() > timeout {
104                    return Err(crate::errors::RuleEngineError::EvaluationError {
105                        message: "Execution timeout exceeded".to_string(),
106                    });
107                }
108            }
109
110            let mut rules = self.knowledge_base.get_rules().clone();
111            rules.sort_by(|a, b| b.salience.cmp(&a.salience));
112            let rules: Vec<_> = rules
113                .iter()
114                .filter(|rule| self.agenda_manager.should_evaluate_rule(rule))
115                .collect();
116
117            for rule in &rules {
118                if !rule.enabled {
119                    continue;
120                }
121                if !rule.is_active_at(timestamp) {
122                    continue;
123                }
124                if !self.agenda_manager.can_fire_rule(rule) {
125                    continue;
126                }
127                if !self.activation_group_manager.can_fire(rule) {
128                    continue;
129                }
130                if rule.no_loop && self.fired_rules_global.contains(&rule.name) {
131                    continue;
132                }
133                rules_evaluated += 1;
134                let condition_result = self.evaluate_conditions(&rule.conditions, facts)?;
135                if condition_result {
136                    for action in &rule.actions {
137                        self.execute_action(action, facts)?;
138                    }
139                    rules_fired += 1;
140                    any_rule_fired = true;
141                    fired_rules_in_cycle.insert(rule.name.clone());
142                    if rule.no_loop {
143                        self.fired_rules_global.insert(rule.name.clone());
144                    }
145                    self.agenda_manager.mark_rule_fired(rule);
146                    self.activation_group_manager.mark_fired(rule);
147                    // Gọi callback khi rule fired - truyền tham chiếu tới facts
148                    on_rule_fired(&rule.name, facts);
149                }
150            }
151            if !any_rule_fired {
152                break;
153            }
154            self.sync_workflow_agenda_activations();
155        }
156        let execution_time = start_time.elapsed();
157        Ok(crate::engine::GruleExecutionResult {
158            cycle_count,
159            rules_evaluated,
160            rules_fired,
161            execution_time,
162        })
163    }
164    /// Create a new RustRuleEngine with default configuration
165    pub fn new(knowledge_base: KnowledgeBase) -> Self {
166        Self {
167            knowledge_base,
168            config: EngineConfig::default(),
169            custom_functions: HashMap::new(),
170            action_handlers: HashMap::new(),
171            analytics: None,
172            agenda_manager: AgendaManager::new(),
173            activation_group_manager: ActivationGroupManager::new(),
174            fired_rules_global: std::collections::HashSet::new(),
175            workflow_engine: WorkflowEngine::new(),
176            plugin_manager: PluginManager::with_default_config(),
177        }
178    }
179
180    /// Create a new RustRuleEngine with custom configuration
181    pub fn with_config(knowledge_base: KnowledgeBase, config: EngineConfig) -> Self {
182        Self {
183            knowledge_base,
184            config,
185            custom_functions: HashMap::new(),
186            action_handlers: HashMap::new(),
187            analytics: None,
188            agenda_manager: AgendaManager::new(),
189            activation_group_manager: ActivationGroupManager::new(),
190            fired_rules_global: std::collections::HashSet::new(),
191            workflow_engine: WorkflowEngine::new(),
192            plugin_manager: PluginManager::with_default_config(),
193        }
194    }
195
196    /// Register a custom function
197    pub fn register_function<F>(&mut self, name: &str, func: F)
198    where
199        F: Fn(&[Value], &Facts) -> Result<Value> + Send + Sync + 'static,
200    {
201        self.custom_functions
202            .insert(name.to_string(), Box::new(func));
203    }
204
205    /// Register a custom action handler
206    pub fn register_action_handler<F>(&mut self, action_type: &str, handler: F)
207    where
208        F: Fn(&HashMap<String, Value>, &Facts) -> Result<()> + Send + Sync + 'static,
209    {
210        self.action_handlers
211            .insert(action_type.to_string(), Box::new(handler));
212    }
213
214    /// Enable analytics with custom configuration
215    pub fn enable_analytics(&mut self, analytics: RuleAnalytics) {
216        self.analytics = Some(analytics);
217    }
218
219    /// Reset global no-loop tracking (useful for testing or when facts change significantly)
220    pub fn reset_no_loop_tracking(&mut self) {
221        self.fired_rules_global.clear();
222    }
223
224    /// Disable analytics
225    pub fn disable_analytics(&mut self) {
226        self.analytics = None;
227    }
228
229    /// Get reference to analytics data
230    pub fn analytics(&self) -> Option<&RuleAnalytics> {
231        self.analytics.as_ref()
232    }
233
234    /// Enable debug mode for detailed execution logging
235    pub fn set_debug_mode(&mut self, enabled: bool) {
236        self.config.debug_mode = enabled;
237    }
238
239    /// Check if a custom function is registered
240    pub fn has_function(&self, name: &str) -> bool {
241        self.custom_functions.contains_key(name)
242    }
243
244    /// Check if a custom action handler is registered
245    pub fn has_action_handler(&self, action_type: &str) -> bool {
246        self.action_handlers.contains_key(action_type)
247    }
248
249    /// Get ready scheduled tasks
250    pub fn get_ready_tasks(&mut self) -> Vec<crate::engine::workflow::ScheduledTask> {
251        self.workflow_engine.get_ready_tasks()
252    }
253
254    /// Execute scheduled tasks that are ready
255    pub fn execute_scheduled_tasks(&mut self, facts: &Facts) -> Result<()> {
256        let ready_tasks = self.get_ready_tasks();
257        for task in ready_tasks {
258            if let Some(rule) = self
259                .knowledge_base
260                .get_rules()
261                .iter()
262                .find(|r| r.name == task.rule_name)
263            {
264                if self.config.debug_mode {
265                    println!("⚡ Executing scheduled task: {}", task.rule_name);
266                }
267
268                // Execute just this one rule if conditions match
269                if self.evaluate_conditions(&rule.conditions, facts)? {
270                    for action in &rule.actions {
271                        self.execute_action(action, facts)?;
272                    }
273                }
274            }
275        }
276        Ok(())
277    }
278
279    /// Activate agenda group
280    pub fn activate_agenda_group(&mut self, group: String) {
281        self.workflow_engine.activate_agenda_group(group.clone());
282        self.agenda_manager.set_focus(&group);
283    }
284
285    /// Get the knowledge base
286    pub fn knowledge_base(&self) -> &KnowledgeBase {
287        &self.knowledge_base
288    }
289
290    /// Get mutable reference to knowledge base
291    pub fn knowledge_base_mut(&mut self) -> &mut KnowledgeBase {
292        &mut self.knowledge_base
293    }
294
295    /// Sync workflow engine agenda activations with agenda manager
296    fn sync_workflow_agenda_activations(&mut self) {
297        // Process any pending agenda activations from workflow engine
298        while let Some(agenda_group) = self.workflow_engine.get_next_pending_agenda_activation() {
299            if self.config.debug_mode {
300                println!("🔄 Syncing workflow agenda activation: {}", agenda_group);
301            }
302            self.agenda_manager.set_focus(&agenda_group);
303        }
304    }
305
306    /// Set focus to a specific agenda group
307    pub fn set_agenda_focus(&mut self, group: &str) {
308        self.agenda_manager.set_focus(group);
309    }
310
311    /// Get the currently active agenda group
312    pub fn get_active_agenda_group(&self) -> &str {
313        self.agenda_manager.get_active_group()
314    }
315
316    /// Pop the agenda focus stack
317    pub fn pop_agenda_focus(&mut self) -> Option<String> {
318        self.agenda_manager.pop_focus()
319    }
320
321    /// Clear all agenda focus and return to MAIN
322    pub fn clear_agenda_focus(&mut self) {
323        self.agenda_manager.clear_focus();
324    }
325
326    /// Get all agenda groups that have rules
327    pub fn get_agenda_groups(&self) -> Vec<String> {
328        self.agenda_manager
329            .get_agenda_groups(&self.knowledge_base.get_rules())
330    }
331
332    /// Get all activation groups that have rules
333    pub fn get_activation_groups(&self) -> Vec<String> {
334        self.activation_group_manager
335            .get_activation_groups(&self.knowledge_base.get_rules())
336    }
337
338    // 🔄 Workflow Engine Methods
339
340    /// Start a new workflow
341    pub fn start_workflow(&mut self, workflow_name: Option<String>) -> String {
342        self.workflow_engine.start_workflow(workflow_name)
343    }
344
345    /// Get workflow statistics
346    pub fn get_workflow_stats(&self) -> crate::engine::workflow::WorkflowStats {
347        self.workflow_engine.get_workflow_stats()
348    }
349
350    /// Get workflow state by ID
351    pub fn get_workflow(
352        &self,
353        workflow_id: &str,
354    ) -> Option<&crate::engine::workflow::WorkflowState> {
355        self.workflow_engine.get_workflow(workflow_id)
356    }
357
358    /// Clean up completed workflows
359    pub fn cleanup_completed_workflows(&mut self, older_than: Duration) {
360        self.workflow_engine.cleanup_completed_workflows(older_than);
361    }
362
363    /// Execute workflow step by activating specific agenda group
364    pub fn execute_workflow_step(
365        &mut self,
366        agenda_group: &str,
367        facts: &Facts,
368    ) -> Result<GruleExecutionResult> {
369        // Set agenda focus to the specific group
370        self.set_agenda_focus(agenda_group);
371
372        // Execute rules in that group
373        let result = self.execute(facts)?;
374
375        // Process any workflow actions that were triggered
376        self.process_workflow_actions(facts)?;
377
378        Ok(result)
379    }
380
381    /// Execute a complete workflow by processing agenda groups sequentially
382    pub fn execute_workflow(
383        &mut self,
384        agenda_groups: Vec<&str>,
385        facts: &Facts,
386    ) -> Result<crate::engine::workflow::WorkflowResult> {
387        let start_time = Instant::now();
388        let mut total_steps = 0;
389
390        if self.config.debug_mode {
391            println!(
392                "🔄 Starting workflow execution with {} steps",
393                agenda_groups.len()
394            );
395        }
396
397        for (i, group) in agenda_groups.iter().enumerate() {
398            if self.config.debug_mode {
399                println!("📋 Executing workflow step {}: {}", i + 1, group);
400            }
401
402            let step_result = self.execute_workflow_step(group, facts)?;
403            total_steps += 1;
404
405            if step_result.rules_fired == 0 {
406                if self.config.debug_mode {
407                    println!("⏸️ No rules fired in step '{}', stopping workflow", group);
408                }
409                break;
410            }
411        }
412
413        let execution_time = start_time.elapsed();
414
415        Ok(crate::engine::workflow::WorkflowResult::success(
416            total_steps,
417            execution_time,
418        ))
419    }
420
421    /// Process workflow-related actions and scheduled tasks
422    fn process_workflow_actions(&mut self, facts: &Facts) -> Result<()> {
423        // Process agenda group activations
424        while let Some(group) = self.workflow_engine.get_next_agenda_group() {
425            self.set_agenda_focus(&group);
426        }
427
428        // Process scheduled tasks
429        let ready_tasks = self.workflow_engine.get_ready_tasks();
430        for task in ready_tasks {
431            if self.config.debug_mode {
432                println!("⚡ Executing scheduled task: {}", task.rule_name);
433            }
434
435            // Find and execute the specific rule
436            if let Some(rule) = self
437                .knowledge_base
438                .get_rules()
439                .iter()
440                .find(|r| r.name == task.rule_name)
441            {
442                // Execute just this one rule
443                if self.evaluate_conditions(&rule.conditions, facts)? {
444                    for action in &rule.actions {
445                        self.execute_action(action, facts)?;
446                    }
447                }
448            }
449        }
450
451        Ok(())
452    }
453
454    /// Execute all rules in the knowledge base against the given facts
455    pub fn execute(&mut self, facts: &Facts) -> Result<GruleExecutionResult> {
456        self.execute_at_time(facts, Utc::now())
457    }
458
459    /// Execute all rules at a specific timestamp (for date-effective/expires testing)
460    pub fn execute_at_time(
461        &mut self,
462        facts: &Facts,
463        timestamp: DateTime<Utc>,
464    ) -> Result<GruleExecutionResult> {
465        let start_time = Instant::now();
466        let mut cycle_count = 0;
467        let mut rules_evaluated = 0;
468        let mut rules_fired = 0;
469
470        // Process any pending agenda group activations from workflow engine
471        self.sync_workflow_agenda_activations();
472
473        if self.config.debug_mode {
474            println!(
475                "🚀 Starting rule execution with {} rules (agenda group: {})",
476                self.knowledge_base.get_rules().len(),
477                self.agenda_manager.get_active_group()
478            );
479        }
480
481        for cycle in 0..self.config.max_cycles {
482            cycle_count = cycle + 1;
483            let mut any_rule_fired = false;
484            let mut fired_rules_in_cycle = std::collections::HashSet::new();
485
486            // Reset activation groups for each cycle
487            self.activation_group_manager.reset_cycle();
488
489            // Check for timeout
490            if let Some(timeout) = self.config.timeout {
491                if start_time.elapsed() > timeout {
492                    return Err(RuleEngineError::EvaluationError {
493                        message: "Execution timeout exceeded".to_string(),
494                    });
495                }
496            }
497
498            // Get rule indices sorted by salience (highest first) - avoids cloning rules
499            let rule_indices = self.knowledge_base.get_rules_by_salience();
500
501            // Process rules by index to avoid cloning
502            for &rule_index in &rule_indices {
503                if let Some(rule) = self.knowledge_base.get_rule_by_index(rule_index) {
504                    if !rule.enabled {
505                        continue;
506                    }
507
508                    if !self.agenda_manager.should_evaluate_rule(&rule) {
509                        continue;
510                    }
511
512                    // Check date effective/expires
513                    if !rule.is_active_at(timestamp) {
514                        continue;
515                    }
516
517                    // Check agenda group constraints (lock-on-active)
518                    if !self.agenda_manager.can_fire_rule(&rule) {
519                        continue;
520                    }
521
522                    // Check activation group constraints (only one rule per group can fire)
523                    if !self.activation_group_manager.can_fire(&rule) {
524                        continue;
525                    }
526
527                    // Check no-loop: skip if already fired in this execution cycle
528                    if rule.no_loop && self.fired_rules_global.contains(&rule.name) {
529                        println!("⛔ Skipping '{}' due to no_loop (already fired)", rule.name);
530                        continue;
531                    }
532
533                    // Debug
534                    if self.config.debug_mode {
535                        println!(
536                            "🔍 Checking rule '{}' (no_loop: {})",
537                            rule.name, rule.no_loop
538                        );
539                    }
540
541                    let rule_start = std::time::Instant::now();
542
543                    // Count rule evaluation
544                    rules_evaluated += 1;
545
546                    // Evaluate rule conditions
547                    let condition_result = self.evaluate_conditions(&rule.conditions, facts)?;
548
549                    if self.config.debug_mode {
550                        println!(
551                            "   Rule '{}' condition result: {}",
552                            rule.name, condition_result
553                        );
554                    }
555
556                    // If conditions match, fire the rule
557                    if condition_result {
558                        if self.config.debug_mode {
559                            println!(
560                                "🔥 Firing rule '{}' (salience: {})",
561                                rule.name, rule.salience
562                            );
563                        }
564
565                        // Execute actions
566                        for action in &rule.actions {
567                            self.execute_action(action, facts)?;
568                        }
569
570                        let rule_duration = rule_start.elapsed();
571
572                        // Record analytics if enabled
573                        if let Some(analytics) = &mut self.analytics {
574                            analytics.record_execution(
575                                &rule.name,
576                                rule_duration,
577                                true,
578                                true,
579                                None,
580                                0,
581                            );
582                        }
583
584                        rules_fired += 1;
585                        any_rule_fired = true;
586
587                        // Track that this rule fired in this cycle (for cycle counting)
588                        fired_rules_in_cycle.insert(rule.name.clone());
589
590                        // Track that this rule fired globally (for no-loop support)
591                        if rule.no_loop {
592                            self.fired_rules_global.insert(rule.name.clone());
593                            if self.config.debug_mode {
594                                println!("  🔒 Marked '{}' as fired (no_loop tracking)", rule.name);
595                            }
596                        }
597
598                        // Mark rule as fired for agenda and activation group management
599                        self.agenda_manager.mark_rule_fired(&rule);
600                        self.activation_group_manager.mark_fired(&rule);
601                    } else {
602                        let rule_duration = rule_start.elapsed();
603
604                        // Record analytics for failed rules too
605                        if let Some(analytics) = &mut self.analytics {
606                            analytics.record_execution(
607                                &rule.name,
608                                rule_duration,
609                                false,
610                                false,
611                                None,
612                                0,
613                            );
614                        }
615                    }
616                } // Close if let Some(rule)
617            }
618
619            // If no rules fired in this cycle, we're done
620            if !any_rule_fired {
621                break;
622            }
623
624            // Sync any new workflow agenda activations at the end of each cycle
625            self.sync_workflow_agenda_activations();
626        }
627
628        let execution_time = start_time.elapsed();
629
630        Ok(GruleExecutionResult {
631            cycle_count,
632            rules_evaluated,
633            rules_fired,
634            execution_time,
635        })
636    }
637
638    /// Evaluate conditions against facts
639    fn evaluate_conditions(
640        &self,
641        conditions: &crate::engine::rule::ConditionGroup,
642        facts: &Facts,
643    ) -> Result<bool> {
644        use crate::engine::pattern_matcher::PatternMatcher;
645        use crate::engine::rule::ConditionGroup;
646
647        match conditions {
648            ConditionGroup::Single(condition) => self.evaluate_single_condition(condition, facts),
649            ConditionGroup::Compound {
650                left,
651                operator,
652                right,
653            } => {
654                let left_result = self.evaluate_conditions(left, facts)?;
655                let right_result = self.evaluate_conditions(right, facts)?;
656
657                match operator {
658                    crate::types::LogicalOperator::And => Ok(left_result && right_result),
659                    crate::types::LogicalOperator::Or => Ok(left_result || right_result),
660                    crate::types::LogicalOperator::Not => Err(RuleEngineError::EvaluationError {
661                        message: "NOT operator should not appear in compound conditions"
662                            .to_string(),
663                    }),
664                }
665            }
666            ConditionGroup::Not(condition) => {
667                let result = self.evaluate_conditions(condition, facts)?;
668                Ok(!result)
669            }
670            // Pattern matching conditions
671            ConditionGroup::Exists(condition) => {
672                Ok(PatternMatcher::evaluate_exists(condition, facts))
673            }
674            ConditionGroup::Forall(condition) => {
675                Ok(PatternMatcher::evaluate_forall(condition, facts))
676            }
677            ConditionGroup::Accumulate {
678                result_var,
679                source_pattern,
680                extract_field,
681                source_conditions,
682                function,
683                function_arg,
684            } => {
685                // Evaluate accumulate and inject result into facts
686                self.evaluate_accumulate(
687                    result_var,
688                    source_pattern,
689                    extract_field,
690                    source_conditions,
691                    function,
692                    function_arg,
693                    facts,
694                )?;
695                // After injecting result, return true to continue
696                Ok(true)
697            }
698
699            #[cfg(feature = "streaming")]
700            ConditionGroup::StreamPattern { .. } => {
701                // Stream patterns are handled by the streaming engine, not here
702                // For forward chaining context, return true to allow rule evaluation
703                Ok(true)
704            }
705        }
706    }
707
708    /// Evaluate accumulate condition and inject result into facts
709    #[allow(clippy::too_many_arguments)]
710    fn evaluate_accumulate(
711        &self,
712        _result_var: &str,
713        source_pattern: &str,
714        extract_field: &str,
715        source_conditions: &[String],
716        function: &str,
717        _function_arg: &str,
718        facts: &Facts,
719    ) -> Result<()> {
720        use crate::rete::accumulate::*;
721
722        // 1. Collect all facts matching the source pattern
723        let all_facts = facts.get_all_facts();
724        let mut matching_values = Vec::new();
725
726        // Find all facts that match the pattern (e.g., "Order.amount", "Order.status")
727        let pattern_prefix = format!("{}.", source_pattern);
728
729        // Group facts by instance (e.g., Order.1.amount, Order.1.status) - pre-sized for performance
730        let mut instances: HashMap<String, HashMap<String, Value>> = HashMap::with_capacity(16);
731
732        for (key, value) in &all_facts {
733            if key.starts_with(&pattern_prefix) {
734                // Extract instance ID if present (e.g., "Order.1.amount" -> "1")
735                let parts: Vec<&str> = key
736                    .strip_prefix(&pattern_prefix)
737                    .unwrap()
738                    .split('.')
739                    .collect();
740
741                if parts.len() >= 2 {
742                    // Has instance ID: Order.1.amount
743                    let instance_id = parts[0];
744                    let field_name = parts[1..].join(".");
745
746                    instances
747                        .entry(instance_id.to_string())
748                        .or_default()
749                        .insert(field_name, value.clone());
750                } else if parts.len() == 1 {
751                    // No instance ID: Order.amount (single instance)
752                    instances
753                        .entry("default".to_string())
754                        .or_default()
755                        .insert(parts[0].to_string(), value.clone());
756                }
757            }
758        }
759
760        // 2. Filter instances by source conditions
761        for (_instance_id, instance_facts) in instances {
762            // Check if this instance matches all source conditions
763            let mut matches = true;
764
765            for condition_str in source_conditions {
766                // Parse condition: "status == \"completed\""
767                if !self.evaluate_condition_string(condition_str, &instance_facts) {
768                    matches = false;
769                    break;
770                }
771            }
772
773            if matches {
774                // Extract the field value
775                if let Some(value) = instance_facts.get(extract_field) {
776                    matching_values.push(value.clone());
777                }
778            }
779        }
780
781        // 3. Run accumulate function
782        let result = match function {
783            "sum" => {
784                let mut state = SumFunction.init();
785                for value in &matching_values {
786                    state.accumulate(&self.value_to_fact_value(value));
787                }
788                self.fact_value_to_value(&state.get_result())
789            }
790            "count" => {
791                let mut state = CountFunction.init();
792                for value in &matching_values {
793                    state.accumulate(&self.value_to_fact_value(value));
794                }
795                self.fact_value_to_value(&state.get_result())
796            }
797            "average" | "avg" => {
798                let mut state = AverageFunction.init();
799                for value in &matching_values {
800                    state.accumulate(&self.value_to_fact_value(value));
801                }
802                self.fact_value_to_value(&state.get_result())
803            }
804            "min" => {
805                let mut state = MinFunction.init();
806                for value in &matching_values {
807                    state.accumulate(&self.value_to_fact_value(value));
808                }
809                self.fact_value_to_value(&state.get_result())
810            }
811            "max" => {
812                let mut state = MaxFunction.init();
813                for value in &matching_values {
814                    state.accumulate(&self.value_to_fact_value(value));
815                }
816                self.fact_value_to_value(&state.get_result())
817            }
818            _ => {
819                return Err(RuleEngineError::EvaluationError {
820                    message: format!("Unknown accumulate function: {}", function),
821                });
822            }
823        };
824
825        // 4. Inject result into facts
826        // Use pattern.function as key to avoid collision
827        let result_key = format!("{}.{}", source_pattern, function);
828
829        facts.set(&result_key, result);
830
831        if self.config.debug_mode {
832            println!(
833                "    🧮 Accumulate result: {} = {:?}",
834                result_key,
835                facts.get(&result_key)
836            );
837        }
838
839        Ok(())
840    }
841
842    /// Helper: Convert Value to FactValue
843    fn value_to_fact_value(&self, value: &Value) -> crate::rete::facts::FactValue {
844        use crate::rete::facts::FactValue;
845        match value {
846            Value::Integer(i) => FactValue::Integer(*i),
847            Value::Number(n) => FactValue::Float(*n),
848            Value::String(s) => FactValue::String(s.clone()),
849            Value::Boolean(b) => FactValue::Boolean(*b),
850            _ => FactValue::String(value.to_string()),
851        }
852    }
853
854    /// Helper: Convert FactValue to Value
855    fn fact_value_to_value(&self, fact_value: &crate::rete::facts::FactValue) -> Value {
856        use crate::rete::facts::FactValue;
857        match fact_value {
858            FactValue::Integer(i) => Value::Integer(*i),
859            FactValue::Float(f) => Value::Number(*f),
860            FactValue::String(s) => Value::String(s.clone()),
861            FactValue::Boolean(b) => Value::Boolean(*b),
862            FactValue::Array(_) => Value::String(format!("{:?}", fact_value)),
863            FactValue::Null => Value::String("null".to_string()),
864        }
865    }
866
867    /// Helper: Evaluate a condition string against facts
868    fn evaluate_condition_string(&self, condition: &str, facts: &HashMap<String, Value>) -> bool {
869        // Simple condition parser: "field == value" or "field != value", etc.
870        let condition = condition.trim();
871
872        // Try to parse operator
873        let operators = ["==", "!=", ">=", "<=", ">", "<"];
874
875        for op in &operators {
876            if let Some(pos) = condition.find(op) {
877                let field = condition[..pos].trim();
878                let value_str = condition[pos + op.len()..]
879                    .trim()
880                    .trim_matches('"')
881                    .trim_matches('\'');
882
883                if let Some(field_value) = facts.get(field) {
884                    return self.compare_values(field_value, op, value_str);
885                } else {
886                    return false;
887                }
888            }
889        }
890
891        false
892    }
893
894    /// Helper: Compare values
895    fn compare_values(&self, field_value: &Value, operator: &str, value_str: &str) -> bool {
896        match field_value {
897            Value::String(s) => match operator {
898                "==" => s == value_str,
899                "!=" => s != value_str,
900                _ => false,
901            },
902            Value::Integer(i) => {
903                if let Ok(num) = value_str.parse::<i64>() {
904                    match operator {
905                        "==" => *i == num,
906                        "!=" => *i != num,
907                        ">" => *i > num,
908                        "<" => *i < num,
909                        ">=" => *i >= num,
910                        "<=" => *i <= num,
911                        _ => false,
912                    }
913                } else {
914                    false
915                }
916            }
917            Value::Number(n) => {
918                if let Ok(num) = value_str.parse::<f64>() {
919                    match operator {
920                        "==" => (*n - num).abs() < f64::EPSILON,
921                        "!=" => (*n - num).abs() >= f64::EPSILON,
922                        ">" => *n > num,
923                        "<" => *n < num,
924                        ">=" => *n >= num,
925                        "<=" => *n <= num,
926                        _ => false,
927                    }
928                } else {
929                    false
930                }
931            }
932            Value::Boolean(b) => {
933                if let Ok(bool_val) = value_str.parse::<bool>() {
934                    match operator {
935                        "==" => *b == bool_val,
936                        "!=" => *b != bool_val,
937                        _ => false,
938                    }
939                } else {
940                    false
941                }
942            }
943            _ => false,
944        }
945    }
946
947    /// Evaluate rule conditions - wrapper for evaluate_conditions for compatibility
948    fn evaluate_rule_conditions(
949        &self,
950        rule: &crate::engine::rule::Rule,
951        facts: &Facts,
952    ) -> Result<bool> {
953        self.evaluate_conditions(&rule.conditions, facts)
954    }
955
956    /// Check if a fact object has been retracted
957    fn is_retracted(&self, object_name: &str, facts: &Facts) -> bool {
958        let retract_key = format!("_retracted_{}", object_name);
959        matches!(facts.get(&retract_key), Some(Value::Boolean(true)))
960    }
961
962    /// Evaluate a single condition
963    fn evaluate_single_condition(
964        &self,
965        condition: &crate::engine::rule::Condition,
966        facts: &Facts,
967    ) -> Result<bool> {
968        use crate::engine::rule::ConditionExpression;
969
970        let result = match &condition.expression {
971            ConditionExpression::Field(field_name) => {
972                // Check if the fact object has been retracted
973                // Extract object name from field (e.g., "Session.expired" -> "Session")
974                if let Some(object_name) = field_name.split('.').next() {
975                    if self.is_retracted(object_name, facts) {
976                        if self.config.debug_mode {
977                            println!("    🗑️ Skipping retracted fact: {}", object_name);
978                        }
979                        return Ok(false);
980                    }
981                }
982
983                // Field condition - try nested first, then flat lookup
984                // If field not found, treat as Null for proper null checking
985                let field_value = facts
986                    .get_nested(field_name)
987                    .or_else(|| facts.get(field_name))
988                    .unwrap_or(Value::Null);
989
990                if self.config.debug_mode {
991                    println!(
992                        "    🔎 Evaluating field condition: {} {} {:?}",
993                        field_name,
994                        format!("{:?}", condition.operator).to_lowercase(),
995                        condition.value
996                    );
997                    println!("      Field value: {:?}", field_value);
998                }
999
1000                // condition.operator.evaluate(&value, &condition.value)
1001                // If the condition's right-hand value is a string that names another fact,
1002                // try to resolve that fact and use its value for comparison. This allows
1003                // rules like `L1 > L1Min` where the parser may have stored "L1Min"
1004                // as a string literal.
1005                let rhs = match &condition.value {
1006                    crate::types::Value::String(s) => {
1007                        // Try nested lookup first, then flat lookup
1008                        facts
1009                            .get_nested(s)
1010                            .or_else(|| facts.get(s))
1011                            .unwrap_or(crate::types::Value::String(s.clone()))
1012                    }
1013                    crate::types::Value::Expression(expr) => {
1014                        // Try to evaluate expression - could be a variable reference or arithmetic
1015                        match crate::expression::evaluate_expression(expr, facts) {
1016                            Ok(evaluated) => evaluated,
1017                            Err(_) => {
1018                                // If evaluation fails, try as simple variable lookup
1019                                facts
1020                                    .get_nested(expr)
1021                                    .or_else(|| facts.get(expr))
1022                                    .unwrap_or(crate::types::Value::Expression(expr.clone()))
1023                            }
1024                        }
1025                    }
1026                    _ => condition.value.clone(),
1027                };
1028
1029                if self.config.debug_mode {
1030                    println!("      Resolved RHS for comparison: {:?}", rhs);
1031                }
1032
1033                condition.operator.evaluate(&field_value, &rhs)
1034            }
1035            ConditionExpression::FunctionCall { name, args } => {
1036                // Function call condition
1037                if self.config.debug_mode {
1038                    println!(
1039                        "    🔎 Evaluating function condition: {}({:?}) {} {:?}",
1040                        name,
1041                        args,
1042                        format!("{:?}", condition.operator).to_lowercase(),
1043                        condition.value
1044                    );
1045                }
1046
1047                if let Some(function) = self.custom_functions.get(name) {
1048                    // Resolve arguments from facts
1049                    let arg_values: Vec<Value> = args
1050                        .iter()
1051                        .map(|arg| {
1052                            facts
1053                                .get_nested(arg)
1054                                .or_else(|| facts.get(arg))
1055                                .unwrap_or(Value::String(arg.clone()))
1056                        })
1057                        .collect();
1058
1059                    // Call the function
1060                    match function(&arg_values, facts) {
1061                        Ok(result_value) => {
1062                            if self.config.debug_mode {
1063                                println!("      Function result: {:?}", result_value);
1064                            }
1065                            condition.operator.evaluate(&result_value, &condition.value)
1066                        }
1067                        Err(e) => {
1068                            if self.config.debug_mode {
1069                                println!("      Function error: {}", e);
1070                            }
1071                            false
1072                        }
1073                    }
1074                } else {
1075                    if self.config.debug_mode {
1076                        println!("      Function '{}' not found", name);
1077                    }
1078                    false
1079                }
1080            }
1081            ConditionExpression::Test { name, args } => {
1082                // Test CE condition - expects boolean result
1083                if self.config.debug_mode {
1084                    println!("    🧪 Evaluating test CE: test({}({:?}))", name, args);
1085                }
1086
1087                // Check if name is a registered custom function
1088                if let Some(function) = self.custom_functions.get(name) {
1089                    // Resolve arguments from facts
1090                    let arg_values: Vec<Value> = args
1091                        .iter()
1092                        .map(|arg| {
1093                            let resolved = facts
1094                                .get_nested(arg)
1095                                .or_else(|| facts.get(arg))
1096                                .unwrap_or(Value::String(arg.clone()));
1097                            if self.config.debug_mode {
1098                                println!("      Resolving arg '{}' -> {:?}", arg, resolved);
1099                            }
1100                            resolved
1101                        })
1102                        .collect();
1103
1104                    // Call the function
1105                    match function(&arg_values, facts) {
1106                        Ok(result_value) => {
1107                            if self.config.debug_mode {
1108                                println!("      Test result: {:?}", result_value);
1109                            }
1110                            // Test CE expects boolean result directly
1111                            match result_value {
1112                                Value::Boolean(b) => b,
1113                                Value::Integer(i) => i != 0,
1114                                Value::Number(f) => f != 0.0,
1115                                Value::String(s) => !s.is_empty(),
1116                                _ => false,
1117                            }
1118                        }
1119                        Err(e) => {
1120                            if self.config.debug_mode {
1121                                println!("      Test function error: {}", e);
1122                            }
1123                            false
1124                        }
1125                    }
1126                } else {
1127                    // Not a custom function - try to evaluate as arithmetic expression
1128                    // Format: "User.Age % 3 == 0" where name is the full expression
1129                    if self.config.debug_mode {
1130                        println!(
1131                            "      Trying to evaluate '{}' as arithmetic expression",
1132                            name
1133                        );
1134                    }
1135
1136                    // Try to parse and evaluate the expression
1137                    match self.evaluate_arithmetic_condition(name, facts) {
1138                        Ok(result) => {
1139                            if self.config.debug_mode {
1140                                println!("      Arithmetic expression result: {}", result);
1141                            }
1142                            result
1143                        }
1144                        Err(e) => {
1145                            if self.config.debug_mode {
1146                                println!("      Failed to evaluate expression: {}", e);
1147                                println!("      Test function '{}' not found", name);
1148                            }
1149                            false
1150                        }
1151                    }
1152                }
1153            }
1154            ConditionExpression::MultiField {
1155                field,
1156                operation,
1157                variable: _,
1158            } => {
1159                // Multi-field operation condition
1160                if self.config.debug_mode {
1161                    println!("    📦 Evaluating multi-field: {}.{}", field, operation);
1162                }
1163
1164                // Get the field value
1165                let field_value = facts.get_nested(field).or_else(|| facts.get(field));
1166
1167                if let Some(value) = field_value {
1168                    match operation.as_str() {
1169                        "empty" => {
1170                            matches!(value, Value::Array(arr) if arr.is_empty())
1171                        }
1172                        "not_empty" => {
1173                            matches!(value, Value::Array(arr) if !arr.is_empty())
1174                        }
1175                        "count" => {
1176                            if let Value::Array(arr) = value {
1177                                let count = Value::Integer(arr.len() as i64);
1178                                condition.operator.evaluate(&count, &condition.value)
1179                            } else {
1180                                false
1181                            }
1182                        }
1183                        "contains" => {
1184                            // Use existing contains operator
1185                            condition.operator.evaluate(&value, &condition.value)
1186                        }
1187                        _ => {
1188                            // Other operations (collect, first, last) not fully supported yet
1189                            // Return true to not block rule evaluation
1190                            if self.config.debug_mode {
1191                                println!(
1192                                    "      ⚠️ Operation '{}' not fully implemented yet",
1193                                    operation
1194                                );
1195                            }
1196                            true
1197                        }
1198                    }
1199                } else {
1200                    false
1201                }
1202            }
1203        };
1204
1205        if self.config.debug_mode {
1206            println!("      Result: {}", result);
1207        }
1208
1209        Ok(result)
1210    }
1211
1212    /// Execute an action
1213    fn execute_action(&mut self, action: &ActionType, facts: &Facts) -> Result<()> {
1214        match action {
1215            ActionType::Set { field, value } => {
1216                // Evaluate expression if value is an Expression
1217                let evaluated_value = match value {
1218                    Value::Expression(expr) => {
1219                        // Evaluate the expression with current facts
1220                        crate::expression::evaluate_expression(expr, facts)?
1221                    }
1222                    _ => value.clone(),
1223                };
1224
1225                // Try nested first, then fall back to flat key setting
1226                if facts.set_nested(field, evaluated_value.clone()).is_err() {
1227                    // If nested fails, use flat key
1228                    facts.set(field, evaluated_value.clone());
1229                }
1230                if self.config.debug_mode {
1231                    println!("  ✅ Set {field} = {evaluated_value:?}");
1232                }
1233            }
1234            ActionType::Log { message } => {
1235                println!("📋 LOG: {}", message);
1236            }
1237            ActionType::MethodCall {
1238                object,
1239                method,
1240                args,
1241            } => {
1242                let result = self.execute_method_call(object, method, args, facts)?;
1243                if self.config.debug_mode {
1244                    println!("  🔧 Called {object}.{method}({args:?}) -> {result}");
1245                }
1246            }
1247            ActionType::Retract { object } => {
1248                if self.config.debug_mode {
1249                    println!("  🗑️ Retracted {object}");
1250                }
1251                // Mark fact as retracted in working memory
1252                facts.set(&format!("_retracted_{}", object), Value::Boolean(true));
1253            }
1254            ActionType::Custom {
1255                action_type,
1256                params,
1257            } => {
1258                if let Some(handler) = self.action_handlers.get(action_type) {
1259                    if self.config.debug_mode {
1260                        println!(
1261                            "  🎯 Executing custom action: {action_type} with params: {params:?}"
1262                        );
1263                    }
1264
1265                    // Resolve parameter values from facts
1266                    let resolved_params = self.resolve_action_parameters(params, facts)?;
1267
1268                    // Execute the registered handler
1269                    handler(&resolved_params, facts)?;
1270                } else {
1271                    if self.config.debug_mode {
1272                        println!("  ⚠️ No handler registered for custom action: {action_type}");
1273                        println!(
1274                            "     Available handlers: {:?}",
1275                            self.action_handlers.keys().collect::<Vec<_>>()
1276                        );
1277                    }
1278
1279                    // Return error if no handler found
1280                    return Err(RuleEngineError::EvaluationError {
1281                        message: format!(
1282                            "No action handler registered for '{action_type}'. Use engine.register_action_handler() to add custom action handlers."
1283                        ),
1284                    });
1285                }
1286            }
1287            // 🔄 Workflow Actions
1288            ActionType::ActivateAgendaGroup { group } => {
1289                if self.config.debug_mode {
1290                    println!("  🎯 Activating agenda group: {}", group);
1291                }
1292                // Sync with both workflow engine and agenda manager immediately
1293                self.workflow_engine.activate_agenda_group(group.clone());
1294                self.agenda_manager.set_focus(group);
1295            }
1296            ActionType::ScheduleRule {
1297                rule_name,
1298                delay_ms,
1299            } => {
1300                if self.config.debug_mode {
1301                    println!(
1302                        "  ⏰ Scheduling rule '{}' to execute in {}ms",
1303                        rule_name, delay_ms
1304                    );
1305                }
1306                self.workflow_engine
1307                    .schedule_rule(rule_name.clone(), *delay_ms, None);
1308            }
1309            ActionType::CompleteWorkflow { workflow_name } => {
1310                if self.config.debug_mode {
1311                    println!("  ✅ Completing workflow: {}", workflow_name);
1312                }
1313                self.workflow_engine
1314                    .complete_workflow(workflow_name.clone());
1315            }
1316            ActionType::SetWorkflowData { key, value } => {
1317                if self.config.debug_mode {
1318                    println!("  💾 Setting workflow data: {} = {:?}", key, value);
1319                }
1320                // For now, we'll use a default workflow ID. Later this could be enhanced
1321                // to track current workflow context
1322                let workflow_id = "default_workflow";
1323                self.workflow_engine
1324                    .set_workflow_data(workflow_id, key.clone(), value.clone());
1325            }
1326            ActionType::Append { field, value } => {
1327                // Evaluate expression if value is an Expression
1328                let evaluated_value = match value {
1329                    Value::Expression(expr) => crate::expression::evaluate_expression(expr, facts)?,
1330                    _ => value.clone(),
1331                };
1332
1333                // Get current array or create new one
1334                let current_value = facts.get(field);
1335                let mut array = match current_value {
1336                    Some(Value::Array(arr)) => arr.clone(),
1337                    Some(_) => {
1338                        // Field exists but is not an array, create new array
1339                        if self.config.debug_mode {
1340                            println!("  ⚠️ Field {} is not an array, creating new array", field);
1341                        }
1342                        Vec::new()
1343                    }
1344                    None => Vec::new(),
1345                };
1346
1347                // Append value
1348                array.push(evaluated_value.clone());
1349
1350                // Set the updated array (try nested first, then flat)
1351                if facts
1352                    .set_nested(field, Value::Array(array.clone()))
1353                    .is_err()
1354                {
1355                    facts.set(field, Value::Array(array.clone()));
1356                }
1357
1358                if self.config.debug_mode {
1359                    println!("  ➕ Appended to {}: {:?}", field, evaluated_value);
1360                }
1361            }
1362        }
1363        Ok(())
1364    }
1365
1366    /// Evaluate arithmetic condition like "User.Age % 3 == 0"
1367    fn evaluate_arithmetic_condition(&self, expr: &str, facts: &Facts) -> Result<bool> {
1368        // Parse expression format: "left_expr operator right_value"
1369        // e.g., "User.Age % 3 == 0" or "User.Price * 2 > 100"
1370
1371        let operators = [">=", "<=", "==", "!=", ">", "<"];
1372        let mut split_pos = None;
1373        let mut found_op = "";
1374
1375        for op in &operators {
1376            if let Some(pos) = expr.rfind(op) {
1377                split_pos = Some(pos);
1378                found_op = op;
1379                break;
1380            }
1381        }
1382
1383        if split_pos.is_none() {
1384            return Err(RuleEngineError::EvaluationError {
1385                message: format!("No comparison operator found in expression: {}", expr),
1386            });
1387        }
1388
1389        let pos = split_pos.unwrap();
1390        let left_expr = expr[..pos].trim();
1391        let right_value = expr[pos + found_op.len()..].trim();
1392
1393        // Evaluate left side arithmetic expression
1394        let left_result = crate::expression::evaluate_expression(left_expr, facts)?;
1395
1396        // Parse right value
1397        let right_val = if let Ok(i) = right_value.parse::<i64>() {
1398            Value::Integer(i)
1399        } else if let Ok(f) = right_value.parse::<f64>() {
1400            Value::Number(f)
1401        } else {
1402            // Try to evaluate as expression or get from facts
1403            match crate::expression::evaluate_expression(right_value, facts) {
1404                Ok(v) => v,
1405                Err(_) => Value::String(right_value.to_string()),
1406            }
1407        };
1408
1409        // Compare values
1410        let operator =
1411            Operator::from_str(found_op).ok_or_else(|| RuleEngineError::InvalidOperator {
1412                operator: found_op.to_string(),
1413            })?;
1414
1415        Ok(operator.evaluate(&left_result, &right_val))
1416    }
1417
1418    /// Execute function call
1419    fn execute_function_call(
1420        &self,
1421        function: &str,
1422        args: &[Value],
1423        facts: &Facts,
1424    ) -> Result<String> {
1425        let function_lower = function.to_lowercase();
1426
1427        // Handle built-in utility functions
1428        match function_lower.as_str() {
1429            "log" | "print" | "println" => self.handle_log_function(args),
1430            "update" | "refresh" => self.handle_update_function(args),
1431            "now" | "timestamp" => self.handle_timestamp_function(),
1432            "random" => self.handle_random_function(args),
1433            "format" | "sprintf" => self.handle_format_function(args),
1434            "length" | "size" | "count" => self.handle_length_function(args),
1435            "sum" | "add" => self.handle_sum_function(args),
1436            "max" | "maximum" => self.handle_max_function(args),
1437            "min" | "minimum" => self.handle_min_function(args),
1438            "avg" | "average" => self.handle_average_function(args),
1439            "round" => self.handle_round_function(args),
1440            "floor" => self.handle_floor_function(args),
1441            "ceil" | "ceiling" => self.handle_ceil_function(args),
1442            "abs" | "absolute" => self.handle_abs_function(args),
1443            "contains" | "includes" => self.handle_contains_function(args),
1444            "startswith" | "begins_with" => self.handle_starts_with_function(args),
1445            "endswith" | "ends_with" => self.handle_ends_with_function(args),
1446            "lowercase" | "tolower" => self.handle_lowercase_function(args),
1447            "uppercase" | "toupper" => self.handle_uppercase_function(args),
1448            "trim" | "strip" => self.handle_trim_function(args),
1449            "split" => self.handle_split_function(args),
1450            "join" => self.handle_join_function(args),
1451            _ => {
1452                // Try to call custom user-defined function
1453                self.handle_custom_function(function, args, facts)
1454            }
1455        }
1456    }
1457
1458    /// Handle logging functions (log, print, println)
1459    fn handle_log_function(&self, args: &[Value]) -> Result<String> {
1460        let message = if args.is_empty() {
1461            "".to_string()
1462        } else if args.len() == 1 {
1463            args[0].to_string()
1464        } else {
1465            args.iter()
1466                .map(|v| v.to_string())
1467                .collect::<Vec<_>>()
1468                .join(" ")
1469        };
1470
1471        info!("📋 {}", message);
1472        Ok(message)
1473    }
1474
1475    /// Handle update/refresh functions
1476    fn handle_update_function(&self, args: &[Value]) -> Result<String> {
1477        if let Some(arg) = args.first() {
1478            Ok(format!("Updated: {}", arg.to_string()))
1479        } else {
1480            Ok("Updated".to_string())
1481        }
1482    }
1483
1484    /// Handle timestamp function
1485    fn handle_timestamp_function(&self) -> Result<String> {
1486        use std::time::{SystemTime, UNIX_EPOCH};
1487        let timestamp = SystemTime::now()
1488            .duration_since(UNIX_EPOCH)
1489            .map_err(|e| RuleEngineError::EvaluationError {
1490                message: format!("Failed to get timestamp: {}", e),
1491            })?
1492            .as_secs();
1493        Ok(timestamp.to_string())
1494    }
1495
1496    /// Handle random function
1497    fn handle_random_function(&self, args: &[Value]) -> Result<String> {
1498        use std::collections::hash_map::DefaultHasher;
1499        use std::hash::{Hash, Hasher};
1500
1501        // Simple pseudo-random based on current time (for deterministic behavior in tests)
1502        let mut hasher = DefaultHasher::new();
1503        std::time::SystemTime::now().hash(&mut hasher);
1504        let random_value = hasher.finish();
1505
1506        if args.is_empty() {
1507            Ok((random_value % 100).to_string()) // 0-99
1508        } else if let Some(Value::Number(max)) = args.first() {
1509            let max_val = *max as u64;
1510            Ok((random_value % max_val).to_string())
1511        } else {
1512            Ok(random_value.to_string())
1513        }
1514    }
1515
1516    /// Handle format function (simple sprintf-like)
1517    fn handle_format_function(&self, args: &[Value]) -> Result<String> {
1518        if args.is_empty() {
1519            return Ok("".to_string());
1520        }
1521
1522        let template = args[0].to_string();
1523        let values: Vec<String> = args[1..].iter().map(|v| v.to_string()).collect();
1524
1525        // Simple placeholder replacement: {0}, {1}, etc.
1526        let mut result = template;
1527        for (i, value) in values.iter().enumerate() {
1528            result = result.replace(&format!("{{{}}}", i), value);
1529        }
1530
1531        Ok(result)
1532    }
1533
1534    /// Handle length/size functions
1535    fn handle_length_function(&self, args: &[Value]) -> Result<String> {
1536        if let Some(arg) = args.first() {
1537            match arg {
1538                Value::String(s) => Ok(s.len().to_string()),
1539                Value::Array(arr) => Ok(arr.len().to_string()),
1540                Value::Object(obj) => Ok(obj.len().to_string()),
1541                _ => Ok("1".to_string()), // Single value has length 1
1542            }
1543        } else {
1544            Ok("0".to_string())
1545        }
1546    }
1547
1548    /// Handle sum function
1549    fn handle_sum_function(&self, args: &[Value]) -> Result<String> {
1550        let sum = args.iter().fold(0.0, |acc, val| match val {
1551            Value::Number(n) => acc + n,
1552            Value::Integer(i) => acc + (*i as f64),
1553            _ => acc,
1554        });
1555        Ok(sum.to_string())
1556    }
1557
1558    /// Handle max function
1559    fn handle_max_function(&self, args: &[Value]) -> Result<String> {
1560        let max = args.iter().fold(f64::NEG_INFINITY, |acc, val| match val {
1561            Value::Number(n) => acc.max(*n),
1562            Value::Integer(i) => acc.max(*i as f64),
1563            _ => acc,
1564        });
1565        Ok(max.to_string())
1566    }
1567
1568    /// Handle min function
1569    fn handle_min_function(&self, args: &[Value]) -> Result<String> {
1570        let min = args.iter().fold(f64::INFINITY, |acc, val| match val {
1571            Value::Number(n) => acc.min(*n),
1572            Value::Integer(i) => acc.min(*i as f64),
1573            _ => acc,
1574        });
1575        Ok(min.to_string())
1576    }
1577
1578    /// Handle average function
1579    fn handle_average_function(&self, args: &[Value]) -> Result<String> {
1580        if args.is_empty() {
1581            return Ok("0".to_string());
1582        }
1583
1584        let (sum, count) = args.iter().fold((0.0, 0), |(sum, count), val| match val {
1585            Value::Number(n) => (sum + n, count + 1),
1586            Value::Integer(i) => (sum + (*i as f64), count + 1),
1587            _ => (sum, count),
1588        });
1589
1590        if count > 0 {
1591            Ok((sum / count as f64).to_string())
1592        } else {
1593            Ok("0".to_string())
1594        }
1595    }
1596
1597    /// Handle mathematical functions
1598    fn handle_round_function(&self, args: &[Value]) -> Result<String> {
1599        if let Some(Value::Number(n)) = args.first() {
1600            Ok(n.round().to_string())
1601        } else if let Some(Value::Integer(i)) = args.first() {
1602            Ok(i.to_string())
1603        } else {
1604            Err(RuleEngineError::EvaluationError {
1605                message: "round() requires a numeric argument".to_string(),
1606            })
1607        }
1608    }
1609
1610    fn handle_floor_function(&self, args: &[Value]) -> Result<String> {
1611        if let Some(Value::Number(n)) = args.first() {
1612            Ok(n.floor().to_string())
1613        } else if let Some(Value::Integer(i)) = args.first() {
1614            Ok(i.to_string())
1615        } else {
1616            Err(RuleEngineError::EvaluationError {
1617                message: "floor() requires a numeric argument".to_string(),
1618            })
1619        }
1620    }
1621
1622    fn handle_ceil_function(&self, args: &[Value]) -> Result<String> {
1623        if let Some(Value::Number(n)) = args.first() {
1624            Ok(n.ceil().to_string())
1625        } else if let Some(Value::Integer(i)) = args.first() {
1626            Ok(i.to_string())
1627        } else {
1628            Err(RuleEngineError::EvaluationError {
1629                message: "ceil() requires a numeric argument".to_string(),
1630            })
1631        }
1632    }
1633
1634    fn handle_abs_function(&self, args: &[Value]) -> Result<String> {
1635        if let Some(Value::Number(n)) = args.first() {
1636            Ok(n.abs().to_string())
1637        } else if let Some(Value::Integer(i)) = args.first() {
1638            Ok(i.abs().to_string())
1639        } else {
1640            Err(RuleEngineError::EvaluationError {
1641                message: "abs() requires a numeric argument".to_string(),
1642            })
1643        }
1644    }
1645
1646    /// Handle string functions
1647    fn handle_contains_function(&self, args: &[Value]) -> Result<String> {
1648        if args.len() >= 2 {
1649            let haystack = args[0].to_string();
1650            let needle = args[1].to_string();
1651            Ok(haystack.contains(&needle).to_string())
1652        } else {
1653            Err(RuleEngineError::EvaluationError {
1654                message: "contains() requires 2 arguments".to_string(),
1655            })
1656        }
1657    }
1658
1659    fn handle_starts_with_function(&self, args: &[Value]) -> Result<String> {
1660        if args.len() >= 2 {
1661            let text = args[0].to_string();
1662            let prefix = args[1].to_string();
1663            Ok(text.starts_with(&prefix).to_string())
1664        } else {
1665            Err(RuleEngineError::EvaluationError {
1666                message: "startswith() requires 2 arguments".to_string(),
1667            })
1668        }
1669    }
1670
1671    fn handle_ends_with_function(&self, args: &[Value]) -> Result<String> {
1672        if args.len() >= 2 {
1673            let text = args[0].to_string();
1674            let suffix = args[1].to_string();
1675            Ok(text.ends_with(&suffix).to_string())
1676        } else {
1677            Err(RuleEngineError::EvaluationError {
1678                message: "endswith() requires 2 arguments".to_string(),
1679            })
1680        }
1681    }
1682
1683    fn handle_lowercase_function(&self, args: &[Value]) -> Result<String> {
1684        if let Some(arg) = args.first() {
1685            Ok(arg.to_string().to_lowercase())
1686        } else {
1687            Err(RuleEngineError::EvaluationError {
1688                message: "lowercase() requires 1 argument".to_string(),
1689            })
1690        }
1691    }
1692
1693    fn handle_uppercase_function(&self, args: &[Value]) -> Result<String> {
1694        if let Some(arg) = args.first() {
1695            Ok(arg.to_string().to_uppercase())
1696        } else {
1697            Err(RuleEngineError::EvaluationError {
1698                message: "uppercase() requires 1 argument".to_string(),
1699            })
1700        }
1701    }
1702
1703    fn handle_trim_function(&self, args: &[Value]) -> Result<String> {
1704        if let Some(arg) = args.first() {
1705            Ok(arg.to_string().trim().to_string())
1706        } else {
1707            Err(RuleEngineError::EvaluationError {
1708                message: "trim() requires 1 argument".to_string(),
1709            })
1710        }
1711    }
1712
1713    fn handle_split_function(&self, args: &[Value]) -> Result<String> {
1714        if args.len() >= 2 {
1715            let text = args[0].to_string();
1716            let delimiter = args[1].to_string();
1717            let parts: Vec<String> = text.split(&delimiter).map(|s| s.to_string()).collect();
1718            Ok(format!("{:?}", parts)) // Return as debug string for now
1719        } else {
1720            Err(RuleEngineError::EvaluationError {
1721                message: "split() requires 2 arguments".to_string(),
1722            })
1723        }
1724    }
1725
1726    fn handle_join_function(&self, args: &[Value]) -> Result<String> {
1727        if args.len() >= 2 {
1728            let delimiter = args[0].to_string();
1729            let parts: Vec<String> = args[1..].iter().map(|v| v.to_string()).collect();
1730            Ok(parts.join(&delimiter))
1731        } else {
1732            Err(RuleEngineError::EvaluationError {
1733                message: "join() requires at least 2 arguments".to_string(),
1734            })
1735        }
1736    }
1737
1738    /// Handle custom user-defined functions
1739    fn handle_custom_function(
1740        &self,
1741        function: &str,
1742        args: &[Value],
1743        facts: &Facts,
1744    ) -> Result<String> {
1745        // Check if we have a registered custom function
1746        if let Some(custom_func) = self.custom_functions.get(function) {
1747            if self.config.debug_mode {
1748                println!("🎯 Calling registered function: {}({:?})", function, args);
1749            }
1750
1751            match custom_func(args, facts) {
1752                Ok(result) => Ok(result.to_string()),
1753                Err(e) => Err(e),
1754            }
1755        } else {
1756            // Function not found - return error or placeholder
1757            if self.config.debug_mode {
1758                println!("⚠️ Custom function '{}' not registered", function);
1759            }
1760
1761            Err(RuleEngineError::EvaluationError {
1762                message: format!("Function '{}' is not registered. Use engine.register_function() to add custom functions.", function),
1763            })
1764        }
1765    }
1766
1767    /// Execute method call on object
1768    fn execute_method_call(
1769        &self,
1770        object_name: &str,
1771        method: &str,
1772        args: &[Value],
1773        facts: &Facts,
1774    ) -> Result<String> {
1775        // Get the object from facts
1776        let Some(object_value) = facts.get(object_name) else {
1777            return Err(RuleEngineError::EvaluationError {
1778                message: format!("Object '{}' not found in facts", object_name),
1779            });
1780        };
1781
1782        let method_lower = method.to_lowercase();
1783
1784        // Handle setter methods (set + property name)
1785        if method_lower.starts_with("set") && args.len() == 1 {
1786            return self.handle_setter_method(object_name, method, &args[0], object_value, facts);
1787        }
1788
1789        // Handle getter methods (get + property name)
1790        if method_lower.starts_with("get") && args.is_empty() {
1791            return self.handle_getter_method(object_name, method, &object_value);
1792        }
1793
1794        // Handle built-in methods
1795        match method_lower.as_str() {
1796            "tostring" => Ok(object_value.to_string()),
1797            "update" => {
1798                facts.add_value(object_name, object_value)?;
1799                Ok(format!("Updated {}", object_name))
1800            }
1801            "reset" => self.handle_reset_method(object_name, object_value, facts),
1802            _ => self.handle_property_access_or_fallback(
1803                object_name,
1804                method,
1805                args.len(),
1806                &object_value,
1807            ),
1808        }
1809    }
1810
1811    /// Handle setter method calls (setXxx)
1812    fn handle_setter_method(
1813        &self,
1814        object_name: &str,
1815        method: &str,
1816        new_value: &Value,
1817        mut object_value: Value,
1818        facts: &Facts,
1819    ) -> Result<String> {
1820        let property_name = Self::extract_property_name_from_setter(method);
1821
1822        match object_value {
1823            Value::Object(ref mut obj) => {
1824                obj.insert(property_name.clone(), new_value.clone());
1825                facts.add_value(object_name, object_value)?;
1826                Ok(format!(
1827                    "Set {} to {}",
1828                    property_name,
1829                    new_value.to_string()
1830                ))
1831            }
1832            _ => Err(RuleEngineError::EvaluationError {
1833                message: format!("Cannot call setter on non-object type: {}", object_name),
1834            }),
1835        }
1836    }
1837
1838    /// Handle getter method calls (getXxx)
1839    fn handle_getter_method(
1840        &self,
1841        object_name: &str,
1842        method: &str,
1843        object_value: &Value,
1844    ) -> Result<String> {
1845        let property_name = Self::extract_property_name_from_getter(method);
1846
1847        match object_value {
1848            Value::Object(obj) => {
1849                if let Some(value) = obj.get(&property_name) {
1850                    Ok(value.to_string())
1851                } else {
1852                    Err(RuleEngineError::EvaluationError {
1853                        message: format!(
1854                            "Property '{}' not found on object '{}'",
1855                            property_name, object_name
1856                        ),
1857                    })
1858                }
1859            }
1860            _ => Err(RuleEngineError::EvaluationError {
1861                message: format!("Cannot call getter on non-object type: {}", object_name),
1862            }),
1863        }
1864    }
1865
1866    /// Handle reset method call
1867    fn handle_reset_method(
1868        &self,
1869        object_name: &str,
1870        mut object_value: Value,
1871        facts: &Facts,
1872    ) -> Result<String> {
1873        match object_value {
1874            Value::Object(ref mut obj) => {
1875                obj.clear();
1876                facts.add_value(object_name, object_value)?;
1877                Ok(format!("Reset {}", object_name))
1878            }
1879            _ => Err(RuleEngineError::EvaluationError {
1880                message: format!("Cannot reset non-object type: {}", object_name),
1881            }),
1882        }
1883    }
1884
1885    /// Handle property access or fallback to generic method call
1886    fn handle_property_access_or_fallback(
1887        &self,
1888        object_name: &str,
1889        method: &str,
1890        arg_count: usize,
1891        object_value: &Value,
1892    ) -> Result<String> {
1893        if let Value::Object(obj) = object_value {
1894            // Try exact property name match
1895            if let Some(value) = obj.get(method) {
1896                return Ok(value.to_string());
1897            }
1898
1899            // Try capitalized property name
1900            let capitalized_method = Self::capitalize_first_letter(method);
1901            if let Some(value) = obj.get(&capitalized_method) {
1902                return Ok(value.to_string());
1903            }
1904        }
1905
1906        // Fallback to generic response
1907        Ok(format!(
1908            "Called {}.{} with {} args",
1909            object_name, method, arg_count
1910        ))
1911    }
1912
1913    /// Extract property name from setter method (setXxx -> Xxx)
1914    fn extract_property_name_from_setter(method: &str) -> String {
1915        let property_name = &method[3..]; // Remove "set" prefix
1916        Self::capitalize_first_letter(property_name)
1917    }
1918
1919    /// Extract property name from getter method (getXxx -> Xxx)
1920    fn extract_property_name_from_getter(method: &str) -> String {
1921        let property_name = &method[3..]; // Remove "get" prefix
1922        Self::capitalize_first_letter(property_name)
1923    }
1924
1925    /// Helper function to capitalize first letter of a string
1926    fn capitalize_first_letter(s: &str) -> String {
1927        if s.is_empty() {
1928            return String::new();
1929        }
1930        let mut chars = s.chars();
1931        match chars.next() {
1932            None => String::new(),
1933            Some(first) => first.to_uppercase().collect::<String>() + chars.as_str(),
1934        }
1935    }
1936
1937    /// Resolve action parameters by replacing fact references with actual values
1938    fn resolve_action_parameters(
1939        &self,
1940        params: &HashMap<String, Value>,
1941        facts: &Facts,
1942    ) -> Result<HashMap<String, Value>> {
1943        let mut resolved = HashMap::new();
1944
1945        for (key, value) in params {
1946            let resolved_value = match value {
1947                Value::String(s) => {
1948                    // Check if string looks like a fact reference (contains dot)
1949                    if s.contains('.') {
1950                        // Try to get the value from facts
1951                        if let Some(fact_value) = facts.get_nested(s) {
1952                            fact_value
1953                        } else {
1954                            // If not found, keep original string
1955                            value.clone()
1956                        }
1957                    } else {
1958                        value.clone()
1959                    }
1960                }
1961                _ => value.clone(),
1962            };
1963            resolved.insert(key.clone(), resolved_value);
1964        }
1965
1966        Ok(resolved)
1967    }
1968
1969    // 🔌 Plugin System Methods
1970
1971    /// Load a plugin into the engine
1972    pub fn load_plugin(
1973        &mut self,
1974        plugin: std::sync::Arc<dyn crate::engine::plugin::RulePlugin>,
1975    ) -> Result<()> {
1976        // First register the plugin actions with this engine
1977        plugin.register_actions(self)?;
1978        plugin.register_functions(self)?;
1979
1980        // Then store it in the plugin manager
1981        self.plugin_manager.load_plugin(plugin)
1982    }
1983
1984    /// Unload a plugin from the engine
1985    pub fn unload_plugin(&mut self, name: &str) -> Result<()> {
1986        self.plugin_manager.unload_plugin(name)
1987    }
1988
1989    /// Hot reload a plugin
1990    pub fn hot_reload_plugin(
1991        &mut self,
1992        name: &str,
1993        new_plugin: std::sync::Arc<dyn crate::engine::plugin::RulePlugin>,
1994    ) -> Result<()> {
1995        // Unload old plugin
1996        self.plugin_manager.unload_plugin(name)?;
1997
1998        // Register new plugin actions
1999        new_plugin.register_actions(self)?;
2000        new_plugin.register_functions(self)?;
2001
2002        // Load new plugin
2003        self.plugin_manager.load_plugin(new_plugin)
2004    }
2005
2006    /// Get plugin information
2007    pub fn get_plugin_info(&self, name: &str) -> Option<&crate::engine::plugin::PluginMetadata> {
2008        self.plugin_manager.get_plugin_info(name)
2009    }
2010
2011    /// List all loaded plugins
2012    pub fn list_plugins(&self) -> Vec<PluginInfo> {
2013        self.plugin_manager.list_plugins()
2014    }
2015
2016    /// Get plugin statistics
2017    pub fn get_plugin_stats(&self) -> PluginStats {
2018        self.plugin_manager.get_stats()
2019    }
2020
2021    /// Check health of all plugins
2022    pub fn plugin_health_check(&mut self) -> HashMap<String, crate::engine::plugin::PluginHealth> {
2023        self.plugin_manager.plugin_health_check()
2024    }
2025
2026    /// Configure plugin manager
2027    pub fn configure_plugins(&mut self, config: PluginConfig) {
2028        self.plugin_manager = PluginManager::new(config);
2029    }
2030}