defmodule WhoNeedHelpWeb.ActivityLive.New do
  use WhoNeedHelpWeb, :live_view

  alias WhoNeedHelp.{Activities, Catalog}
  alias WhoNeedHelp.Activities.Activity
  alias WhoNeedHelpWeb.FormParams

  @impl true
  def mount(_params, _session, socket) do
    {:ok,
     socket
     |> assign(:page_title, gettext("Create activity"))
     |> assign(:categories, Catalog.list_categories(:activity))
     |> assign(:selected_category, nil)
     |> assign(:structured_fields, [])
     |> assign(:form, to_form(Activities.change_activity(%Activity{})))}
  end

  @impl true
  def handle_event("validate", %{"activity" => params}, socket) do
    params = FormParams.drop_unused_structured_fields(params)

    changeset =
      %Activity{}
      |> Activities.change_activity(normalize_datetimes(params))
      |> Map.put(:action, :validate)

    {:noreply,
     socket
     |> assign(:form, to_form(changeset))
     |> assign_category(params)}
  end

  def handle_event("save", %{"activity" => params}, socket) do
    params = FormParams.drop_unused_structured_fields(params)

    case Activities.create_activity(socket.assigns.current_scope, normalize_datetimes(params)) do
      {:ok, activity} ->
        {:noreply,
         socket
         |> put_flash(:info, gettext("Activity published. You approve every participant."))
         |> push_navigate(to: ~p"/activities/#{activity.id}")}

      {:error, %Ecto.Changeset{} = changeset} ->
        {:noreply,
         socket
         |> assign(:form, to_form(changeset))
         |> assign_category(params)}

      {:error, reason} ->
        {:noreply, put_flash(socket, :error, error_message(reason))}
    end
  end

  defp normalize_datetimes(params) do
    Enum.reduce(["starts_at", "join_deadline"], params, fn key, normalized ->
      case normalized[key] do
        value when is_binary(value) ->
          parsed =
            case NaiveDateTime.from_iso8601(
                   value <> if(String.length(value) == 16, do: ":00", else: "")
                 ) do
              {:ok, naive} -> DateTime.from_naive!(naive, "Etc/UTC")
              _ -> value
            end

          Map.put(normalized, key, parsed)

        _ ->
          normalized
      end
    end)
  end

  defp assign_category(socket, params) do
    category = Enum.find(socket.assigns.categories, &(&1.id == params["category_id"]))

    socket
    |> assign(:selected_category, category)
    |> assign(:structured_fields, if(category, do: Catalog.structured_fields(category), else: []))
  end

  defp field_label(field, locale) do
    labels = field["label"] || %{}
    labels[to_string(locale)] || labels["en"] || field["key"]
  end

  defp option_label(option, locale) when is_map(option) do
    labels = option["label"] || %{}
    labels[to_string(locale)] || labels["en"] || option["value"]
  end

  defp option_label(option, _locale), do: to_string(option)
  defp option_value(option) when is_map(option), do: option["value"]
  defp option_value(option), do: option

  defp structured_value(form, key) do
    case Map.get(form.params, "structured_data") do
      structured_data when is_map(structured_data) -> Map.get(structured_data, key)
      _invalid_or_missing -> nil
    end
  end

  defp error_message(:account_not_eligible),
    do: gettext("Confirm your email and ensure your account is active before publishing.")

  defp error_message(:rate_limited),
    do: gettext("Too many actions in the configured time window.")

  defp error_message(_reason), do: gettext("Could not publish the activity. Please try again.")

  @impl true
  def render(assigns) do
    ~H"""
    <Layouts.app flash={@flash} current_scope={@current_scope}>
      <div class="mx-auto max-w-3xl">
        <.link navigate={~p"/activities"} class="btn btn-ghost btn-sm mb-4">
          {gettext("← Back to activities")}
        </.link>
        <h1 class="text-4xl font-black">{gettext("Create an activity")}</h1>
        <p class="mt-2 text-base-content/65">
          {gettext("Publish a clear public plan. Join requests stay pending until you approve them.")}
        </p>

        <div class="alert alert-warning mt-6 text-sm">
          <.icon name="hero-exclamation-triangle" class="size-5" />
          <span>
            {gettext(
              "Use a public first meeting point. Do not publish a home address, access code, travel document, or other sensitive information."
            )}
          </span>
        </div>

        <.form
          for={@form}
          id="activity-form"
          phx-change="validate"
          phx-submit="save"
          class="mt-8 space-y-5"
        >
          <.input
            field={@form[:category_id]}
            type="select"
            label={gettext("Activity type")}
            prompt={gettext("Choose activity")}
            options={
              Enum.map(
                @categories,
                &{Catalog.category_path(&1, Gettext.get_locale(WhoNeedHelpWeb.Gettext)), &1.id}
              )
            }
          />
          <p
            :if={@selected_category}
            id="selected-activity-category-description"
            class="-mt-3 text-sm text-base-content/60"
          >
            {Catalog.Category.description(
              @selected_category,
              Gettext.get_locale(WhoNeedHelpWeb.Gettext)
            )}
          </p>

          <div
            :if={@structured_fields != []}
            class="space-y-4 rounded-2xl border border-info/30 bg-info/5 p-5"
          >
            <h2 class="font-bold">{gettext("Activity details")}</h2>
            <div :for={field <- @structured_fields}>
              <label class="fieldset">
                <span class="label">
                  {field_label(field, Gettext.get_locale(WhoNeedHelpWeb.Gettext))}
                </span>
                <select
                  :if={field["type"] == "select"}
                  name={"activity[structured_data][#{field["key"]}]"}
                  required={field["required"] == true}
                  class="select w-full"
                >
                  <option value="">{gettext("Choose…")}</option>
                  <option
                    :for={option <- field["options"] || []}
                    value={option_value(option)}
                    selected={
                      to_string(structured_value(@form, field["key"])) ==
                        to_string(option_value(option))
                    }
                  >
                    {option_label(option, Gettext.get_locale(WhoNeedHelpWeb.Gettext))}
                  </option>
                </select>
                <input
                  :if={field["type"] == "text"}
                  type="text"
                  name={"activity[structured_data][#{field["key"]}]"}
                  value={structured_value(@form, field["key"])}
                  required={field["required"] == true}
                  maxlength={field["max_length"]}
                  class="input w-full"
                />
                <select
                  :if={field["type"] == "boolean"}
                  name={"activity[structured_data][#{field["key"]}]"}
                  required={field["required"] == true}
                  class="select w-full"
                >
                  <option value="">{gettext("Choose…")}</option>
                  <option value="true" selected={structured_value(@form, field["key"]) == "true"}>
                    {gettext("Yes")}
                  </option>
                  <option value="false" selected={structured_value(@form, field["key"]) == "false"}>
                    {gettext("No")}
                  </option>
                </select>
              </label>
            </div>
            <p :for={{message, _opts} <- @form[:structured_data].errors} class="text-sm text-error">
              {message}
            </p>
          </div>

          <.input
            field={@form[:title]}
            label={gettext("Short title")}
            placeholder={gettext("Coffee and conversation")}
          />
          <.input
            field={@form[:description]}
            type="textarea"
            label={gettext("Plan and expectations")}
            placeholder={
              gettext("Describe the public plan, approximate duration, and who might enjoy it.")
            }
          />
          <div class="grid gap-4 md:grid-cols-2">
            <.input
              field={@form[:starts_at]}
              type="datetime-local"
              label={gettext("Starts at (UTC)")}
            />
            <.input
              field={@form[:join_deadline]}
              type="datetime-local"
              label={gettext("Join requests close (UTC)")}
            />
          </div>
          <.input
            field={@form[:capacity]}
            type="number"
            min="2"
            label={gettext("Total group capacity")}
          />
          <.input
            field={@form[:location_label]}
            label={gettext("Approximate public meeting area")}
            placeholder={gettext("City centre, near the main entrance")}
          />
          <.input
            field={@form[:location_visibility]}
            type="select"
            label={gettext("Public map visibility")}
            options={[
              {gettext("Approximate area"), "approximate_public"},
              {gettext("Hidden"), "hidden"}
            ]}
          />
          <div class="rounded-2xl bg-base-200 p-5">
            <button
              type="button"
              phx-hook="LocationPicker"
              id="activity-location-picker"
              data-latitude-target="#activity-latitude"
              data-longitude-target="#activity-longitude"
              class="btn btn-outline btn-sm"
            >
              {gettext("Use my current foreground location")}
            </button>
            <p class="mt-2 text-xs text-base-content/60">
              {gettext("Exact coordinates are shown only to participants you approve.")}
            </p>
            <div class="mt-3 grid grid-cols-2 gap-3">
              <.input
                field={@form[:latitude]}
                id="activity-latitude"
                type="number"
                step="any"
                label={gettext("Latitude")}
              />
              <.input
                field={@form[:longitude]}
                id="activity-longitude"
                type="number"
                step="any"
                label={gettext("Longitude")}
              />
            </div>
          </div>
          <div class="rounded-2xl border border-base-300 p-4 text-sm">
            <.input
              field={@form[:safety_confirmed]}
              type="checkbox"
              label={
                gettext(
                  "I will approve participants individually, keep sensitive details in the approved group, and use an appropriate public first meeting point."
                )
              }
              required
              class="checkbox checkbox-info mt-0.5"
            />
          </div>
          <.button
            class="btn btn-info btn-lg w-full"
            phx-disable-with={gettext("Publishing…")}
          >
            {gettext("Publish activity")}
          </.button>
        </.form>
      </div>
    </Layouts.app>
    """
  end
end
