# EventBridge event buses =====================================================

resource "aws_cloudwatch_event_bus" "this" {
  for_each = var.event_buses

  name               = each.value.name
  description        = each.value.description
  kms_key_identifier = each.value.kms_key_identifier

  tags = local.tags
}

# Event bus policies ----------------------------------------------------------

resource "aws_cloudwatch_event_bus_policy" "this" {
  for_each = {
    for k, v in var.event_buses : k => v
    if v.policy != null
  }

  event_bus_name = aws_cloudwatch_event_bus.this[each.key].name
  policy         = each.value.policy
}

# Event bus archives ----------------------------------------------------------

resource "aws_cloudwatch_event_archive" "this" {
  for_each = local.buses_with_archives

  name             = each.value.archive.name
  description      = each.value.archive.description
  event_source_arn = aws_cloudwatch_event_bus.this[each.key].arn
  retention_days   = each.value.archive.retention_days
  event_pattern    = each.value.archive.event_pattern
}

# EventBridge rules ===========================================================

resource "aws_cloudwatch_event_rule" "this" {
  for_each = var.rules

  name                = each.value.name
  description         = each.value.description
  event_bus_name      = local.rule_event_bus_names[each.key]
  state               = each.value.state
  event_pattern       = each.value.event_pattern
  schedule_expression = each.value.schedule_expression
  role_arn            = each.value.role_arn

  tags = local.tags
}

# EventBridge targets =========================================================

resource "aws_cloudwatch_event_target" "this" {
  for_each = var.targets

  rule           = aws_cloudwatch_event_rule.this[each.value.rule_key].name
  event_bus_name = local.target_event_bus_names[each.key]
  target_id      = each.value.target_id
  arn            = each.value.arn
  role_arn       = each.value.role_arn
  input          = each.value.input
  input_path     = each.value.input_path

  dynamic "input_transformer" {
    for_each = each.value.input_transformer != null ? [each.value.input_transformer] : []
    content {
      input_paths    = input_transformer.value.input_paths
      input_template = input_transformer.value.input_template
    }
  }

  dynamic "dead_letter_config" {
    for_each = each.value.dead_letter_config != null ? [each.value.dead_letter_config] : []
    content {
      arn = dead_letter_config.value.arn
    }
  }

  dynamic "retry_policy" {
    for_each = each.value.retry_policy != null ? [each.value.retry_policy] : []
    content {
      maximum_event_age_in_seconds = retry_policy.value.maximum_event_age_in_seconds
      maximum_retry_attempts       = retry_policy.value.maximum_retry_attempts
    }
  }

  dynamic "batch_target" {
    for_each = each.value.batch_target != null ? [each.value.batch_target] : []
    content {
      job_definition = batch_target.value.job_definition
      job_name       = batch_target.value.job_name
      array_size     = batch_target.value.array_size
      job_attempts   = batch_target.value.job_attempts
    }
  }

  dynamic "ecs_target" {
    for_each = each.value.ecs_target != null ? [each.value.ecs_target] : []
    content {
      task_definition_arn = ecs_target.value.task_definition_arn
      launch_type         = ecs_target.value.launch_type
      platform_version    = ecs_target.value.platform_version
      task_count          = ecs_target.value.task_count
      group               = ecs_target.value.group

      dynamic "network_configuration" {
        for_each = ecs_target.value.network_configuration != null ? [ecs_target.value.network_configuration] : []
        content {
          subnets          = network_configuration.value.subnets
          security_groups  = network_configuration.value.security_groups
          assign_public_ip = network_configuration.value.assign_public_ip
        }
      }
    }
  }

  dynamic "sqs_target" {
    for_each = each.value.sqs_target != null ? [each.value.sqs_target] : []
    content {
      message_group_id = sqs_target.value.message_group_id
    }
  }
}

# EventBridge connections =====================================================

resource "aws_cloudwatch_event_connection" "this" {
  for_each = var.connections

  name               = each.value.name
  description        = each.value.description
  authorization_type = each.value.authorization_type

  auth_parameters {
    dynamic "api_key" {
      for_each = each.value.auth_parameters.api_key != null ? [each.value.auth_parameters.api_key] : []
      content {
        key   = api_key.value.key
        value = api_key.value.value
      }
    }

    dynamic "basic" {
      for_each = each.value.auth_parameters.basic != null ? [each.value.auth_parameters.basic] : []
      content {
        username = basic.value.username
        password = basic.value.password
      }
    }

    dynamic "oauth" {
      for_each = each.value.auth_parameters.oauth != null ? [each.value.auth_parameters.oauth] : []
      content {
        authorization_endpoint = oauth.value.authorization_endpoint
        http_method            = oauth.value.http_method

        client_parameters {
          client_id     = oauth.value.client_parameters.client_id
          client_secret = oauth.value.client_parameters.client_secret
        }

        oauth_http_parameters {}
      }
    }
  }
}

