class Discharger::SetupRunner::ConditionEvaluator

def evaluate(condition, context = {})

def evaluate(condition, context = {})
  return true if condition.nil? || condition.strip.empty?
  ast = Prism.parse(condition).value
  raise "Parse error" unless ast
  evaluate_node(ast)
rescue => e
  log_warning("Condition evaluation failed: #{e.message}")
  false
end

def evaluate_node(node)

def evaluate_node(node)
  case node.type
  when :program_node
    # Evaluate the first statement in the program
    stmts = node.statements
    if stmts&.body&.any?
      evaluate_node(stmts.body.first)
    else
      true
    end
  when :statements_node
    # Evaluate the first statement
    if node.body.any?
      evaluate_node(node.body.first)
    else
      true
    end
  when :and_node
    left = evaluate_node(node.left)
    right = evaluate_node(node.right)
    left && right
  when :or_node
    left = evaluate_node(node.left)
    right = evaluate_node(node.right)
    left || right
  when :call_node
    # Handle method calls
    if node.receiver&.type == :constant_read_node
      case node.receiver.name
      when :ENV
        if node.name == :[]
          ENV[evaluate_node(node.arguments.arguments.first)]
        else
          raise "Unsafe ENV method: #{node.name}"
        end
      when :File
        case node.name
        when :exist?
          File.exist?(evaluate_node(node.arguments.arguments.first))
        when :directory?
          File.directory?(evaluate_node(node.arguments.arguments.first))
        when :file?
          File.file?(evaluate_node(node.arguments.arguments.first))
        else
          raise "Unsafe File method: #{node.name}"
        end
      when :Dir
        if node.name == :exist?
          Dir.exist?(evaluate_node(node.arguments.arguments.first))
        else
          raise "Unsafe Dir method: #{node.name}"
        end
      else
        raise "Unsafe method call: #{node.receiver.name}.#{node.name}"
      end
    elsif node.receiver&.type == :call_node
      # Handle chained calls like ENV['FOO'] == 'bar'
      if node.name == :==
        left = evaluate_node(node.receiver)
        right = evaluate_node(node.arguments.arguments.first)
        left == right
      elsif node.name == :!=
        left = evaluate_node(node.receiver)
        right = evaluate_node(node.arguments.arguments.first)
        left != right
      else
        raise "Unsafe operator: #{node.name}"
      end
    elsif node.receiver.nil?
      # Method call without receiver (like system)
      raise "Unsafe method call: #{node.name}"
    else
      raise "Unsafe method call: #{node.receiver&.name}.#{node.name}"
    end
  when :constant_read_node
    node.name
  when :string_node
    node.unescaped
  when :true_node # standard:disable Lint/BooleanSymbol
    true
  when :false_node # standard:disable Lint/BooleanSymbol
    false
  when :array_node
    node.elements.map { |el| evaluate_node(el) }
  when :symbol_node
    node.unescaped
  when :integer_node
    node.value
  when :x_string_node
    # Backtick commands - block for security
    raise "Unsafe backtick command"
  when :parentheses_node
    # Evaluate the expression inside parentheses
    evaluate_node(node.body)
  else
    raise "Unsafe node: #{node.type}"
  end
end

def log_warning(message)

def log_warning(message)
  if defined?(Rails)
    Rails.logger.warn(message)
  else
    warn("[SetupRunner] #{message}")
  end
end