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

  alias WhoNeedHelp.Catalog
  alias WhoNeedHelp.Help
  alias WhoNeedHelp.Help.HelpRequest
  alias WhoNeedHelpWeb.FormParams

  @impl true
  def mount(_params, _session, socket) do
    expires = DateTime.utc_now(:second) |> DateTime.add(3, :hour)
    default_location_visibility = socket.assigns.current_scope.user.location_visibility

    changeset =
      Help.change_request(%HelpRequest{}, %{
        "expires_at" => expires,
        "urgency" => "now",
        "location_visibility" => to_string(default_location_visibility)
      })

    {:ok,
     socket
     |> assign(:page_title, gettext("Ask for help"))
     |> assign(:categories, Catalog.list_categories())
     |> assign(:selected_category, nil)
     |> assign(:structured_fields, [])
     |> assign(:form, to_form(changeset))}
  end

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

    changeset =
      %HelpRequest{}
      |> Help.change_request(normalize_expiry(params))
      |> Map.put(:action, :validate)

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

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

    case Help.create_request(socket.assigns.current_scope, normalize_expiry(params)) do
      {:ok, request} ->
        {:noreply,
         socket
         |> put_flash(:info, gettext("Your request is now visible to nearby helpers."))
         |> push_navigate(to: ~p"/requests/#{request.id}")}

      {:error, changeset} ->
        if match?(%Ecto.Changeset{}, changeset) do
          {:noreply,
           socket
           |> assign(:form, to_form(changeset))
           |> assign_category(params)}
        else
          {:noreply, put_flash(socket, :error, error_message(changeset))}
        end
    end
  end

  defp normalize_expiry(%{"expires_at" => value} = params) when is_binary(value) do
    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(params, "expires_at", parsed)
  end

  defp normalize_expiry(params), do: params

  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 category_description(nil, _locale), do: nil

  defp category_description(category, locale),
    do: WhoNeedHelp.Catalog.Category.description(category, locale)

  defp category_title_placeholder(%{slug: "medicine-pickup"}),
    do: gettext("Medicine is ready at the pharmacy")

  defp category_title_placeholder(%{parent: %{slug: "roadside-help"}}),
    do: gettext("Need roadside help in a safe location")

  defp category_title_placeholder(_category), do: gettext("Briefly describe the help you need")

  defp safety_confirmation(%{slug: "medicine-pickup"}) do
    gettext(
      "I confirm this is not an emergency, medical advice request, controlled substance, or request to buy medicine on my behalf."
    )
  end

  defp safety_confirmation(%{parent: %{slug: "roadside-help"}}) do
    gettext(
      "I confirm there is no immediate danger, people and vehicles are away from active traffic or emergency services have already been contacted, and the requested task is lawful."
    )
  end

  defp safety_confirmation(_category) do
    gettext(
      "I confirm this is not an emergency, there is no immediate danger, and the requested task is lawful."
    )
  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 requests in the configured time window.")

  defp error_message(_reason), do: gettext("Could not publish the request. 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"/requests"} class="btn btn-ghost btn-sm mb-4">
          {gettext("← Back to requests")}
        </.link>
        <h1 class="text-4xl font-black">{gettext("Ask for urgent help")}</h1>
        <p class="mt-2 text-base-content/65">
          {gettext(
            "Medicine pickup remains the first priority. Roadside categories use the same moderated, extensible request flow with details specific to each type of help."
          )}
        </p>

        <div class="alert alert-warning mt-6 text-sm">
          <.icon name="hero-exclamation-triangle" class="size-5" />
          <span>
            {gettext(
              "This is not an emergency service. Contact local emergency services for immediate danger. Never include prescription details, payment card data, access codes, or other sensitive information."
            )}
          </span>
        </div>

        <.form
          for={@form}
          id="request-form"
          phx-change="validate"
          phx-submit="save"
          class="mt-8 space-y-5"
        >
          <.input
            field={@form[:category_id]}
            type="select"
            label={gettext("Category")}
            prompt={gettext("Choose category")}
            options={
              Enum.map(
                @categories,
                &{WhoNeedHelp.Catalog.category_path(
                   &1,
                   Gettext.get_locale(WhoNeedHelpWeb.Gettext)
                 ), &1.id}
              )
            }
          />
          <p
            :if={
              category_description(
                @selected_category,
                Gettext.get_locale(WhoNeedHelpWeb.Gettext)
              )
            }
            id="selected-category-description"
            class="-mt-3 text-sm text-base-content/60"
          >
            {category_description(
              @selected_category,
              Gettext.get_locale(WhoNeedHelpWeb.Gettext)
            )}
          </p>
          <div
            :if={@structured_fields != []}
            class="space-y-4 rounded-2xl border border-success/30 bg-success/5 p-5"
          >
            <h2 class="font-bold">{gettext("Category 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={"help_request[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={"help_request[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={"help_request[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={category_title_placeholder(@selected_category)}
          />
          <.input
            field={@form[:description]}
            type="textarea"
            label={gettext("What help do you need?")}
            placeholder={
              gettext("Explain what is already arranged and what the volunteer needs to do.")
            }
          />
          <.input
            field={@form[:pickup_instructions]}
            type="textarea"
            label={gettext("Pickup instructions (optional)")}
            placeholder={
              gettext(
                "Share only non-sensitive instructions. Exact details can wait for the matched chat."
              )
            }
          />
          <div class="grid gap-4 md:grid-cols-2">
            <.input
              field={@form[:urgency]}
              type="select"
              label={gettext("Urgency")}
              options={[
                {gettext("Now"), "now"},
                {gettext("Today"), "today"},
                {gettext("Scheduled"), "scheduled"}
              ]}
            />
            <.input
              field={@form[:expires_at]}
              type="datetime-local"
              label={gettext("Request expires (UTC)")}
            />
          </div>
          <.input
            field={@form[:location_label]}
            label={gettext("Approximate area")}
            placeholder={gettext("Podil, near the central pharmacy")}
          />
          <.input
            field={@form[:location_visibility]}
            type="select"
            label={gettext("Location visibility")}
            options={[
              {gettext("Approximate publicly (recommended)"), "approximate_public"},
              {gettext("Hidden"), "hidden"},
              {gettext("Exact only for active match"), "exact_for_active_match"},
              {gettext("Exact publicly — explicit consent"), "exact_public"}
            ]}
          />
          <div class="rounded-2xl bg-base-200 p-5">
            <button
              type="button"
              phx-hook="LocationPicker"
              id="location-picker"
              data-latitude-target="#request-latitude"
              data-longitude-target="#request-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("You can also enter coordinates manually for local testing.")}
            </p>
            <div class="mt-3 grid grid-cols-2 gap-3">
              <.input
                field={@form[:latitude]}
                id="request-latitude"
                type="number"
                step="any"
                label={gettext("Latitude")}
              />
              <.input
                field={@form[:longitude]}
                id="request-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={safety_confirmation(@selected_category)}
              required
              class="checkbox checkbox-success mt-0.5"
            />
          </div>
          <.button
            class="btn btn-primary btn-lg w-full"
            phx-disable-with={gettext("Publishing…")}
          >
            {gettext("Publish request")}
          </.button>
        </.form>
      </div>
    </Layouts.app>
    """
  end
end
