/**
 * Condition evaluation for if_else and switch nodes.
 */

export interface ConditionRule {
  field: string;
  operator: string;
  value: string;
}

/**
 * Evaluate a single condition rule against a context value.
 */
export function evaluateRule(fieldValue: any, operator: string, compareValue: string): boolean {
  switch (operator) {
    case 'equals':
    case '==':
      return String(fieldValue) === compareValue;
    case 'notEquals':
    case '!=':
      return String(fieldValue) !== compareValue;
    case 'contains':
      return String(fieldValue).includes(compareValue);
    case 'notContains':
      return !String(fieldValue).includes(compareValue);
    case 'startsWith':
      return String(fieldValue).startsWith(compareValue);
    case 'endsWith':
      return String(fieldValue).endsWith(compareValue);
    case 'greaterThan':
    case '>':
      return Number(fieldValue) > Number(compareValue);
    case 'lessThan':
    case '<':
      return Number(fieldValue) < Number(compareValue);
    case 'greaterThanOrEqual':
    case '>=':
      return Number(fieldValue) >= Number(compareValue);
    case 'lessThanOrEqual':
    case '<=':
      return Number(fieldValue) <= Number(compareValue);
    case 'isEmpty':
      return fieldValue == null || fieldValue === '' || (Array.isArray(fieldValue) && fieldValue.length === 0);
    case 'isNotEmpty':
      return fieldValue != null && fieldValue !== '' && !(Array.isArray(fieldValue) && fieldValue.length === 0);
    case 'regex':
      try {
        return new RegExp(compareValue).test(String(fieldValue));
      } catch {
        return false;
      }
    default:
      return false;
  }
}

/**
 * Evaluate multiple condition rules with AND/OR combinator.
 */
export function evaluateConditions(
  conditions: ConditionRule[],
  contextData: Record<string, any>,
  combineOperation: 'AND' | 'OR' = 'AND',
): boolean {
  if (conditions.length === 0) return true;

  const results = conditions.map((rule) => {
    const fieldValue = getNestedValue(contextData, rule.field);
    return evaluateRule(fieldValue, rule.operator, rule.value);
  });

  return combineOperation === 'AND'
    ? results.every(Boolean)
    : results.some(Boolean);
}

/**
 * Evaluate a switch node — returns the matched case value or "default".
 */
export function evaluateSwitch(
  field: string,
  cases: Array<{ value: string; label: string }>,
  contextData: Record<string, any>,
): string {
  const fieldValue = String(getNestedValue(contextData, field) ?? '');
  const matched = cases.find((c) => c.value === fieldValue);
  return matched ? matched.value : 'default';
}

/**
 * Get a nested value from an object using dot-notation path.
 */
function getNestedValue(obj: Record<string, any>, path: string): any {
  const parts = path.split('.');
  let current: any = obj;
  for (const part of parts) {
    if (current == null) return undefined;
    current = current[part];
  }
  return current;
}
