# frozen_string_literal: true

module Prometheus
  class CreateDefaultAlertsService < BaseService
    include Gitlab::Utils::StrongMemoize

    attr_reader :project

    DEFAULT_ALERTS = [
      {
        identifier: 'response_metrics_nginx_ingress_16_http_error_rate',
        operator: 'gt',
        threshold: 0.1
      },
      {
        identifier: 'response_metrics_nginx_ingress_http_error_rate',
        operator: 'gt',
        threshold: 0.1
      },
      {
        identifier: 'response_metrics_nginx_http_error_percentage',
        operator: 'gt',
        threshold: 0.1
      }
    ].freeze

    def initialize(project:)
      @project = project
    end

    def execute
      return ServiceResponse.error(message: 'Invalid project') unless project
      return ServiceResponse.error(message: 'Invalid environment') unless environment

      create_alerts
      schedule_prometheus_update

      ServiceResponse.success
    end

    private

    def create_alerts
      DEFAULT_ALERTS.each do |alert_hash|
        identifier = alert_hash[:identifier]
        next if alerts_by_identifier(environment).key?(identifier)

        metric = metrics_by_identifier[identifier]
        next unless metric

        create_alert(alert: alert_hash, metric: metric)
      end
    end

    def schedule_prometheus_update
      return unless prometheus_application

      ::Clusters::Applications::ScheduleUpdateService.new(prometheus_application, project).execute
    end

    def prometheus_application
      environment.cluster_prometheus_adapter
    end

    def metrics_by_identifier
      strong_memoize(:metrics_by_identifier) do
        metric_identifiers = DEFAULT_ALERTS.map { |alert| alert[:identifier] }

        PrometheusMetricsFinder
          .new(identifier: metric_identifiers, common: true)
          .execute
          .index_by(&:identifier)
      end
    end

    def alerts_by_identifier(environment)
      strong_memoize(:alerts_by_identifier) do
        Projects::Prometheus::AlertsFinder
          .new(project: project, metric: metrics_by_identifier.values, environment: environment)
          .execute
          .index_by { |alert| alert.prometheus_metric.identifier }
      end
    end

    def environment
      strong_memoize(:environment) do
        EnvironmentsFinder.new(project, nil, name: 'production').find.first ||
          project.environments.first
      end
    end

    def create_alert(alert:, metric:)
      PrometheusAlert.create!(
        project: project,
        prometheus_metric: metric,
        environment: environment,
        threshold: alert[:threshold],
        operator: alert[:operator]
      )
    rescue ActiveRecord::RecordNotUnique
      # Ignore duplicate creations although it unlikely to happen
    end
  end
end
