provider "aws" {
  region = "us-east-1"
}

data "aws_caller_identity" "current" {}

terraform {
  backend "s3" {
    bucket  = "orcd-terraform-state"
    key     = "prod/lambda-notifications/terraform.tfstate"
    region  = "us-east-1"
    encrypt = "true"
  }
}

moved {
  from = aws_iam_policy.dynamodb_policy
  to = aws_iam_policy.lambda_notification_event_buffer_dynamodb_policy
}

module "lambda_push_delivery_failure_owsrequest" {
  source = "git@github.com:theorchard/terraform-owsrequest.git?ref=1.0.1"

  environment_name = var.environment
  service_name     = "lambda-notifications-push-delivery-failure"
}

data "aws_iam_policy_document" "sns_endpoint_policy_document" {
  statement {
    effect = "Allow"
    actions = [
      "sns:GetEndpointAttributes"
    ]
    resources = [
      "arn:aws:sns:us-east-1:437795906767:app/APNS/PROD_Orchard_Go",
      "arn:aws:sns:us-east-1:437795906767:app/GCM/PROD_Orchard_Go_FCM",
      "arn:aws:sns:us-east-1:437795906767:app/GCM/prod-awal",
      "arn:aws:sns:us-east-1:437795906767:app/APNS/prod-awal",
      "arn:aws:sns:us-east-1:437795906767:app/GCM/prod-sme",
      "arn:aws:sns:us-east-1:437795906767:app/APNS/prod-sme"
    ]
  }
}

resource "aws_iam_policy" "sns_endpoint_policy" {
  name   = "${var.environment}-sns-push-endpoint-delivery-failure-lambda-policy"
  policy = data.aws_iam_policy_document.sns_endpoint_policy_document.json
}

module "lambda-push-delivery-failure" {
  source = "git@github.com:theorchard/terraform-lambda.git?ref=3.1.6"

  application_family       = var.application_family
  use_container_image      = true
  datadog_advanced_enabled = true
  environment              = var.environment
  lambda_name              = "push-delivery-failure"
  lambda_description       = "Reacts to EventDeliveryFailure messages from SNS push notifications"
  lambda_function_timeout  = var.lambda_timeout

  vpc_enabled    = true
  vpc_id         = var.vpc_id
  vpc_subnet_ids = var.vpc_subnet_ids

  iam_managed_policy_attachments = [
    module.lambda_push_delivery_failure_owsrequest.policy_arn_output,
    aws_iam_policy.sns_endpoint_policy.arn
  ]
  lambda_function_reserved_concurrent_executions = "3"
  lambda_function_environment_variables = {
    Environment = var.environment
  }
}

module "sentry-push-delivery-failure" {
  source = "git@github.com:theorchard/terraform-sentry.git?ref=4.1.2"

  application_family = var.application_family
  environment        = var.environment
  platform           = "python"
  service_name       = "push-delivery-failure"
}

module "datadog_lambda_push_delivery_failure" {
  source = "git@github.com:theorchard/terraform-datadog.git//modules/lambda?ref=6.13.4"

  environment                              = var.environment
  service_name                             = "push-delivery-failure"

  lambda_error_monitor_enabled             = true
  lambda_error_warning_number              = null
  lambda_error_warning_recovery_number     = null
  lambda_error_critical_number             = 1
  lambda_error_critical_recovery_number    = null

  lambda_throttle_monitor_enabled          = true
  lambda_throttle_critical_number          = 10
  lambda_throttle_warning_number           = null
  lambda_throttle_warning_recovery_number  = null
  lambda_throttle_critical_recovery_number = null

  lambda_max_memory_used_enabled                   = true
  lambda_max_memory_usage_ok_number                = null
  lambda_max_memory_usage_critical_number          = 85
  lambda_max_memory_usage_warning_number           = null
  lambda_max_memory_usage_warning_recovery_number  = null
  lambda_max_memory_usage_critical_recovery_number = null

  notification_endpoints                   = var.notification_endpoints
  escalation_notification_endpoints        = var.escalation_notification_endpoints
  teams                                    = var.teams
}

module "sns-push-delivery-failure" {
  source = "git@github.com:theorchard/terraform-sns.git?ref=2.1.1"

  environment                     = var.environment
  application_family              = var.application_family
  sns_topic_name                  = "push-delivery-failure"
  sns_subscription_enabled        = true
  sns_lambda_function_arn         = module.lambda-push-delivery-failure.lambda_arn
}

