input: Write a function to implement a fuzzy search algorithm in Python that can match strings with near similarities based on a given threshold. The function should take the query string, a list of choices, and the threshold value as parameters. It should return a list of strings from the choices that are within the given threshold distance from the query string using the Levenshtein distance metric. If the given list of choices is empty, the function should return an empty list.
  
  def find_matches(query, choices, threshold):
      # Convert query and choices to lower case
      query, choices = query.lower(), [choice.lower() for choice in choices]
      # Initialize empty list to store matches
      matches = []
      
      # Loop through each choice
      for choice in choices:
          # Calculate Levenshtein distance between query and choice
          distance = levenshtein_distance(query, choice)
          # If distance is less than threshold, append choice to matches
          if distance <= threshold:
              matches.append(choice)
      
      return matches
  
  # Assertions
  assert find_matches("apple", ["apple", "appel", "aple", "pineapple"], 2) == ["apple", "appel", "aple"]
  assert find_matches("banana", ["banana", "bannana", "bananana", "apple"], 3) == ["banana", "bannana", "bananana"]
  assert find_matches("strawberry", ["strawberry", "strawberr", "strawberryy", "berry"], 4) == ["strawberry", "strawberr", "strawberryy"]
  assert find_matches("grape", ["grape", "grap", "grapejuice"], 1) == ["grape", "grap"]
  assert find_matches("cherry", [], 2) == []
output: def find_matches(query, choices, threshold):
      query = query.lower()
      choices = [choice.lower() for choice in choices]
      matches = []
      
      for choice in choices:
          distance = levenshtein_distance(query, choice)
          if distance <= threshold:
              matches.append(choice)
      
      return matches