defmodule WhoNeedHelpWeb.ProfileLive do
  use WhoNeedHelpWeb, :live_view

  alias WhoNeedHelp.Accounts
  alias WhoNeedHelp.SocialOAuth
  alias WhoNeedHelp.Trust

  @impl true
  def mount(_params, _session, socket) do
    user = socket.assigns.current_scope.user
    reviews = Trust.paginate_visible_reviews(user.id)
    blocks = Trust.paginate_blocks(socket.assigns.current_scope)

    {:ok,
     socket
     |> assign(:page_title, gettext("Profile"))
     |> assign(:reputation, Trust.reputation(user.id))
     |> assign(:reviews, reviews.entries)
     |> assign(:reviews_cursor, reviews.next_cursor)
     |> assign(:blocks, blocks.entries)
     |> assign(:blocks_cursor, blocks.next_cursor)
     |> assign(:github_oauth_enabled, SocialOAuth.enabled?(:github))
     |> assign(:form, to_form(Accounts.change_user_profile(user)))
     |> assign_social_identities(user)}
  end

  @impl true
  def handle_event("save", %{"user" => params}, socket) do
    case Accounts.update_user_profile(socket.assigns.current_scope.user, params) do
      {:ok, user} ->
        Gettext.put_locale(WhoNeedHelpWeb.Gettext, user.locale)

        {:noreply,
         socket
         |> assign(:current_scope, WhoNeedHelp.Accounts.Scope.for_user(user))
         |> assign(:form, to_form(Accounts.change_user_profile(user)))
         |> put_flash(:info, gettext("Profile updated."))}

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

  def handle_event("add-social", %{"social_identity" => params}, socket) do
    user = socket.assigns.current_scope.user

    with {:ok, _limit} <- Trust.authorize_action(socket.assigns.current_scope, :add_social),
         {:ok, _identity} <- Accounts.add_social_identity(user, params) do
      {:noreply,
       socket
       |> assign_social_identities(user)
       |> put_flash(:info, gettext("Social link added as unverified."))}
    else
      {:error, %Ecto.Changeset{} = changeset} ->
        {:noreply, assign(socket, :social_form, to_form(changeset, as: :social_identity))}

      {:error, :rate_limited} ->
        {:noreply,
         put_flash(socket, :error, gettext("Too many actions in the configured time window."))}

      {:error, :account_not_eligible} ->
        {:noreply, put_flash(socket, :error, gettext("This account cannot perform that action."))}
    end
  end

  def handle_event("remove-social", %{"id" => identity_id}, socket) do
    user = socket.assigns.current_scope.user

    case Accounts.delete_social_identity(user, identity_id) do
      {:ok, _identity} ->
        {:noreply, assign_social_identities(socket, user)}

      {:error, :not_found} ->
        {:noreply, put_flash(socket, :error, gettext("Social link was not found."))}
    end
  end

  def handle_event("unblock", %{"id" => blocked_id}, socket) do
    case Trust.unblock(socket.assigns.current_scope, blocked_id) do
      {:ok, _result} ->
        blocks = Trust.paginate_blocks(socket.assigns.current_scope)

        {:noreply,
         socket
         |> assign(:blocks, blocks.entries)
         |> assign(:blocks_cursor, blocks.next_cursor)
         |> put_flash(:info, gettext("User unblocked."))}

      {:error, _reason} ->
        {:noreply,
         put_flash(socket, :error, gettext("Could not unblock this user. Please try again."))}
    end
  end

  def handle_event("load-more-reviews", _params, socket) do
    page =
      Trust.paginate_visible_reviews(socket.assigns.current_scope.user.id,
        after: socket.assigns.reviews_cursor
      )

    {:noreply, append_page(socket, :reviews, page)}
  end

  def handle_event("load-more-blocks", _params, socket) do
    page =
      Trust.paginate_blocks(socket.assigns.current_scope,
        after: socket.assigns.blocks_cursor
      )

    {:noreply, append_page(socket, :blocks, page)}
  end

  defp append_page(socket, name, page) do
    existing = socket.assigns[name]
    existing_ids = MapSet.new(existing, & &1.id)

    socket
    |> assign(name, existing ++ Enum.reject(page.entries, &MapSet.member?(existing_ids, &1.id)))
    |> assign(cursor_assign(name), page.next_cursor)
  end

  defp cursor_assign(:reviews), do: :reviews_cursor
  defp cursor_assign(:blocks), do: :blocks_cursor

  defp assign_social_identities(socket, user) do
    socket
    |> assign(:social_identities, Accounts.list_social_identities(user))
    |> assign(
      :social_form,
      to_form(
        Accounts.change_social_identity(%WhoNeedHelp.Accounts.SocialIdentity{}),
        as: :social_identity
      )
    )
  end

  @impl true
  def render(assigns) do
    ~H"""
    <Layouts.app flash={@flash} current_scope={@current_scope}>
      <div class="mx-auto max-w-4xl">
        <h1 class="text-4xl font-black">{gettext("Your profile")}</h1>
        <div class="mt-6 grid gap-6 md:grid-cols-[1fr_.75fr]">
          <.form
            for={@form}
            phx-submit="save"
            class="space-y-4 rounded-3xl border border-base-300 p-6"
          >
            <.input field={@form[:display_name]} label={gettext("Display name")} />
            <.input field={@form[:bio]} type="textarea" label={gettext("Short bio")} />
            <.input
              field={@form[:locale]}
              type="select"
              label={gettext("Interface language")}
              options={[
                {gettext("English"), "en"},
                {"Українська", "uk"},
                {"Русский", "ru"}
              ]}
            />
            <.input
              field={@form[:location_visibility]}
              type="select"
              label={gettext("Default location visibility")}
              options={[
                {gettext("Hidden"), "hidden"},
                {gettext("Approximate publicly"), "approximate_public"},
                {gettext("Exact for active match"), "exact_for_active_match"},
                {gettext("Exact publicly"), "exact_public"}
              ]}
            />
            <.input
              field={@form[:tip_url]}
              label={gettext("Optional external thank-you link")}
              placeholder="https://…"
            />
            <p class="text-xs text-base-content/55">
              {gettext("The platform never handles, requires, splits, or guarantees a payment.")}
            </p>
            <.button class="btn btn-primary w-full">{gettext("Save profile")}</.button>
          </.form>

          <aside class="space-y-5">
            <div class="rounded-3xl bg-success p-6 text-success-content">
              <h2 class="font-bold">{gettext("Public reputation")}</h2>
              <div class="mt-5 grid grid-cols-2 gap-4">
                <div>
                  <div class="text-3xl font-black">{@reputation.completed}</div><div class="text-xs">
                    {gettext("completed")}
                  </div>
                </div>
                <div>
                  <div class="text-3xl font-black">{@reputation.unique_people}</div><div class="text-xs">
                    {gettext("unique people")}
                  </div>
                </div>
                <div>
                  <div class="text-3xl font-black">{@reputation.verified_handovers}</div><div class="text-xs">
                    {gettext("verified handovers")}
                  </div>
                </div>
                <div>
                  <div class="text-3xl font-black">{@reputation.rating || "—"}</div><div class="text-xs">
                    {gettext("rating")}
                  </div>
                </div>
              </div>
            </div>
            <div class="rounded-3xl bg-base-200 p-5">
              <h3 class="font-bold">{gettext("Visible reviews")}</h3>
              <p :if={@reviews == []} class="mt-3 text-sm text-base-content/55">
                {gettext("None revealed yet.")}
              </p>
              <div :for={review <- @reviews} class="mt-3 border-t border-base-300 pt-3 text-sm">
                <div class="font-semibold">{"★" |> String.duplicate(review.rating)}</div>
                <div class="mt-1">{review.comment}</div>
              </div>
              <button
                :if={@reviews_cursor}
                type="button"
                phx-click="load-more-reviews"
                class="btn btn-outline btn-sm mt-4 w-full"
              >
                {gettext("Load more")}
              </button>
            </div>
          </aside>
        </div>

        <section class="mt-6 rounded-3xl border border-base-300 p-6">
          <div class="flex flex-wrap items-start justify-between gap-3">
            <div>
              <h2 class="text-xl font-bold">{gettext("Social links")}</h2>
              <p class="mt-1 text-sm text-base-content/55">
                {gettext(
                  "Manually added links are public and marked unverified. A verified badge is only granted after completing a provider authorization flow."
                )}
              </p>
            </div>
            <.link
              :if={@github_oauth_enabled}
              href={~p"/auth/social/github"}
              class="btn btn-primary btn-sm"
            >
              {gettext("Verify GitHub")}
            </.link>
          </div>

          <p
            :if={!@github_oauth_enabled}
            class="mt-4 rounded-2xl bg-base-200 p-4 text-sm text-base-content/60"
          >
            {gettext(
              "GitHub verification is unavailable until the operator configures its OAuth credentials. No manually entered link is treated as verified."
            )}
          </p>

          <div class="mt-5 grid gap-4 md:grid-cols-[1fr_.9fr]">
            <div class="space-y-3">
              <p :if={@social_identities == []} class="text-sm text-base-content/55">
                {gettext("No social links added.")}
              </p>
              <div
                :for={identity <- @social_identities}
                class="flex items-center justify-between gap-3 rounded-2xl bg-base-200 p-4"
              >
                <div class="min-w-0">
                  <div class="flex items-center gap-2">
                    <span class="font-semibold capitalize">{identity.provider}</span>
                    <span class={[
                      "badge badge-sm",
                      identity.verified_at && "badge-success",
                      is_nil(identity.verified_at) && "badge-warning"
                    ]}>
                      {if identity.verified_at,
                        do: gettext("verified"),
                        else: gettext("unverified")}
                    </span>
                  </div>
                  <a
                    href={identity.profile_url}
                    target="_blank"
                    rel="noopener noreferrer nofollow ugc"
                    class="link mt-1 block truncate text-sm"
                  >
                    {identity.handle || identity.profile_url}
                  </a>
                </div>
                <button
                  type="button"
                  phx-click="remove-social"
                  phx-value-id={identity.id}
                  class="btn btn-ghost btn-sm text-error"
                >
                  {gettext("Remove")}
                </button>
              </div>
            </div>

            <.form for={@social_form} phx-submit="add-social" class="space-y-3">
              <.input
                field={@social_form[:provider]}
                type="select"
                label={gettext("Network")}
                options={[
                  {"GitHub", "github"},
                  {"Instagram", "instagram"},
                  {"Facebook", "facebook"},
                  {"Telegram", "telegram"},
                  {"Google", "google"},
                  {gettext("Other"), "other"}
                ]}
              />
              <.input
                field={@social_form[:profile_url]}
                type="url"
                label={gettext("Public profile URL")}
                placeholder="https://…"
              />
              <.input
                field={@social_form[:handle]}
                label={gettext("Handle (optional)")}
                placeholder="@name"
              />
              <.button class="btn btn-outline w-full">{gettext("Add unverified link")}</.button>
            </.form>
          </div>
        </section>

        <section class="mt-6 rounded-3xl border border-base-300 p-6">
          <h2 class="text-xl font-bold">{gettext("Blocked users")}</h2>
          <p :if={@blocks == []} class="mt-3 text-sm text-base-content/55">
            {gettext("You have not blocked anyone.")}
          </p>
          <div
            :for={block <- @blocks}
            class="mt-3 flex items-center justify-between rounded-2xl bg-base-200 p-4"
          >
            <span class="font-semibold">{block.blocked.display_name}</span>
            <button
              phx-click="unblock"
              phx-value-id={block.blocked_id}
              class="btn btn-sm btn-outline"
            >
              {gettext("Unblock")}
            </button>
          </div>
          <button
            :if={@blocks_cursor}
            type="button"
            phx-click="load-more-blocks"
            class="btn btn-outline btn-sm mt-4"
          >
            {gettext("Load more")}
          </button>
        </section>
      </div>
    </Layouts.app>
    """
  end
end