# EventBridge API destinations ================================================

resource "aws_cloudwatch_event_api_destination" "this" {
  for_each = var.api_destinations

  name                             = each.value.name
  description                      = each.value.description
  connection_arn                   = aws_cloudwatch_event_connection.this[each.value.connection_key].arn
  invocation_endpoint              = each.value.invocation_endpoint
  http_method                      = each.value.http_method
  invocation_rate_limit_per_second = each.value.invocation_rate_limit_per_second
}

# EventBridge Pipes ===========================================================

resource "aws_pipes_pipe" "this" {
  for_each = var.pipes

  name          = each.value.name
  description   = each.value.description
  role_arn      = each.value.role_arn
  source        = each.value.source
  target        = each.value.target
  desired_state = each.value.state

  dynamic "source_parameters" {
    for_each = each.value.source_parameters != null ? [each.value.source_parameters] : []
    content {
      dynamic "filter_criteria" {
        for_each = source_parameters.value.filter_criteria != null ? [source_parameters.value.filter_criteria] : []
        content {
          dynamic "filter" {
            for_each = filter_criteria.value.filters
            content {
              pattern = filter.value.pattern
            }
          }
        }
      }

      dynamic "sqs_queue_parameters" {
        for_each = source_parameters.value.sqs_queue_parameters != null ? [source_parameters.value.sqs_queue_parameters] : []
        content {
          batch_size                         = sqs_queue_parameters.value.batch_size
          maximum_batching_window_in_seconds = sqs_queue_parameters.value.maximum_batching_window_in_seconds
        }
      }

      dynamic "kinesis_stream_parameters" {
        for_each = source_parameters.value.kinesis_stream_parameters != null ? [source_parameters.value.kinesis_stream_parameters] : []
        content {
          starting_position                  = kinesis_stream_parameters.value.starting_position
          batch_size                         = kinesis_stream_parameters.value.batch_size
          maximum_batching_window_in_seconds = kinesis_stream_parameters.value.maximum_batching_window_in_seconds
          maximum_retry_attempts             = kinesis_stream_parameters.value.maximum_retry_attempts
        }
      }

      dynamic "dynamodb_stream_parameters" {
        for_each = source_parameters.value.dynamodb_stream_parameters != null ? [source_parameters.value.dynamodb_stream_parameters] : []
        content {
          starting_position                  = dynamodb_stream_parameters.value.starting_position
          batch_size                         = dynamodb_stream_parameters.value.batch_size
          maximum_batching_window_in_seconds = dynamodb_stream_parameters.value.maximum_batching_window_in_seconds
          maximum_retry_attempts             = dynamodb_stream_parameters.value.maximum_retry_attempts
        }
      }
    }
  }

  dynamic "target_parameters" {
    for_each = each.value.target_parameters != null ? [each.value.target_parameters] : []
    content {
      input_template = target_parameters.value.input_template

      dynamic "sqs_queue_parameters" {
        for_each = target_parameters.value.sqs_queue_parameters != null ? [target_parameters.value.sqs_queue_parameters] : []
        content {
          message_group_id         = sqs_queue_parameters.value.message_group_id
          message_deduplication_id = sqs_queue_parameters.value.message_deduplication_id
        }
      }

      dynamic "lambda_function_parameters" {
        for_each = target_parameters.value.lambda_function_parameters != null ? [target_parameters.value.lambda_function_parameters] : []
        content {
          invocation_type = lambda_function_parameters.value.invocation_type
        }
      }

      dynamic "eventbridge_event_bus_parameters" {
        for_each = target_parameters.value.eventbridge_event_bus_parameters != null ? [target_parameters.value.eventbridge_event_bus_parameters] : []
        content {
          detail_type = eventbridge_event_bus_parameters.value.detail_type
          endpoint_id = eventbridge_event_bus_parameters.value.endpoint_id
          source      = eventbridge_event_bus_parameters.value.source
          time        = eventbridge_event_bus_parameters.value.time
          resources   = eventbridge_event_bus_parameters.value.resources
        }
      }
    }
  }

  tags = local.tags
}
