defmodule ZoeyscomputerWeb.GistLive.Select do
  use Phoenix.Component

  import Phoenix.HTML.Form, only: [input_value: 2]

  attr :id, :string, required: true
  attr :form, :any, required: true
  attr :field, :atom, required: true
  attr :options, :list, required: true
  attr :label, :string, default: nil
  attr :prompt, :string, default: "Select an option..."
  attr :class, :string, default: nil
  attr :disabled, :boolean, default: false

  def select(assigns) do
    selected_value = input_value(assigns.form, assigns.field)

    assigns = assign(assigns, :selected_value, selected_value)

    ~H"""
    <div class="relative" id={@id <> "-container"} phx-hook="SelectHook">
      <label :if={@label} for={@id} class="block text-sm font-bold mb-2 text-ctp-overlay1">
        <%= @label %>
      </label>

      <button
        type="button"
        id={@id <> "-trigger"}
        phx-update="ignore"
        class={[
          "relative w-full cursor-default rounded-md py-1.5 pl-3 pr-10 text-left",
          "bg-ctp-base text-ctp-text border-ctp-surface0 border",
          "focus:outline-none focus:ring-2 focus:ring-offset-0 focus:ctp-ring-lavender",
          "transition-colors duration-200",
          "disabled:cursor-not-allowed disabled:opacity-50"
        ]}
        disabled={@disabled}
      >
        <span class="block truncate" id={@id <> "-selected"}>
          <%= selected_option(@options, @selected_value) || @prompt %>
        </span>
        <span class="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2">
          <svg class="h-5 w-5 ctp-text-overlay0" viewBox="0 0 20 20" fill="currentColor">
            <path d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" />
          </svg>
        </span>
      </button>

      <div
        id={@id <> "-dropdown"}
        phx-update="ignore"
        class={
          [
            "absolute z-10 mt-1 w-full rounded-md py-1 shadow-lg",
            "bg-ctp-base border-ctp-surface0 border",
            # Initially hidden, toggled by JS
            "hidden"
          ]
        }
      >
        <div class="px-3 py-2">
          <input
            type="text"
            id={@id <> "-search"}
            placeholder="Search..."
            class={[
              "w-full rounded-md py-1.5 px-3",
              "bg-ctp-mantle text-ctp-text placeholder-ctp-overlay0",
              "focus:outline-none focus:ring-2 focus:ring-offset-0 focus:ring-ctp-lavender",
              "transition-colors duration-200"
            ]}
          />
        </div>

        <ul class="max-h-60 overflow-auto" id={@id <> "-options"} role="listbox" tabindex="-1">
          <%= for {label, value} <- @options do %>
            <li
              class={[
                "relative cursor-default select-none py-2 pl-3 pr-9",
                "text-ctp-text hover:bg-ctp-surface0",
                "transition-colors duration-200"
              ]}
              role="option"
              data-value={value}
              aria-selected={to_string(value) == to_string(@selected_value)}
            >
              <span class="block truncate"><%= label %></span>
              <%= if to_string(value) == to_string(@selected_value) do %>
                <span class="absolute inset-y-0 right-0 flex items-center pr-4 ctp-text-lavender">
                  <svg class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
                    <path
                      fill-rule="evenodd"
                      d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
                      clip-rule="evenodd"
                    />
                  </svg>
                </span>
              <% end %>
            </li>
          <% end %>
        </ul>
      </div>

      <input
        type="hidden"
        name={input_name(@form, @field)}
        id={input_id(@form, @field)}
        value={@selected_value}
      />
    </div>
    """
  end

  defp selected_option(_options, value) when is_nil(value), do: nil

  defp selected_option(options, value) do
    case Enum.find(options, fn {_label, val} -> to_string(val) == to_string(value) end) do
      {label, _value} -> label
      _ -> nil
    end
  end

  defp input_id(%{id: id}, field) when is_atom(field), do: "#{id}_#{field}"
  defp input_name(%{name: name}, field), do: "#{name}[#{field}]"
end
