import { BaseRule } from './BaseRule.js';
import { RelationalComparatorRule } from './RelationalComparatorRule.js';
import { QualitativeRelationalComparatorRule } from './QualitativeRelationalComparatorRule.js';

/**
 * RelationalComparatorRouter - Routes relational comparator rules to either
 * numeric or qualitative implementations based on rule configuration.
 * 
 * This router acts as the public entry point for relational comparator rules,
 * automatically delegating to the appropriate implementation:
 * - Numeric: Traditional numeric intervals with OWA fusion
 * - Qualitative: Qualitative scales with possibility theory
 * 
 * Configuration Detection:
 * - If rule.qualitative === true, uses qualitative implementation
 * - If leftOperand.scaleName or rightOperand.scaleName is present, uses qualitative
 * - Otherwise, uses numeric implementation (default)
 */
export class RelationalComparatorRouter extends BaseRule {
  constructor(arbiter, ruleEvaluator) {
    super(arbiter);
    this.ruleEvaluator = ruleEvaluator;
    
    // Instantiate both concrete implementations
    this.numericRule = new RelationalComparatorRule(arbiter, ruleEvaluator);
    this.qualitativeRule = new QualitativeRelationalComparatorRule(arbiter, ruleEvaluator);
  }

  /**
   * Route the rule evaluation to the appropriate implementation
   */
  _evaluateRule(userId, userKey, objectId, objectKey, rule, visited, currentRelation, options) {
    // Decide which rule to use based on the configuration
    if (this._isQualitativeRule(rule)) {
      return this.qualitativeRule._evaluateRule(userId, userKey, objectId, objectKey, rule, visited, currentRelation, options);
    } else {
      return this.numericRule._evaluateRule(userId, userKey, objectId, objectKey, rule, visited, currentRelation, options);
    }
  }

  /**
   * Determine if this rule should use qualitative implementation
   * @param {Object} rule - The rule configuration
   * @returns {boolean} True if qualitative implementation should be used
   */
  _isQualitativeRule(rule) {
    // Check explicit qualitative flag
    if (rule.qualitative === true) {
      return true;
    }

    // Check for scale names in operands
    if (rule.left?.scaleName || rule.right?.scaleName) {
      return true;
    }

    // Check for qualitative-specific properties (must be defined and not null)
    if (this._hasValidQualitativeProperty(rule.left?.decaySteps) || 
        this._hasValidQualitativeProperty(rule.right?.decaySteps) ||
        this._hasValidQualitativeProperty(rule.left?.baseBlurSteps) || 
        this._hasValidQualitativeProperty(rule.right?.baseBlurSteps) ||
        this._hasValidQualitativeProperty(rule.marginSteps)) {
      return true;
    }

    return false;
  }

  /**
   * Get the appropriate rule implementation for debugging/logging
   * @param {Object} rule - The rule configuration
   * @returns {string} 'qualitative' or 'numeric'
   */
  getImplementationType(rule) {
    return this._isQualitativeRule(rule) ? 'qualitative' : 'numeric';
  }

  /**
   * Check if a property value is a valid qualitative property (defined and not null)
   * @private
   */
  _hasValidQualitativeProperty(value) {
    return value !== undefined && value !== null;
  }
}
