# Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
# frozen_string_literal: true

require 'contrast/components/logger'
require 'contrast/utils/object_share'
require 'base64'

module Contrast
  module Agent
    module Reporting
      # This is the class which will hold up all the Endpoints we use for the direct report from the agent. It builds
      # the full URLs needed for communication.
      module Endpoints
        extend Contrast::Components::Logger::InstanceMethods

        APP_LANGUAGE = Contrast::Utils::ObjectShare::RUBY.upcase.cs__freeze
        ENDPOINT_VERSION = '/v1.0'.cs__freeze
        NG_ENDPOINTS = {
            application_activity: "#{ Contrast::API.api_url }/api/ng/activity/application",
            application_create: "#{ Contrast::API.api_url }/api/ng/applications/create",
            agent_startup: "#{ Contrast::API.api_url }/api/ng/servers/"
        }.cs__freeze

        class << self
          # @return [String,nil]
          def application_startup
            with_rescue do
              "#{ application_endpoint }/startup".cs__freeze
            end
          end

          # @return [String,nil]
          def application_settings
            with_rescue do
              "#{ application_endpoint }/settings".cs__freeze
            end
          end

          # @return [String,nil]
          def application_inventory
            with_rescue do
              "#{ application_endpoint }/inventory".cs__freeze
            end
          end

          def application_activity
            with_rescue do
              NG_ENDPOINTS[:application_activity].cs__freeze
            end
          end

          # @return [String,nil]
          def library_usage
            with_rescue do
              "#{ application_endpoint }/library-usage".cs__freeze
            end
          end

          # @return [String,nil]
          def heartbeat
            with_rescue do
              "#{ application_endpoint }/heartbeat".cs__freeze
            end
          end

          # @return [String,nil]
          def observed_route
            with_rescue do
              "#{ route_endpoint }/observed".cs__freeze
            end
          end

          # @return [String,nil]
          def trace_observed
            with_rescue do
              "#{ trace_endpoint }/observed".cs__freeze
            end
          end

          private

          # Returns the URL needed to connect to endpoints in TeamServer required for application related information.
          #
          # @return [String]
          def application_endpoint
            @_application_endpoint ||= "#{ Contrast::API.api_url }/agents#{ ENDPOINT_VERSION }/applications"\
                                       "#{ server_path_segment }#{ application_path_segment }"
          end

          # Returns the URL needed to connect to endpoints in TeamServer required for route related information.
          #
          # @return [String]
          def route_endpoint
            @_route_endpoint ||= "#{ Contrast::API.api_url }/agents#{ ENDPOINT_VERSION }/routes"\
                                 "#{ server_path_segment }#{ application_path_segment }"
          end

          # Returns the URL needed to connect to endpoints in TeamServer required for server related information.
          #
          # @return [String]
          def server_endpoint
            @_server_endpoint ||= "#{ Contrast::API.api_url }/agents#{ ENDPOINT_VERSION }/servers"\
                                  "#{ server_path_segment }"
          end

          # Returns the URL needed to connect to endpoints in TeamServer required for trace/finding related information.
          #
          # @return [String]
          def trace_endpoint
            @_trace_endpoint ||= "#{ Contrast::API.api_url }/agents#{ ENDPOINT_VERSION }/traces"\
                                 "#{ server_path_segment }#{ application_path_segment }"
          end

          # The server host, path, and type; required for endpoints that are server specific.
          #
          # @return [String]
          def server_path_segment
            @_server_path_segment ||= "/#{ Base64.urlsafe_encode64(server_host_name, padding: false) }"\
                                      "/#{ Base64.urlsafe_encode64(server_path, padding: false) }"\
                                      "/#{ Base64.urlsafe_encode64(server_type, padding: false) }"
          end

          # The application language and name; required for endpoints that are application specific.
          #
          # @return [String]
          def application_path_segment
            @_application_path_segment ||= "/#{ Base64.urlsafe_encode64(APP_LANGUAGE, padding: false) }"\
                                           "/#{ Base64.urlsafe_encode64(app_name, padding: false) }"
          end

          # @return [String,nil]
          def server_host_name
            return @_server_host_name unless @_server_host_name.nil?

            @_server_host_name = ::Contrast::APP_CONTEXT.server_name
          end

          # @return [String,nil]
          def server_path
            return @_server_path unless @_server_path.nil?

            @_server_path = ::Contrast::APP_CONTEXT.server_path
          end

          # @return [String,nil]
          def server_type
            return @_server_type unless @_server_type.nil?

            @_server_type = ::Contrast::APP_CONTEXT.server_type
          end

          # @return [String,nil]
          def app_name
            return @_app_name unless @_app_name.nil?

            @_app_name = ::Contrast::APP_CONTEXT.app_name
          end

          # @return [String,nil]
          def with_rescue
            yield
          rescue StandardError => e
            logger.debug('Endpoint failed with the following error', e)
            Contrast::Utils::ObjectShare::EMPTY_STRING
          end
        end
      end
    end
  end
end