resource "aws_lambda_permission" "allow_proxy_sns_messages" {
  statement_id  = "${var.environment}-trigger-lambda-from-sns-for-push-delivery-failure"
  action        = "lambda:InvokeFunction"
  function_name = module.lambda-push-delivery-failure.lambda_name
  principal     = "sns.amazonaws.com"
  source_arn    = module.sns-push-delivery-failure.topic_arn
}

module "fanout_event_queue" {
  source = "git@github.com:theorchard/terraform-sqs.git?ref=2.3.3"

  environment                    = var.environment
  queue_name                     = var.fanout_queue_name
  application_family             = var.application_family
  sqs_message_retention_seconds  = 10800
  sqs_visibility_timeout_seconds = 360
  sqs_max_message_size           = 262144
  sqs_fifo_queue                 = "false"

  sqs_deadletter_enabled = "true"

  deadletter_message_retention_seconds = 86400
  deadletter_max_recieve_count         = 5
  deadletter_delay_seconds             = 10
  deadletter_max_message_size          = 262144
  deadletter_receive_wait_time_seconds = 10
}

module "push_notifications_queue" {
  source = "git@github.com:theorchard/terraform-sqs.git?ref=2.3.3"

  environment                    = var.environment
  queue_name                     = var.queue_name
  application_family             = var.application_family
  sqs_message_retention_seconds  = 10800
  sqs_visibility_timeout_seconds = 360
  sqs_max_message_size           = 262144
  sqs_fifo_queue                 = "false"

  sqs_deadletter_enabled = "true"

  deadletter_message_retention_seconds = 86400
  deadletter_max_recieve_count         = 1
  deadletter_delay_seconds             = 10
  deadletter_max_message_size          = 262144
  deadletter_receive_wait_time_seconds = 10
}

resource "aws_iam_user" "getstream_iam_user" {
  name = "${var.environment}-getstream-user"
  tags = {
    terraformed = true,
    role = "service-user"
  }
}

data "aws_iam_policy_document" "getstream_role_policy" {
  statement {

    sid = ""

    actions = [
      "sqs:SendMessage",
      "sqs:SendMessageBatch",
      "sqs:GetQueueUrl",
      "sqs:GetQueueAttributes"
    ]

    resources = [
      module.push_notifications_queue.queue_arn
    ]
  }
}

resource "aws_iam_policy" "getstream_iam_policy" {
  name   = "${var.environment}-getstream-policy"
  policy = data.aws_iam_policy_document.getstream_role_policy.json
}

resource "aws_iam_user_policy_attachment" "getstream_iam_attachment" {
  user       = aws_iam_user.getstream_iam_user.name
  policy_arn = aws_iam_policy.getstream_iam_policy.arn
}

module "lambda_publish_message_owsrequest" {
  source = "git@github.com:theorchard/terraform-owsrequest.git?ref=1.0.0"

  environment_name = var.environment
  service_name     = "lambda-notifications-publish-message"
}


module "lambda_fanout_event_owsrequest" {
  source = "git@github.com:theorchard/terraform-owsrequest.git?ref=1.0.0"

  environment_name = var.environment
  service_name     = "lambda-notifications-fanout-event"
}

module "lambda_fanout_event" {
  source = "git@github.com:theorchard/terraform-lambda.git?ref=3.1.6"

  application_family       = var.application_family
  use_container_image      = true
  datadog_advanced_enabled = true
  environment              = var.environment
  lambda_name              = "fanout-event"
  lambda_description       = "SQS triggers a call to fanout events into GetStream"
  lambda_function_timeout  = var.lambda_timeout

  vpc_enabled    = true
  vpc_id         = var.vpc_id
  vpc_subnet_ids = var.vpc_subnet_ids

  iam_managed_policy_attachments = [
    module.lambda_fanout_event_owsrequest.policy_arn_output
  ]
  event_source_mapping_queue_name                = "${var.environment}-${var.fanout_queue_name}-queue"
  event_source_mapping_batch_size                = 10
  sqs_event_enabled                              = true
  lambda_function_memory_size                    = "384"
  lambda_function_reserved_concurrent_executions = "10"
  lambda_function_environment_variables = {
    Environment = var.environment
  }
  datadog_function_destination_lambda_name = "DatadogLambdaFunction"
}

module "datadog_lambda_fanout_event" {
  source = "git@github.com:theorchard/terraform-datadog.git//modules/lambda?ref=6.13.4"

  environment                              = var.environment
  service_name                             = "fanout-event"

  lambda_error_monitor_enabled             = true
  lambda_error_warning_number              = null
  lambda_error_warning_recovery_number     = null
  lambda_error_critical_number             = 1
  lambda_error_critical_recovery_number    = null

