module WolfCore::StringUtils

def base64_encoded?(str)

def base64_encoded?(str)
  return false unless str.is_a?(String) && str.length % 4 == 0
  base64_regex = %r{^[A-Za-z0-9+/]+={0,2}$}
  str.match?(base64_regex)
end

def camelcase_to_spaces(str)

def camelcase_to_spaces(str)
  return if str.nil?
  str.to_s.gsub(/([A-Z])/, ' \1').strip.downcase.capitalize
end

def clean_phone_number(phone)

def clean_phone_number(phone)
  return if phone.nil?
  cleaned_phone = phone.to_s.gsub(/\D/, "")
  cleaned_phone[-10, 10]
end

def deep_parse_json(input)

def deep_parse_json(input)
  while input.is_a?(String)
    begin
      input = JSON.parse(input)
    rescue JSON::ParserError
      break
    end
  end
  input || {}
end

def hash_str_to_json(hash_str)

def hash_str_to_json(hash_str)
  hash_str&.to_s&.gsub("=>", ":")&.gsub('\"', '"')&.gsub("{", "{")&.gsub("}", "}")&.gsub(/(\w+)(?=\s*:)/) do |key|
    "\"#{key}\""
  end
end

def jaro_winkler_similarity(string1, string2)

def jaro_winkler_similarity(string1, string2)
  str1 = string1.to_s.strip.downcase
  str2 = string2.to_s.strip.downcase
  return 1.0 if str1 == str2
  return 0.0 if str1.empty? || str2.empty?
  max_len = [str1.length, str2.length].max
  match_distance = [(max_len / 2) - 1, 0].max
  str1_matches = Array.new(str1.length, false)
  str2_matches = Array.new(str2.length, false)
  matches = 0
  str1.each_char.with_index do |char, i|
    start = [i - match_distance, 0].max
    finish = [i + match_distance + 1, str2.length].min
    (start...finish).each do |j|
      next if str2_matches[j]
      next unless str2[j] == char
      str1_matches[i] = true
      str2_matches[j] = true
      matches += 1
      break
    end
  end
  return 0.0 if matches.zero?
  transpositions = 0
  j = 0
  str1.each_char.with_index do |char, i|
    next unless str1_matches[i]
    j += 1 while j < str2.length && !str2_matches[j]
    break if j >= str2.length
    transpositions += 1 if str2[j] != char
    j += 1
  end
  transpositions /= 2.0
  jaro = (
    (matches / str1.length.to_f) +
    (matches / str2.length.to_f) +
    ((matches - transpositions) / matches)
  ) / 3.0
  prefix_length = 0
  max_prefix = 4
  while prefix_length < max_prefix &&
        prefix_length < str1.length &&
        prefix_length < str2.length &&
        str1[prefix_length] == str2[prefix_length]
    prefix_length += 1
  end
  jaro + (prefix_length * 0.1 * (1 - jaro))
end

def remove_blank_spaces(str)

def remove_blank_spaces(str)
  return if str.nil?
  str.to_s.gsub(/\s+/, "")
end

def remove_non_alphanumeric_chars(str, exceptions: nil)

def remove_non_alphanumeric_chars(str, exceptions: nil)
  return if str.nil?
  exceptions ||= []
  exceptions = Array(exceptions)
  escaped_exceptions = exceptions.map { |char| Regexp.escape(char) }.join
  regex = /[^a-zA-Z0-9#{escaped_exceptions}]/
  str.to_s.gsub(regex, "")
end

def split_address(address_string)

def split_address(address_string)
  address_string = address_string&.dup
  address_string ||= ""
  address = { street: nil, city: nil, state: nil, zip: nil }
  city_and_state_regex_found = false
  city_and_state_regex = /\b([A-Za-z\s]+),\s*([A-Za-z]{2})\b/
  zip_regex = /\d{5}(?:-\d{4})?$/
  street_regex = /\A([^,]+)/
  state_regex = /\b[A-Za-z]{2}\b/
  city_regex = /\b[a-zA-Z0-9\s]{2,}\b/
  if match_data = address_string.match(city_and_state_regex)
    address[:city] = match_data[1].strip
    address[:state] = match_data[2].strip
    address_string.sub!(city_and_state_regex, "")
    city_and_state_regex_found = true
  end
  if zip_match = address_string.match(zip_regex)
    address[:zip] = zip_match[0].strip
    address_string.sub!(zip_regex, "")
  end
  if street_match = address_string.match(street_regex)
    address[:street] = street_match[0].strip
    address[:street] = nil if address[:street].empty?
    address_string.sub!(street_regex, "")
  end
  return address if city_and_state_regex_found
  if state_match = address_string.match(state_regex)
    address[:state] = state_match[0].strip
    address_string.sub!(state_regex, "")
  end
  if city_match = address_string.match(city_regex)
    address[:city] = city_match[0].strip
    address_string.sub!(city_regex, "")
  end
  address
end

def split_name(full_name, name_range: nil, lastname_range: nil, if_one_word: nil)

def split_name(full_name, name_range: nil, lastname_range: nil, if_one_word: nil)
  if_one_word = {} unless if_one_word.is_a?(Hash)
  if_one_word.merge!(lastname: "-") if if_one_word[:lastname].nil?
  words = full_name.strip.split
  return { first_name: words[0], last_name: if_one_word[:lastname] } if words.length == 1
  return { first_name: words[0], last_name: words[1] } if words.length == 2
  name_range ||= 0..-2
  lastname_range ||= -1..-1
  name = words[name_range].join(" ")
  lastname = words[lastname_range].join(" ")
  { first_name: name, last_name: lastname }
end

def to_kebab_case(str)

def to_kebab_case(str)
  return if str.nil?
  str.to_s.gsub(/\s+/, "-").downcase
end

def to_snake_case(str)

def to_snake_case(str)
  return if str.nil?
  str.to_s.gsub(/\s+/, "_").downcase
end

def valid_json?(str)

def valid_json?(str)
  return false unless str.is_a?(String)
  JSON.parse(str)
  true
rescue JSON::ParserError
  false
end

def valid_url?(url)

def valid_url?(url)
  return false unless url.instance_of?(String)
  uri = URI.parse(url)
  uri.is_a?(URI::HTTP) || (uri.is_a?(URI::HTTPS) && !uri.host.nil?)
rescue URI::InvalidURIError
  false
end