defmodule ToweropsWeb.UserRegistrationController do
  @moduledoc false

  use ToweropsWeb, :controller

  alias Towerops.Accounts
  alias Towerops.Accounts.User
  alias Towerops.Organizations
  alias ToweropsWeb.UserAuth

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

    changeset = Accounts.change_user_registration(%User{})

    render(conn, :new,
      form: Phoenix.Component.to_form(changeset, as: "user"),
      invitation: invitation,
      invitation_token: invitation_token
    )
  end

  def create(conn, %{"user" => user_params}) do
    invitation_token = user_params["invitation_token"] || conn.params["invitation_token"]

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

  defp create_with_organization(conn, user_params) do
    case Accounts.register_user_with_organization(user_params) do
      {:ok, user} ->
        conn
        |> put_flash(:info, "Account created successfully.")
        |> UserAuth.log_in_user(user)

      {:error, %Ecto.Changeset{} = changeset} ->
        render(conn, :new,
          form: Phoenix.Component.to_form(changeset, as: "user"),
          invitation: nil,
          invitation_token: nil
        )
    end
  end

  defp create_via_invitation(conn, user_params, invitation_token) do
    with {:ok, invitation} <- get_valid_invitation(invitation_token),
         {:ok, user} <- Accounts.register_user(user_params),
         {:ok, _membership} <- Organizations.accept_invitation(invitation, user.id) do
      conn
      |> put_flash(:info, "Account created successfully. Welcome to #{invitation.organization.name}!")
      |> UserAuth.log_in_user(user)
    else
      {:error, :invalid_invitation} ->
        changeset = Accounts.change_user_registration(%User{}, user_params)

        conn
        |> put_flash(:error, "Invalid or expired invitation link.")
        |> render(:new,
          form: Phoenix.Component.to_form(changeset, as: "user"),
          invitation: nil,
          invitation_token: nil
        )

      {:error, %Ecto.Changeset{} = changeset} ->
        render(conn, :new,
          form: Phoenix.Component.to_form(changeset, as: "user"),
          invitation_token: invitation_token
        )
    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
end