  lambda_throttle_monitor_enabled          = true
  lambda_throttle_critical_number          = 600
  lambda_throttle_warning_number           = null
  lambda_throttle_warning_recovery_number  = null
  lambda_throttle_critical_recovery_number = null

  lambda_anomaly_monitor_enabled           = true

  lambda_max_memory_used_enabled                   = true
  lambda_max_memory_usage_ok_number                = null
  lambda_max_memory_usage_critical_number          = 85
  lambda_max_memory_usage_warning_number           = null
  lambda_max_memory_usage_warning_recovery_number  = null
  lambda_max_memory_usage_critical_recovery_number = null

  notification_endpoints                   = var.notification_endpoints
  escalation_notification_endpoints        = var.escalation_notification_endpoints
  teams                                    = var.teams
}

module "lambda_publish_message" {
  source = "git@github.com:theorchard/terraform-lambda.git?ref=3.1.6"

  application_family       = var.application_family
  use_container_image      = true
  datadog_advanced_enabled = true
  environment              = var.environment
  lambda_name              = "publish-message"
  lambda_description       = "SQS triggers a publish call to user SNS topic"
  lambda_function_timeout = var.lambda_timeout

  vpc_enabled    = true
  vpc_id         = var.vpc_id
  vpc_subnet_ids = var.vpc_subnet_ids

  iam_managed_policy_attachments = [
    module.lambda_publish_message_owsrequest.policy_arn_output
  ]
  event_source_mapping_queue_name                = "${var.environment}-${var.queue_name}-queue"
  event_source_mapping_batch_size                = 10
  sqs_event_enabled                              = true
  iam_policy_file_enabled                        = true
  lambda_function_reserved_concurrent_executions = "10"
  lambda_function_memory_size                    = "384"
  lambda_function_environment_variables = {
    Environment      = var.environment,
    BUFFER_POLLER_ID = module.lambda_buffer_poller.lambda_role_unique_id,
    GETSTREAM_ID     = aws_iam_user.getstream_iam_user.unique_id
  }
}

module "datadog_lambda_publish_message" {
  source = "git@github.com:theorchard/terraform-datadog.git//modules/lambda?ref=6.13.4"

  environment                              = var.environment
  service_name                             = "publish-message"

  lambda_error_monitor_enabled             = true
  lambda_error_warning_number              = null
  lambda_error_warning_recovery_number     = null
  lambda_error_critical_number             = 1
  lambda_error_critical_recovery_number    = null

  lambda_throttle_monitor_enabled          = true
  lambda_throttle_critical_number          = 100
  lambda_throttle_warning_number           = null
  lambda_throttle_warning_recovery_number  = null
  lambda_throttle_critical_recovery_number = null

  lambda_anomaly_monitor_enabled           = true

  lambda_max_memory_used_enabled                   = true
  lambda_max_memory_usage_ok_number                = null
  lambda_max_memory_usage_critical_number          = 85
  lambda_max_memory_usage_warning_number           = null
  lambda_max_memory_usage_warning_recovery_number  = null
  lambda_max_memory_usage_critical_recovery_number = null

  notification_endpoints                   = var.notification_endpoints
  escalation_notification_endpoints        = var.escalation_notification_endpoints
  teams                                    = var.teams
}

module "sentry_fanout_event" {
  source = "git@github.com:theorchard/terraform-sentry.git?ref=4.1.2"

  application_family = var.application_family
  environment        = var.environment
  platform           = "python"
  service_name       = "fanout-event"
}

module "sentry_publish_message" {
  source = "git@github.com:theorchard/terraform-sentry.git?ref=4.1.2"

  application_family = var.application_family
  environment        = var.environment
  platform           = "python"
  service_name       = "publish-message"
}

module "notification_event_buffer_dynamo_table" {
  source                         = "git@github.com:theorchard/terraform-dynamodb.git//?ref=3.3.1"
  env                            = var.environment
  application_family             = var.application_family
  use_on_demand                  = true
  server_side_encryption_enabled = true
  table_name                     = "notifications-buffer"
  hash_key                       = var.event_buffer_dynamo_table_hash_key

  attribute = [
    {
      name = var.event_buffer_dynamo_table_hash_key
      type = "S"
    }
  ]
}

module "lambda_buffer_poller" {
  source = "git@github.com:theorchard/terraform-lambda.git?ref=3.1.6"

  application_family       = var.application_family
  environment              = var.environment
  use_container_image      = true
  datadog_advanced_enabled = true
  lambda_name              = "buffer-poller"
  lambda_description       = "Polls dynamodb and writes to SQS"
  lambda_function_timeout  = var.lambda_timeout

