defmodule MvWeb.CustomFieldLive.FormComponent do
  @moduledoc """
  LiveComponent form for creating and editing custom fields (embedded in settings).

  ## Features
  - Create new custom field definitions
  - Edit existing custom fields
  - Select value type from supported types (only on create; immutable after creation)
  - Set required flag
  - Real-time validation

  ## Props
  - `custom_field` - The custom field to edit (nil for new)
  - `on_save` - Callback function to call when form is saved
  - `on_cancel` - Callback function to call when form is cancelled
  """
  use MvWeb, :live_component

  @impl true
  def render(assigns) do
    ~H"""
    <div id={@id} class="mb-8 border shadow-xl card border-base-300">
      <div class="card-body">
        <div class="flex items-center gap-4 mb-4">
          <.button
            type="button"
            phx-click="cancel"
            phx-target={@myself}
            aria-label={gettext("Back to settings")}
          >
            <.icon name="hero-arrow-left" class="w-4 h-4" />
          </.button>
          <h3 class="card-title">
            {if @custom_field, do: gettext("Edit Data Field"), else: gettext("New Data Field")}
          </h3>
        </div>

        <.form
          for={@form}
          id={@id <> "-form"}
          phx-change="validate"
          phx-submit="save"
          phx-target={@myself}
        >
          <.input field={@form[:name]} type="text" label={gettext("Name")} />

          <%= if @custom_field do %>
            <%!-- Show value_type as read-only input when editing (matches Member Field pattern) --%>
            <div
              class="tooltip tooltip-right"
              data-tip={gettext("Value type cannot be changed after creation")}
              aria-label={gettext("Value type cannot be changed after creation")}
            >
              <fieldset class="mb-2 fieldset">
                <label>
                  <span class="mb-1 label flex items-center gap-2">
                    {gettext("Value type")}
                    <.icon
                      name="hero-information-circle"
                      class="w-4 h-4 text-base-content/60 cursor-help"
                      aria-hidden="true"
                    />
                  </span>
                  <input
                    type="text"
                    name={@form[:value_type].name}
                    id={@form[:value_type].id}
                    value={MvWeb.Translations.FieldTypes.label(@custom_field.value_type)}
                    disabled
                    readonly
                    class="w-full input"
                  />
                </label>
              </fieldset>
            </div>
          <% else %>
            <%!-- Show value_type as select when creating --%>
            <.input
              field={@form[:value_type]}
              type="select"
              label={gettext("Value type")}
              options={
                Ash.Resource.Info.attribute(Mv.Membership.CustomField, :value_type).constraints[
                  :one_of
                ]
                |> Enum.map(fn type -> {MvWeb.Translations.FieldTypes.label(type), type} end)
              }
            />
          <% end %>

          <.input field={@form[:description]} type="text" label={gettext("Description")} />
          <.input field={@form[:required]} type="checkbox" label={gettext("Required")} />
          <.input
            field={@form[:show_in_overview]}
            type="checkbox"
            label={gettext("Show in overview")}
          />

          <div class="justify-end mt-4 card-actions">
            <.button type="button" phx-click="cancel" phx-target={@myself}>
              {gettext("Cancel")}
            </.button>
            <.button phx-disable-with={gettext("Saving...")} variant="primary">
              {gettext("Save Data Field")}
            </.button>
          </div>
        </.form>
      </div>
    </div>
    """
  end

  @impl true
  def update(assigns, socket) do
    {:ok,
     socket
     |> assign(assigns)
     |> assign_form()}
  end

  @impl true
  def handle_event("validate", %{"custom_field" => custom_field_params}, socket) do
    # Remove value_type from params when editing (it's immutable after creation)
    cleaned_params =
      if socket.assigns[:custom_field] do
        Map.delete(custom_field_params, "value_type")
      else
        custom_field_params
      end

    {:noreply,
     assign(socket, form: AshPhoenix.Form.validate(socket.assigns.form, cleaned_params))}
  end

  @impl true
  def handle_event("save", %{"custom_field" => custom_field_params}, socket) do
    # Actor must be passed from parent (IndexComponent); component socket has no current_user
    actor = socket.assigns[:actor]

    # Remove value_type from params when editing (it's immutable after creation)
    cleaned_params =
      if socket.assigns[:custom_field] do
        Map.delete(custom_field_params, "value_type")
      else
        custom_field_params
      end

    case MvWeb.LiveHelpers.submit_form(socket.assigns.form, cleaned_params, actor) do
      {:ok, custom_field} ->
        action =
          case socket.assigns.form.source.type do
            :create -> gettext("create")
            :update -> gettext("update")
            other -> to_string(other)
          end

        socket.assigns.on_save.(custom_field, action)
        {:noreply, socket}

      {:error, form} ->
        {:noreply, assign(socket, form: form)}
    end
  end

  @impl true
  def handle_event("cancel", _params, socket) do
    socket.assigns.on_cancel.()
    {:noreply, socket}
  end

  defp assign_form(%{assigns: %{custom_field: custom_field}} = socket) do
    form =
      if custom_field do
        AshPhoenix.Form.for_update(custom_field, :update, as: "custom_field")
      else
        AshPhoenix.Form.for_create(Mv.Membership.CustomField, :create, as: "custom_field")
      end

    assign(socket, form: to_form(form))
  end
end
