defmodule MvWeb.MemberLive.Index.Formatter do
  @moduledoc """
  Formats custom field values for display in the member overview table.

  Handles different value types (string, integer, boolean, date, email) and
  formats them appropriately for display in the UI.
  """
  use Gettext, backend: MvWeb.Gettext
  alias MvWeb.Helpers.DateFormatter

  @doc """
  Formats a custom field value for display.

  Handles different input formats:
  - `nil` - Returns empty string
  - `%Ash.Union{}` - Extracts value and type from union type
  - Map (JSONB format) - Extracts type and value from map keys
  - Direct value - Uses custom_field.value_type to determine format

  ## Examples

      iex> format_custom_field_value(nil, %CustomField{value_type: :string})
      ""

      iex> format_custom_field_value("test", %CustomField{value_type: :string})
      "test"

      iex> format_custom_field_value(true, %CustomField{value_type: :boolean})
      "Yes"
  """
  def format_custom_field_value(nil, _custom_field), do: ""

  def format_custom_field_value(%Ash.Union{value: value, type: type}, custom_field) do
    format_value_by_type(value, type, custom_field)
  end

  def format_custom_field_value(value, custom_field) when is_map(value) do
    # Handle map format from JSONB
    type = Map.get(value, "type") || Map.get(value, "_union_type")
    val = Map.get(value, "value") || Map.get(value, "_union_value")
    format_value_by_type(val, type, custom_field)
  end

  def format_custom_field_value(value, custom_field) do
    format_value_by_type(value, custom_field.value_type, custom_field)
  end

  # Format value based on type

  defp format_value_by_type(value, :string, _), do: to_string(value)

  defp format_value_by_type(value, :integer, _), do: to_string(value)

  defp format_value_by_type(value, type, _) when type in [:string, :email] and is_binary(value) do
    # Return empty string if value is empty
    if String.trim(value) == "", do: "", else: value
  end

  defp format_value_by_type(value, :email, _), do: to_string(value)

  defp format_value_by_type(value, :boolean, _) when value == true, do: gettext("Yes")
  defp format_value_by_type(value, :boolean, _) when value == false, do: gettext("No")
  defp format_value_by_type(value, :boolean, _), do: to_string(value)

  defp format_value_by_type(%Date{} = date, :date, _), do: DateFormatter.format_date(date)

  defp format_value_by_type(value, :date, _) when is_binary(value) do
    case Date.from_iso8601(value) do
      {:ok, date} -> DateFormatter.format_date(date)
      _ -> value
    end
  end

  defp format_value_by_type(value, _type, _), do: to_string(value)
end