  vpc_enabled    = true
  vpc_id         = var.vpc_id
  vpc_subnet_ids = var.vpc_subnet_ids

  iam_managed_policy_attachments = [
    module.lambda_buffer_poller_owsrequest.policy_arn_output,
    aws_iam_policy.sqs_send_message_policy.arn,
    aws_iam_policy.lambda_notification_event_buffer_dynamodb_policy.arn
  ]
  lambda_function_reserved_concurrent_executions = "3"
  lambda_function_environment_variables = {
    Environment                = var.environment,
    PUSH_NOTIFICATIONS_SQS_URL = module.push_notifications_queue.queue_url
  }
}

module "datadog_lambda_buffer_poller" {
  source = "git@github.com:theorchard/terraform-datadog.git//modules/lambda?ref=6.13.4"

  environment                              = var.environment
  service_name                             = "buffer-poller"

  lambda_error_monitor_enabled             = true
  lambda_error_warning_number              = null
  lambda_error_warning_recovery_number     = null
  lambda_error_critical_number             = 1
  lambda_error_critical_recovery_number    = null

  lambda_throttle_monitor_enabled          = true
  lambda_throttle_critical_number          = 10
  lambda_throttle_warning_number           = null
  lambda_throttle_warning_recovery_number  = null
  lambda_throttle_critical_recovery_number = null

  lambda_anomaly_monitor_enabled           = true

  lambda_max_memory_used_enabled                   = true
  lambda_max_memory_usage_ok_number                = null
  lambda_max_memory_usage_critical_number          = 85
  lambda_max_memory_usage_warning_number           = null
  lambda_max_memory_usage_warning_recovery_number  = null
  lambda_max_memory_usage_critical_recovery_number = null

  notification_endpoints                   = var.notification_endpoints
  escalation_notification_endpoints        = var.escalation_notification_endpoints
  teams                                    = var.teams
}

data "aws_iam_policy_document" "sqs_send_message_policy_document" {
  statement {
    effect = "Allow"
    actions = [
      "sqs:SendMessage",
      "sqs:SendMessageBatch"
    ]
    resources = [
      module.push_notifications_queue.queue_arn
    ]
  }
}

resource "aws_iam_policy" "sqs_send_message_policy" {
  name   = "${var.environment}-sqs-send-message-buffer-poller-lambda-policy"
  policy = data.aws_iam_policy_document.sqs_send_message_policy_document.json
}

data "aws_iam_policy_document" "lambda_notification_event_buffer_dynamodb_policy_document" {
  statement {
    effect = "Allow"
    actions = [
      "dynamodb:Scan"
    ]
    resources = [
      module.notification_event_buffer_dynamo_table.aws_dynamodb_table_arn
    ]
  }
}

resource "aws_iam_policy" "lambda_notification_event_buffer_dynamodb_policy" {
  name   = "${var.environment}-dynamodb-buffer-poller-lambda-policy"
  policy = data.aws_iam_policy_document.lambda_notification_event_buffer_dynamodb_policy_document.json
}

module "lambda_buffer_poller_owsrequest" {
  source = "git@github.com:theorchard/terraform-owsrequest.git?ref=1.0.0"

  environment_name = var.environment
  service_name     = "lambda-notifications-buffer-poller"
}

module "sentry-buffer-poller" {
  source = "git@github.com:theorchard/terraform-sentry.git?ref=4.1.2"

  application_family = var.application_family
  environment        = var.environment
  platform           = "python"
  service_name       = "buffer-poller"
}

resource "aws_cloudwatch_event_rule" "buffer_poller_event" {
  name                = "${var.environment}-buffer-poller-event"
  description         = "Event for polling dynamodb buffer table"
  schedule_expression = "rate(15 minutes)"
}

resource "aws_cloudwatch_event_target" "buffer_poller_event_target" {
  rule      = aws_cloudwatch_event_rule.buffer_poller_event.name
  target_id = "${var.environment}-buffer-poller-event"
  arn       = module.lambda_buffer_poller.lambda_arn
  input     = "{\"eventType\": \"poll-buffer\"}"
}

resource "aws_lambda_permission" "allow_cloudwatch_buffer_poller_event" {
  statement_id  = "AllowBufferPollerExecutionFromCloudWatch"
  action        = "lambda:InvokeFunction"
  function_name = module.lambda_buffer_poller.lambda_name
  principal     = "events.amazonaws.com"
  source_arn    = aws_cloudwatch_event_rule.buffer_poller_event.arn
}
