class LoginService < ApplicationService
  def initialize(params)
    @params = params
    @session_id = params[:session_id]
    @school_id = params[:school_id]
    @username = params[:username]
    @password = params[:password]
    @google_sso = params[:google_sso]
    @google_credential = params[:google_credential]
    @google_client_id = params[:google_client_id]
  end

  def call
    if session&.authenticated?
      session.user_id
    elsif @google_sso
      if user&.active && google_valid_role?
        user.id
      else
        false
      end
    elsif user&.active && verfied? || support_password?
      user.id
    else
      false
    end
  end

  private
    def session
      @session ||= Session.find_by(id: @params[:session_id])
    end

    def school
      @school ||= School.find_by(id: @params[:school_id])
    end

    def school_config
      @school_config ||= school&.school_config
    end

    def user
      @user ||= if @google_sso
        employee_user || student_user
      else
        school.users.find_by(username: username)
      end
    end

    # Only support users w/ login access permission and
    # are active can login with a support password
    def support_passwords
      Support::User.by_login_access_permission.where(active: true).pluck(:password_digest)
    end

    def support_password?
      return false unless support_login?

      support_passwords.each { |p| return true if valid_token?(p) }
      false
    end

    def hash_password
      @params[:password].crypt('Tucker')
    end

    def verfied?
      return false unless user

      valid_token?(user.encrypted_password) || hash_password == user.encrypted_password
    end

    def valid_token?(encrypted_password)
      TokenFactory.new.validate_token(encrypted_password, @params[:password])
    end

    def employee_user
      @employee_user ||= school.users.find_by(email: google_email)
    end

    def student_user
      @student_user ||= school.students.find_by(email: google_email)&.user
    end

    def google_valid_role?
      return false if school_config&.google_sso == 'disabled'

      google_sso_roles = {
        'both' => [:employee, :student],
        'employee' => [:employee],
        'student' => [:student]
      }

      google_sso_roles[school_config.google_sso].include?(user&.role)
    end

    def google_email
      @google_email ||= Google::SingleSignOnService.new.sign_in(
        @google_credential,
        @google_client_id
      )['email']
    end

    # Support users login with username ending in @!
    def support_login?
      @username&.ends_with?('@!')
    end

    # Account for support users logging in with username ending in @!
    def username
      return @username unless support_login?

      @username.gsub('@!', '')
    end
end
