defmodule Mv.Membership.CustomFieldValueFormatter do
  @moduledoc """
  Neutral formatter for custom field values (e.g. CSV export).

  Same logic as the member overview Formatter but without Gettext or web helpers,
  so it can be used from the Membership context. For boolean: "Yes"/"No";
  for date: European format (dd.mm.yyyy).
  """
  @doc """
  Formats a custom field value for plain text (e.g. CSV).

  Handles nil, Ash.Union, JSONB map, and direct values. Uses custom_field.value_type
  for typing. Boolean -> "Yes"/"No", Date -> dd.mm.yyyy.
  """
  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
    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

  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
    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: "Yes"
  defp format_value_by_type(value, :boolean, _) when value == false, do: "No"
  defp format_value_by_type(value, :boolean, _), do: to_string(value)

  defp format_value_by_type(%Date{} = date, :date, _) do
    Calendar.strftime(date, "%d.%m.%Y")
  end

  defp format_value_by_type(value, :date, _) when is_binary(value) do
    case Date.from_iso8601(value) do
      {:ok, date} -> Calendar.strftime(date, "%d.%m.%Y")
      _ -> value
    end
  end

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