defmodule Zoeyscomputer.IdGenerator do
  @moduledoc """
  Generates URL-friendly unique IDs
  """

  @alphabet "_-0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
  @size 7

  @doc """
  Generates a random ID with default length of 7 characters using URL-friendly characters.

  ## Examples
      iex> IdGenerator.generate()
      "f3k9m4z"
  """
  def generate(size \\ @size) do
    alphabet_length = String.length(@alphabet)

    1..size
    |> Enum.reduce([], fn _, acc ->
      position = :rand.uniform(alphabet_length) - 1
      char = String.at(@alphabet, position)
      [char | acc]
    end)
    |> Enum.join("")
  end

  @doc """
  Generates a random ID and ensures it's unique by checking against a provided function.

  ## Examples
      iex> IdGenerator.generate_unique(&MyApp.id_exists?/1)
      "x7k9m4z"
  """
  def generate_unique(exists_fn, attempts \\ 0)

  def generate_unique(exists_fn, attempts) when attempts < 5 do
    id = generate()

    if exists_fn.(id) do
      generate_unique(exists_fn, attempts + 1)
    else
      id
    end
  end

  def generate_unique(_exists_fn, _attempts) do
    raise "Failed to generate unique ID after 5 attempts"
  end
end
