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