lib/selecto_components/form/list_picker_operations.ex

defmodule SelectoComponents.Form.ListPickerOperations do
  @moduledoc """
  Handles list picker operations for SelectoComponents forms.

  This module contains the business logic for:
  - Adding items to picker lists (selected columns, order_by, group_by, aggregate)
  - Removing items from picker lists
  - Reordering items within picker lists (move up/down)
  - Updating view configuration after list changes
  """

  alias SelectoComponents.SafeAtom
  alias SelectoComponents.Views.Runtime, as: ViewRuntime

  @doc """
  Remove an item from a picker list in the view configuration.

  Returns the updated view_config with the item removed from the specified list.
  """
  def remove_item_from_list(view_config, view, list, item) do
    view = SafeAtom.to_view_mode(view)
    list = SafeAtom.to_list_name(list)

    original_list = view_config.views[view][list]

    filtered_list =
      Enum.filter(original_list, fn
        {id, _, _} when is_binary(id) -> id != item
        [id, _, _] when is_binary(id) -> id != item
        {id, _, _} -> to_string(id) != item
        [id, _, _] -> to_string(id) != item
        _ -> true
      end)

    # Update the view_config
    put_in(view_config.views[view][list], filtered_list)
  end

  @doc """
  Move an item up or down in a picker list.

  Direction should be "up" or "down".
  Returns the updated view_config with the item moved, or the original view_config if item not found.
  """
  def move_item_in_list(view_config, view, list, uuid, direction) do
    view = SafeAtom.to_view_mode(view)
    list = SafeAtom.to_list_name(list)

    item_list = view_config.views[view][list]

    item_index =
      Enum.find_index(item_list, fn
        {id, _, _} when is_binary(id) -> id == uuid
        [id, _, _] when is_binary(id) -> id == uuid
        {id, _, _} -> to_string(id) == uuid
        [id, _, _] -> to_string(id) == uuid
        _ -> false
      end)

    # Handle case where item not found
    if item_index == nil do
      view_config
    else
      {item, item_list} = List.pop_at(item_list, item_index)

      item_list =
        List.insert_at(
          item_list,
          case direction do
            "up" -> item_index - 1
            "down" -> item_index + 1
          end,
          item
        )

      put_in(view_config.views[view][list], item_list)
    end
  end

  @doc """
  Add an item to a picker list in the view configuration.

  Returns the updated view_config with the item appended to the specified list.
  """
  def add_item_to_list(view_config, view, list, item) do
    view = SafeAtom.to_view_mode(view)
    list = SafeAtom.to_list_name(list)

    # Get the current list
    current_list = view_config.views[view][list] || []

    # Append the new item
    updated_list = current_list ++ [item]

    # Update the view_config
    put_in(view_config.views[view][list], updated_list)
  end

  @doc """
  Send an update to the view form component after a list change.

  This ensures the UI reflects the latest view_config state.
  """
  def send_view_update(view_module, updated_view_config, socket_assigns) do
    {id, _mod, _, _} = view_module
    component_id = "view_#{id}_form"

    # Send update to the specific view form component
    Phoenix.LiveView.send_update(ViewRuntime.form_component(view_module),
      id: component_id,
      view_config: updated_view_config,
      columns: socket_assigns.columns,
      view: view_module,
      selecto: socket_assigns.selecto
    )
  end
end