class SignupController < ApplicationController
  before_action :require_user_signed_out
  before_action :require_invitation
  before_action :set_invitation
  before_action :set_new_user, only: ["steps", "validate"]
  before_action :set_context

  def index
    @invited_by_name = @invitation.user.address
  end

  def steps
    @step = params[:step].to_i
    http_status :not_found unless [1,2,3].include?(@step)
    @validation_error = session[:validation_error]
  end

  def validate
    session[:validation_error] = nil

    case user_params.keys.first
    when "cn"
      @user.cn = user_params[:cn]
      @user.valid?
      session[:new_user] = @user

      if @user.errors[:cn].present?
        session[:validation_error] = @user.errors[:cn].first # Store user including validation errors
        redirect_to signup_steps_path(1) and return
      else
        redirect_to signup_steps_path(2) and return
      end
    when "email"
      @user.email = user_params[:email]
      @user.valid?
      session[:new_user] = @user

      if @user.errors[:email].present?
        session[:validation_error] = @user.errors[:email].first # Store user including validation errors
        redirect_to signup_steps_path(2) and return
      else
        redirect_to signup_steps_path(3) and return
      end
    when "password"
      @user.password = user_params[:password]
      @user.password_confirmation = user_params[:password]
      @user.valid?
      session[:new_user] = @user

      if @user.errors[:password].present?
        session[:validation_error] = @user.errors[:password].first # Store user including validation errors
        redirect_to signup_steps_path(3) and return
      else
        complete_signup
        msg = "Almost done! We have sent you an email to confirm your address."
        redirect_to(check_your_email_path, notice: msg) and return
      end
    end
  end

  private

  def user_params
    params.require(:user).permit(:cn, :email, :password)
  end

  def require_invitation
    if session[:invitation_token].blank?
      flash.now[:alert] = "You need an invitation to sign up for an account."
      http_status :unauthorized
    elsif !valid_invitation?(session[:invitation_token])
      flash.now[:alert] = "This invitation either doesn't exist or has already been used."
      http_status :unauthorized
    end

    @invitation = Invitation.find_by(token: session[:invitation_token])
  end

  def valid_invitation?(token)
    Invitation.where(token: session[:invitation_token], used_at: nil).exists?
  end

  def set_invitation
    @invitation = Invitation.find_by(token: session[:invitation_token])
  end

  def set_new_user
    if session[:new_user].present?
      @user = User.new(session[:new_user])
    else
      @user = User.new(ou: Setting.primary_domain)
    end
  end

  def complete_signup
    session[:new_user] = nil
    session[:validation_error] = nil

    CreateAccount.call(account: {
      username: @user.cn,
      domain: Setting.primary_domain,
      email: @user.email,
      password: @user.password,
      invitation: @invitation
    })
  end

  def set_context
    @context = :signup
  end
end
