locals {
  autoscaling_enabled = toset(var.autoscaling_enabled ? ["as"] : [])
}

module "api_appautoscaling" {
  for_each = local.autoscaling_enabled

  source               = "../../../modules/appautoscaling/ecs"
  env_prefix           = var.env_prefix
  max_capacity         = var.autoscaling_max_tasks
  min_capacity         = var.autoscaling_min_tasks
  project              = "api${local.env_suffix}"
  project_group        = var.project_group
  resource_id          = "service/${data.aws_ecs_cluster.main.cluster_name}/${module.api_service.ecs_service.name}"
  upscaling_adjustment = var.autoscaling_step_size
}

resource "aws_cloudwatch_metric_alarm" "high_api" {
  for_each = local.autoscaling_enabled

  alarm_name          = "${local.name_prefix}-api${local.env_suffix}_high_usage"
  alarm_description   = "RequestCountPerTarget or Memory/CPU usage is higher than threshold."
  comparison_operator = "GreaterThanOrEqualToThreshold"
  evaluation_periods  = 1
  threshold           = 1
  actions_enabled     = true
  alarm_actions       = [module.api_appautoscaling[each.value].scaling_up_policy.arn]

  metric_query {
    id          = "check_thresholds"
    expression  = "(cpu >= ${var.autoscaling_cpu_high} %{if var.autoscaling_memory}OR memory >= ${var.autoscaling_memory_high}%{endif} OR requests_per_target >= ${var.autoscaling_requests_per_target_high})"
    label       = "CPU, Memory and RequestCountPerTarget utilization limits"
    return_data = true
  }

  metric_query {
    id          = "cpu"
    return_data = false

    metric {
      metric_name = "CPUUtilization"
      namespace   = "AWS/ECS"
      period      = "60"
      stat        = "Average"

      dimensions = {
        ClusterName = data.aws_ecs_cluster.main.cluster_name
        ServiceName = module.api_service.ecs_service.name
      }
    }
  }

  dynamic "metric_query" {
    for_each = var.autoscaling_memory ? ["Enabled"] : []
    content {
      id          = "memory"
      return_data = false

      metric {
        metric_name = "MemoryUtilization"
        namespace   = "AWS/ECS"
        period      = "60"
        stat        = "Average"

        dimensions = {
          ClusterName = data.aws_ecs_cluster.main.cluster_name
          ServiceName = module.api_service.ecs_service.name
        }
      }
    }
  }

  metric_query {
    id          = "requests_per_target"
    return_data = false

    metric {
      metric_name = "RequestCountPerTarget"
      namespace   = "AWS/ApplicationELB"
      period      = "60"
      stat        = "Sum"

      dimensions = {
        TargetGroup = module.api_service.tg_arn_suffix
      }
    }
  }
}

resource "aws_cloudwatch_metric_alarm" "low_api" {
  for_each = local.autoscaling_enabled

  alarm_name          = "${local.name_prefix}-api${local.env_suffix}_low_usage"
  alarm_description   = "Memory usage and cpu usage is lower than threshold."
  comparison_operator = "GreaterThanOrEqualToThreshold"
  evaluation_periods  = 3
  threshold           = 1
  actions_enabled     = true
  alarm_actions       = [module.api_appautoscaling[each.value].scaling_down_policy.arn]

  metric_query {
    id          = "check_thresholds"
    expression  = "(cpu < ${var.autoscaling_cpu_low} %{if var.autoscaling_memory}AND memory < ${var.autoscaling_memory_low}%{endif} AND requests_per_target < ${var.autoscaling_requests_per_target_low})"
    label       = "CPU and Memory utilization limits"
    return_data = true
  }

  dynamic "metric_query" {
    for_each = var.autoscaling_memory ? ["Enabled"] : []
    content {
      id          = "memory"
      return_data = false

      metric {
        metric_name = "MemoryUtilization"
        namespace   = "AWS/ECS"
        period      = "60"
        stat        = "Average"

        dimensions = {
          ClusterName = data.aws_ecs_cluster.main.cluster_name
          ServiceName = module.api_service.ecs_service.name
        }
      }
    }
  }

  metric_query {
    id          = "cpu"
    return_data = false

    metric {
      metric_name = "CPUUtilization"
      namespace   = "AWS/ECS"
      period      = "60"
      stat        = "Average"

      dimensions = {
        ClusterName = data.aws_ecs_cluster.main.cluster_name
        ServiceName = module.api_service.ecs_service.name
      }
    }
  }

  metric_query {
    id          = "requests_per_target"
    return_data = false

    metric {
      metric_name = "RequestCountPerTarget"
      namespace   = "AWS/ApplicationELB"
      period      = "60"
      stat        = "Sum"

      dimensions = {
        TargetGroup = module.api_service.tg_arn_suffix
      }
    }
  }
}
