input: Write a function to implement a fuzzy search algorithm in Python which can match strings with near similarities using Levenshtein distance. Given a query string, a list of choices, and a threshold for acceptable distance, the function should return a list of strings from choices that have a Levenshtein distance from the query less than or equal to the threshold. The function should convert all strings to lower case before calculating the distance, and if no matches are found, it 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
  
  assert find_matches("apple", ["Apple", "aple", "Appel", "Banana"], 2) == ["apple", "aple"]
  assert find_matches("Python", ["Puthin", "PTI", "JavaScript"], 3) == ["puthin", "pti"]
  assert find_matches("Fuzzy", ["Fuzzle", "uzzyF", "FuzzyMatch"], 1) == ["fuzzle", "fuzzymatch"]
  assert find_matches("AI", ["ai", "AI+", "ArtificialIntelligence"], 1) == ["ai", "ai+"]
  assert find_matches("Fashion", [], 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