defmodule ToweropsWeb.UserRegistrationLive do
  @moduledoc """
  LiveView for user registration with HIBP password breach checking.
  """
  use ToweropsWeb, :live_view

  alias Towerops.Accounts
  alias Towerops.Accounts.HIBP
  alias Towerops.Accounts.User
  alias Towerops.Organizations

  def mount(params, session, socket) do
    # Check if registering via invitation
    invitation_token = params["invitation_token"] || params["token"]
    invitation = invitation_token && Organizations.get_invitation_by_token(invitation_token)

    # Get detected timezone from session (set by CaptureTimezone plug)
    detected_timezone = Map.get(session, "detected_timezone", "UTC")

    changeset = Accounts.change_user_registration(%User{})

    {:ok,
     socket
     |> assign(:form, to_form(changeset))
     |> assign(:invitation, invitation)
     |> assign(:invitation_token, invitation_token)
     |> assign(:password_breach_count, nil)
     |> assign(:detected_timezone, detected_timezone)
     |> assign(:trigger_action, false)
     |> assign(:privacy_policy_consent, false)
     |> assign(:terms_of_service_consent, false)}
  end

  def handle_event("check_password_breach", %{"value" => password}, socket)
      when is_binary(password) and byte_size(password) > 0 do
    case HIBP.check_password(password) do
      {:ok, count} when is_integer(count) ->
        {:noreply, assign(socket, :password_breach_count, count)}

      {:ok, :unknown} ->
        {:noreply, assign(socket, :password_breach_count, nil)}
    end
  end

  def handle_event("check_password_breach", _params, socket) do
    {:noreply, socket}
  end

  def handle_event("validate", %{"user" => user_params}, socket) do
    changeset =
      %User{}
      |> Accounts.change_user_registration(user_params)
      |> Map.put(:action, :validate)

    {:noreply,
     socket
     |> assign(:form, to_form(changeset))
     |> assign(:privacy_policy_consent, user_params["privacy_policy_consent"] == "on")
     |> assign(:terms_of_service_consent, user_params["terms_of_service_consent"] == "on")}
  end

  def handle_event("save", %{"user" => user_params}, socket) do
    invitation_token = socket.assigns.invitation_token

    # Normalize checkbox values: HTML sends "on", but changeset expects true
    user_params = normalize_consent_params(user_params)

    if invitation_token do
      # Registration via invitation - don't create personal org
      create_via_invitation(socket, user_params, invitation_token)
    else
      # Normal registration - create personal org
      create_with_organization(socket, user_params)
    end
  end

  defp normalize_consent_params(params) do
    params
    |> Map.update("privacy_policy_consent", nil, fn
      "on" -> true
      val -> val
    end)
    |> Map.update("terms_of_service_consent", nil, fn
      "on" -> true
      val -> val
    end)
  end

  defp create_with_organization(socket, user_params) do
    # Merge detected timezone into params
    user_params_with_timezone = Map.put(user_params, "timezone", socket.assigns.detected_timezone)

    case Accounts.register_user_with_organization(user_params_with_timezone) do
      {:ok, user} ->
        {:noreply,
         socket
         |> put_flash(:info, "Account created successfully.")
         |> redirect(to: ~p"/users/log-in?email=#{user.email}")
         |> assign(:trigger_action, true)}

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

  defp create_via_invitation(socket, user_params, invitation_token) do
    # Merge detected timezone into params
    user_params_with_timezone = Map.put(user_params, "timezone", socket.assigns.detected_timezone)

    with {:ok, invitation} <- get_valid_invitation(invitation_token),
         {:ok, user} <- Accounts.register_user(user_params_with_timezone),
         {:ok, _membership} <- Organizations.accept_invitation(invitation, user.id) do
      {:noreply,
       socket
       |> put_flash(:info, "Account created successfully. Welcome to #{invitation.organization.name}!")
       |> redirect(to: ~p"/users/log-in?email=#{user.email}")
       |> assign(:trigger_action, true)}
    else
      {:error, :invalid_invitation} ->
        {:noreply,
         socket
         |> put_flash(:error, "Invalid or expired invitation link.")
         |> assign(:invitation, nil)
         |> assign(:invitation_token, nil)}

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

  defp get_valid_invitation(token) do
    case Organizations.get_invitation_by_token(token) do
      nil -> {:error, :invalid_invitation}
      invitation -> {:ok, invitation}
    end
  end

  def render(assigns) do
    ~H"""
    <Layouts.app flash={@flash}>
      <div class="mx-auto max-w-sm">
        <div class="text-center">
          <.header>
            <%= if @invitation do %>
              Join {@invitation.organization.name}
            <% else %>
              Register for an account
            <% end %>
            <:subtitle>
              Already registered?
              <.link
                navigate={~p"/users/log-in"}
                class="font-semibold text-blue-600 hover:text-blue-700 dark:text-blue-400 dark:hover:text-blue-300"
              >
                Log in
              </.link>
              to your account now.
            </:subtitle>
          </.header>

          <%= if @invitation do %>
            <div class="mt-6 rounded-lg bg-blue-50 dark:bg-blue-900/20 p-4 border border-blue-200 dark:border-blue-800">
              <p class="text-sm text-blue-900 dark:text-blue-100">
                You've been invited to join
                <span class="font-semibold">{@invitation.organization.name}</span>
                as
                a {@invitation.role}.
              </p>
            </div>
          <% else %>
            <div class="mt-6 rounded-lg bg-blue-50 dark:bg-blue-900/20 p-4 border border-blue-200 dark:border-blue-800">
              <p class="text-sm font-medium text-blue-900 dark:text-blue-100">
                Free tier includes:
              </p>
              <ul class="mt-2 text-sm text-blue-800 dark:text-blue-200 space-y-1">
                <li>✓ Monitor up to 10 devices</li>
                <li>✓ Real-time alerts and notifications</li>
                <li>✓ Performance charts and historical data</li>
                <li>✓ No credit card required</li>
              </ul>
            </div>
          <% end %>
        </div>

        <div class="mt-8">
          <.form for={@form} phx-change="validate" phx-submit="save">
            <%= if @invitation_token do %>
              <input type="hidden" name="user[invitation_token]" value={@invitation_token} />
            <% end %>

            <div class="grid grid-cols-2 gap-4">
              <.input
                field={@form[:first_name]}
                type="text"
                label="First name"
                autocomplete="given-name"
                phx-mounted={JS.focus()}
              />
              <.input
                field={@form[:last_name]}
                type="text"
                label="Last name"
                autocomplete="family-name"
              />
            </div>
            <.input
              field={@form[:email]}
              type="email"
              label="Email"
              autocomplete="email"
              required
            />
            <.input
              field={@form[:password]}
              type="password"
              label="Password"
              autocomplete="new-password"
              phx-blur="check_password_breach"
              required
            />

            <%= if @password_breach_count && @password_breach_count > 0 do %>
              <div class="mt-2 rounded-md bg-yellow-50 dark:bg-yellow-900/20 p-4">
                <div class="flex">
                  <div class="flex-shrink-0">
                    <.icon name="hero-exclamation-triangle" class="h-5 w-5 text-yellow-400" />
                  </div>
                  <div class="ml-3">
                    <h3 class="text-sm font-medium text-yellow-800 dark:text-yellow-200">
                      Password found in data breaches
                    </h3>
                    <div class="mt-2 text-sm text-yellow-700 dark:text-yellow-300">
                      <p>
                        This password has appeared {@password_breach_count}
                        {if @password_breach_count == 1, do: "time", else: "times"} in known data breaches. We strongly recommend choosing a different,
                        more unique password to protect your account.
                      </p>
                    </div>
                  </div>
                </div>
              </div>
            <% end %>

            <%= unless @invitation do %>
              <.input
                name="user[organization_name]"
                value=""
                type="text"
                label="Organization Name"
                placeholder="My Company"
                required
              />
            <% end %>

            <div class="space-y-3 mt-6">
              <div class="flex items-start">
                <div class="flex items-center h-5">
                  <input
                    id="privacy_policy_consent"
                    name="user[privacy_policy_consent]"
                    type="checkbox"
                    checked={@privacy_policy_consent}
                    required
                    class="h-4 w-4 rounded border-zinc-300 text-blue-600 focus:ring-blue-500 dark:border-zinc-600 dark:bg-zinc-800 dark:checked:bg-blue-500 dark:checked:border-blue-500"
                  />
                </div>
                <div class="ml-3 text-sm">
                  <label
                    for="privacy_policy_consent"
                    class="text-zinc-700 dark:text-zinc-300 cursor-pointer"
                  >
                    I agree to the
                    <.link
                      href={~p"/privacy"}
                      target="_blank"
                      class="font-medium text-blue-600 hover:text-blue-700 dark:text-blue-400 dark:hover:text-blue-300"
                      onclick="event.stopPropagation()"
                    >
                      Privacy Policy
                    </.link>
                    <span class="text-red-600 dark:text-red-400">*</span>
                  </label>
                </div>
              </div>

              <div class="flex items-start">
                <div class="flex items-center h-5">
                  <input
                    id="terms_of_service_consent"
                    name="user[terms_of_service_consent]"
                    type="checkbox"
                    checked={@terms_of_service_consent}
                    required
                    class="h-4 w-4 rounded border-zinc-300 text-blue-600 focus:ring-blue-500 dark:border-zinc-600 dark:bg-zinc-800 dark:checked:bg-blue-500 dark:checked:border-blue-500"
                  />
                </div>
                <div class="ml-3 text-sm">
                  <label
                    for="terms_of_service_consent"
                    class="text-zinc-700 dark:text-zinc-300 cursor-pointer"
                  >
                    I agree to the
                    <.link
                      href={~p"/terms"}
                      target="_blank"
                      class="font-medium text-blue-600 hover:text-blue-700 dark:text-blue-400 dark:hover:text-blue-300"
                      onclick="event.stopPropagation()"
                    >
                      Terms of Service
                    </.link>
                    <span class="text-red-600 dark:text-red-400">*</span>
                  </label>
                </div>
              </div>
            </div>

            <.button phx-disable-with="Creating account..." class="w-full mt-6" variant="primary">
              {if @invitation, do: "Accept invitation and create account", else: "Create an account"}
            </.button>
          </.form>
        </div>
      </div>
    </Layouts.app>
    """
  end
end
