module Support
  module Helpers
    class TwoFactorLogin
      def initialize(user_data)
        @user_login = user_data[:username]
      end

      # INSERT a new row into art_relations containing a unique secret token.
      # This way you don't have to worry about browsers logging in in parallel
      # and stealing each other's tokens.
      def create_new_secret
        current_time = Time.now

        session_time = current_time.strftime("%Y-%m-%d %H:%M:%S")
        secret_token = current_time.strftime("%s%6N")

        query = "INSERT INTO oa_logins (user_login, session_time, secret_token)"\
          " VALUES ('#{@user_login}', '#{session_time}', '#{secret_token}')"
        Support::DbClient.query_art_relations(query)
        secret_token
      end

      def secret_exists?(status:)
        number_of_existing_secrets(status: status) > 0
      end

      def number_of_existing_secrets(status:)
        results_for_secret_query(status: status).count
      end

      def valid_existing_secret
        result = random_result_for_secret_query(status: :valid)

        fail "No valid secret available!" if result.nil?
        result["secret_token"]
      end

      def used_secret
        result = random_result_for_secret_query(status: :used)

        fail "No expired secret available!" if result.nil?
        result["secret_token"]
      end

      def expired_secret
        result = random_result_for_secret_query(status: :expired)

        fail "No expired secret available!" if result.nil?
        result["secret_token"]
      end

      # retrieves emails from OA user's account to find the link
      def link_from_most_recent_email
        verification_link_regex = /Please go to (.*)\r/ # subject to change
        client = case @user_login
                 when "automation_qa"
                   Support::MailClient.automation_qa_client
                 else
                   fail "unknown client!"
                 end
        # client.wait_for_new_email(since: 5, timeout: 20)

        validation_link = client.contents_of_last_message.match(verification_link_regex)[1]
        # all environments email using production link
        validation_link.gsub("https://oa.theorchard.com", DOMAINS[:oa])
      end

      private

      def random_result_for_secret_query(status:)
        results_for_secret_query(status: status).sample
      end

      def results_for_secret_query(status:)
        base_clauses = "SELECT secret_token FROM oa_logins WHERE user_login = '#{@user_login}' "
        where_clauses = case status
                        when :valid
                          "AND authentication_time = '0000-00-00 00:00:00' "\
                          "AND session_time > '#{last_expiration}'"
                        when :used
                          # already authenticated, but not expired
                          "AND authentication_time > '0000-00-00 00:00:00' "\
                          "AND session_time > '#{last_expiration}'"
                        when :expired
                          # never authenticated, but expired
                          "AND authentication_time = '0000-00-00 00:00:00' "\
                          "AND session_time < '#{last_expiration}'"
                        end
        Support::DbClient.query_art_relations(base_clauses + where_clauses).to_a
      end

      # returns 10 minutes ago in sql-friendly format
      def last_expiration
        minutes_ago = 10 # tokens expire after 10 minutes
        (Time.now - minutes_ago * 60).strftime("%Y-%m-%d %H:%M:%S")
      end
    end
  end
end
