/**
 * Copyright 2026 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

locals {
  _alerts_factory_data_raw = merge([
    for k in local.observability_factory_data_raw :
    lookup(k, "alerts", {})
  ]...)
  _alerts_factory_data = {
    for k, v in local._alerts_factory_data_raw :
    k => {
      combiner              = v.combiner
      display_name          = try(v.display_name, null)
      enabled               = try(v.enabled, null)
      notification_channels = try(v.notification_channels, [])
      severity              = try(v.severity, null)
      user_labels           = try(v.user_labels, null)
      alert_strategy = !can(v.alert_strategy) ? null : {
        auto_close           = try(v.alert_strategy.auto_close, null)
        notification_prompts = try(v.alert_strategy.notification_prompts, null)
        notification_rate_limit = !can(v.alert_strategy.notification_rate_limit) ? null : {
          period = try(v.alert_strategy.notification_rate_limit.period, null)
        }
        notification_channel_strategy = !can(v.alert_strategy.notification_channel_strategy) ? null : {
          notification_channel_names = try(v.alert_strategy.notification_channel_strategy.notification_channel_names, null)
          renotify_interval          = try(v.alert_strategy.notification_channel_strategy.renotify_interval, null)
        }
      }
      conditions = !can(v.conditions) ? null : [
        for c in v.conditions : {
          display_name = c.display_name
          condition_absent = !can(c.condition_absent) ? null : {
            duration = c.condition_absent.duration
            filter   = try(c.condition_absent.filter, null)
            aggregations = !can(c.condition_absent.aggregations) ? null : [
              for a in c.condition_absent.aggregations : {
                per_series_aligner   = try(a.per_series_aligner, null)
                group_by_fields      = try(a.group_by_fields, null)
                cross_series_reducer = try(a.cross_series_reducer, null)
                alignment_period     = try(a.alignment_period, null)
              }
            ]
            trigger = !can(c.condition_absent.trigger) ? null : {
              count   = try(c.condition_absent.trigger.count, null)
              percent = try(c.condition_absent.trigger.percent, null)
            }
          }
          condition_matched_log = !can(c.condition_matched_log) ? null : {
            filter           = c.condition_matched_log.filter
            label_extractors = try(c.condition_matched_log.label_extractors, null)
          }
          condition_monitoring_query_language = !can(c.condition_monitoring_query_language) ? null : {
            duration                = c.condition_monitoring_query_language.duration
            query                   = c.condition_monitoring_query_language.query
            evaluation_missing_data = try(c.condition_monitoring_query_language.evaluation_missing_data, null)
            trigger = !can(c.condition_monitoring_query_language.trigger) ? null : {
              count   = try(c.condition_monitoring_query_language.trigger.count, null)
              percent = try(c.condition_monitoring_query_language.trigger.percent, null)
            }
          }
          condition_prometheus_query_language = !can(c.condition_prometheus_query_language) ? null : {
            query                     = c.condition_prometheus_query_language.query
            alert_rule                = try(c.condition_prometheus_query_language.alert_rule, null)
            disable_metric_validation = try(c.condition_prometheus_query_language.disable_metric_validation, null)
            duration                  = try(c.condition_prometheus_query_language.duration, null)
            evaluation_interval       = try(c.condition_prometheus_query_language.evaluation_interval, null)
            labels                    = try(c.condition_prometheus_query_language.labels, null)
            rule_group                = try(c.condition_prometheus_query_language.rule_group, null)
          }
          condition_threshold = !can(c.condition_threshold) ? null : {
            comparison              = c.condition_threshold.comparison
            duration                = c.condition_threshold.duration
            denominator_filter      = try(c.condition_threshold.denominator_filter, null)
            evaluation_missing_data = try(c.condition_threshold.evaluation_missing_data, null)
            filter                  = try(c.condition_threshold.filter, null)
            threshold_value         = try(c.condition_threshold.threshold_value, null)
            aggregations = !can(c.condition_threshold.aggregations) ? null : [
              for a in c.condition_threshold.aggregations : {
                per_series_aligner   = try(a.per_series_aligner, null)
                group_by_fields      = try(a.group_by_fields, null)
                cross_series_reducer = try(a.cross_series_reducer, null)
                alignment_period     = try(a.alignment_period, null)
              }
            ]
            denominator_aggregations = !can(c.condition_threshold.denominator_aggregations) ? null : [
              for a in c.condition_threshold.denominator_aggregations : {
                per_series_aligner   = try(a.per_series_aligner, null)
                group_by_fields      = try(a.group_by_fields, null)
                cross_series_reducer = try(a.cross_series_reducer, null)
                alignment_period     = try(a.alignment_period, null)
              }
            ]
            forecast_options = !can(c.condition_threshold.forecast_options) ? null : {
              forecast_horizon = c.condition_threshold.forecast_options.forecast_horizon
            }
            trigger = !can(c.condition_threshold.trigger) ? null : {
              count   = try(c.condition_threshold.trigger.count, null)
              percent = try(c.condition_threshold.trigger.percent, null)
            }
          }
        }
      ]
      documentation = !can(v.documentation) ? null : {
        content   = try(v.documentation.content, null)
        mime_type = try(v.documentation.mime_type, null)
        subject   = try(v.documentation.subject, null)
        links = !can(v.documentation.links) ? null : [
          for l in v.documentation.links : {
            display_name = try(l.display_name, null)
            url          = try(l.url, null)
        }]
      }
    }
  }
  alerts = merge(local._alerts_factory_data, var.alerts)
}

resource "google_monitoring_alert_policy" "alerts" {
  for_each = local.alerts
  project  = local.project.project_id

  combiner     = each.value.combiner
  display_name = each.value.display_name
  enabled      = each.value.enabled
  notification_channels = [
    for x in each.value.notification_channels :
    try(
      # first try to get a channel created by this module
      google_monitoring_notification_channel.channels[x].name,
      # otherwise check the context
      local.ctx.notification_channels[x],
      # if nothing else, use the provided channel as is
      x
    )
  ]
  severity    = each.value.severity
  user_labels = each.value.user_labels

  dynamic "alert_strategy" {
    for_each = each.value.alert_strategy[*]
    content {
      auto_close           = alert_strategy.value.auto_close
      notification_prompts = alert_strategy.value.notification_prompts
      dynamic "notification_channel_strategy" {
        for_each = alert_strategy.value.notification_channel_strategy[*]
        content {
          notification_channel_names = notification_channel_strategy.value.notification_channel_names
          renotify_interval          = notification_channel_strategy.value.renotify_interval
        }
      }
      dynamic "notification_rate_limit" {
        for_each = alert_strategy.value.notification_rate_limit[*]
        content {
          period = notification_rate_limit.value.period
        }
      }
    }
  }
  dynamic "conditions" {
    for_each = each.value.conditions
    content {
      display_name = conditions.value.display_name
      dynamic "condition_absent" {
        for_each = conditions.value.condition_absent[*]
        content {
          duration = condition_absent.value.duration
          filter   = condition_absent.value.filter
          dynamic "aggregations" {
            for_each = coalesce(condition_absent.value.aggregations, [])
            content {
              alignment_period     = aggregations.value.alignment_period
              cross_series_reducer = aggregations.value.cross_series_reducer
              group_by_fields      = aggregations.value.group_by_fields
              per_series_aligner   = aggregations.value.per_series_aligner
            }
          }
          dynamic "trigger" {
            for_each = condition_absent.value.trigger[*]
            content {
              count   = trigger.value.count
              percent = trigger.value.percent
            }
          }
        }
      }
      dynamic "condition_matched_log" {
        for_each = conditions.value.condition_matched_log[*]
        content {
          filter           = condition_matched_log.value.filter
          label_extractors = condition_matched_log.value.label_extractors
        }
      }
      dynamic "condition_monitoring_query_language" {
        for_each = conditions.value.condition_monitoring_query_language[*]
        content {
          duration                = condition_monitoring_query_language.value.duration
          query                   = condition_monitoring_query_language.value.query
          evaluation_missing_data = condition_monitoring_query_language.value.evaluation_missing_data
          dynamic "trigger" {
            for_each = condition_monitoring_query_language.value.trigger[*]
            content {
              count   = trigger.value.count
              percent = trigger.value.percent
            }
          }
        }
      }

      dynamic "condition_prometheus_query_language" {
        for_each = conditions.value.condition_prometheus_query_language[*]
        content {
          query                     = condition_prometheus_query_language.value.query
          disable_metric_validation = condition_prometheus_query_language.value.disable_metric_validation
          duration                  = condition_prometheus_query_language.value.duration
          evaluation_interval       = condition_prometheus_query_language.value.evaluation_interval
          labels                    = condition_prometheus_query_language.value.labels
          rule_group                = condition_prometheus_query_language.value.rule_group
          alert_rule                = condition_prometheus_query_language.value.alert_rule
        }
      }
      dynamic "condition_threshold" {
        for_each = conditions.value.condition_threshold[*]
        content {
          comparison              = condition_threshold.value.comparison
          duration                = condition_threshold.value.duration
          denominator_filter      = condition_threshold.value.denominator_filter
          evaluation_missing_data = condition_threshold.value.evaluation_missing_data
          filter                  = condition_threshold.value.filter
          threshold_value         = condition_threshold.value.threshold_value
          dynamic "aggregations" {
            for_each = coalesce(condition_threshold.value.aggregations, [])
            content {
              alignment_period     = aggregations.value.alignment_period
              cross_series_reducer = aggregations.value.cross_series_reducer
              group_by_fields      = aggregations.value.group_by_fields
              per_series_aligner   = aggregations.value.per_series_aligner
            }
          }
          dynamic "denominator_aggregations" {
            for_each = coalesce(condition_threshold.value.denominator_aggregations, [])
            content {
              alignment_period     = denominator_aggregations.value.alignment_period
              cross_series_reducer = denominator_aggregations.value.cross_series_reducer
              group_by_fields      = denominator_aggregations.value.group_by_fields
              per_series_aligner   = denominator_aggregations.value.per_series_aligner
            }
          }
          dynamic "forecast_options" {
            for_each = condition_threshold.value.forecast_options[*]
            content {
              forecast_horizon = forecast_options.value.forecast_horizon
            }
          }
          dynamic "trigger" {
            for_each = condition_threshold.value.trigger[*]
            content {
              count   = trigger.value.count
              percent = trigger.value.percent
            }
          }
        }
      }
    }
  }
  dynamic "documentation" {
    for_each = each.value.documentation[*]
    content {
      content   = documentation.value.content
      mime_type = documentation.value.mime_type
      subject   = documentation.value.subject
      dynamic "links" {
        for_each = documentation.value.links[*]
        content {
          display_name = links.value.display_name
          url          = links.value.url
        }
      }
    }
  }

  depends_on = [google_logging_metric.metrics]
}
