lib/qr_nbu/validators/display.ex

defmodule QRNBU.Validators.Display do
  @moduledoc """
  Validator for display text in QR codes.

  Validates display strings shown to users when scanning QR codes.
  """

  alias QRNBU.Encoders.Charset

  @max_length 140

  @doc """
  Validates display text.

  ## Options
  - `:encoding` - Character encoding `:utf8` or `:cp1251` (default: `:utf8`)

  ## Rules
  - Maximum 140 characters
  - Must be valid in specified encoding

  ## Examples

      iex> QRNBU.Validators.Display.validate("Оплата послуг", encoding: :utf8)
      {:ok, "Оплата послуг"}

      iex> QRNBU.Validators.Display.validate("")
      {:error, "Display text cannot be empty"}

      iex> QRNBU.Validators.Display.validate(String.duplicate("A", 141))
      {:error, "Display text must not exceed 140 characters"}
  """
  @spec validate(String.t(), keyword()) :: {:ok, String.t()} | {:error, String.t()}
  def validate(display, opts \\ [])

  def validate(display, opts) when is_binary(display) do
    encoding = Keyword.get(opts, :encoding, :utf8)

    cond do
      String.trim(display) == "" ->
        {:error, "Display text cannot be empty"}

      String.length(display) > @max_length ->
        {:error, "Display text must not exceed #{@max_length} characters"}

      true ->
        case Charset.encode(display, encoding) do
          {:ok, _, _} -> {:ok, display}
          {:error, reason} -> {:error, reason}
        end
    end
  end

  def validate(_, _), do: {:error, "Display text must be a string"}
end