locals {
  dsp_api_secrets_list = [
    "DELPHI_API",
    "DELPHI_JAVA_API",
    "DSPAPI_APPKEY",
    "SENTRY_DSN",
  ]

  dsp_api_common_secrets = {
    ADMINAPI_KEY      = aws_secretsmanager_secret.common_secret["ADMINAPI_KEY"]
    VENDOR_API_APPKEY = aws_secretsmanager_secret.common_secret["VENDORAPI_APPKEY"]
  }

  dsp_api_secrets_mapping = [
    for k, v in merge(aws_secretsmanager_secret.dsp_api_secret, local.dsp_api_common_secrets) :
    {
      name      = k,
      valueFrom = "arn:aws:secretsmanager:${var.aws_region_id}:${local.account_id}:secret:${v["name"]}"
    }
  ]

  dsp_api_env_vars = [
    {
      name  = "DEFAULT_DELPHI_PAGE_SIZE",
      value = 5000
    },
    {
      name  = "DEBUG",
      value = "true"
    },
    {
      name  = "ENVIRONMENT",
      value = local.environment
    },
    {
      name  = "ADMINAPI_HOSTNAME",
      value = module.domains.dev["admin-api-proxy"]
    },
    {
      name  = "VENDOR_API_BASE_URL",
      value = "https://${module.domains.dev["vendor-api"]}"
    },
    {
      name  = "DELPHI_STREAMS_CLEANING_MODE",
      value = "NULLABLE_ONLY"
    },
    {
      name  = "USE_DEFAULT_DELPHI_STREAMS_INCLUDE",
      value = ""
    },
  ]
}

data "aws_ecr_repository" "dsp_api_ecr" {
  name = "${local.project_group}/dsp-api"
}

data "aws_secretsmanager_secret_version" "dsp_api_auth_key" {
  secret_id = "${local.secrets_name_prefix}/dsp-api/DSPAPI_APPKEY"
}

resource "aws_secretsmanager_secret" "dsp_api_secret" {
  for_each = toset(local.dsp_api_secrets_list)

  name       = "${local.secrets_name_prefix}/dsp-api/${each.value}"
  kms_key_id = data.aws_kms_key.secrets_general_key.id

  tags = merge(
    local.common_tags,
    {
      project                  = "Infrastructure",
      service                  = "Secrets Manager",
      plat_env_project_service = "${local.aggregated_tag}_INFRA_SCRT"
    }
  )
}

module "dsp_api_task_def" {
  source = "../../../modules/ecs/tasks/fargate_v3"

  env_prefix      = local.env_prefix
  project_group   = local.project_group
  family          = "${local.env_prefix}-${local.project_group}-dsp-api"
  container_name  = "dsp-api"
  container_image = "${data.aws_ecr_repository.dsp_api_ecr.repository_url}:${local.docker_image_env_tag[local.env_prefix]}"
  cpu             = 1024
  memory          = 2048

  healthcheck = {
    command     = ["CMD-SHELL", "curl -f http://localhost:8000/health || exit 1"]
    retries     = 3
    timeout     = 5
    interval    = 30
    startPeriod = 5
  }

  datadog_enabled    = true
  dd_apm_enabled     = true
  dd_logs_injection  = true
  dd_container_image = "public.ecr.aws/datadog/agent:latest"
  dd_awslogs_group   = aws_cloudwatch_log_group.datadog_agent.name
  dd_env_vars = [
    {
      name  = "DD_APM_IGNORE_RESOURCES",
      value = "GET /health"
    },
    {
      name  = "DD_TAGS",
      value = "service:apollo-dsp-api application_family:apollo"
    },
  ]
  dd_secrets = [
    {
      name      = "DD_API_KEY",
      valueFrom = "arn:aws:secretsmanager:us-east-1:${local.account_id}:secret:apollo/${local.env_prefix}/common/DD_API_KEY"
    }
  ]

  awslogs_retention = module.cloudwatch_logs_retention_by_env[local.env_prefix]

  task_role_arn = data.aws_iam_role.standard_exec.arn
  exec_role_arn = data.aws_iam_role.standard_exec.arn

  env_vars = local.dsp_api_env_vars
  secrets  = local.dsp_api_secrets_mapping

  port_mappings = [
    {
      containerPort = 8000
      hostPort      = 8000
      protocol      = "tcp"
    }
  ]

  docker_labels = {
    "traefik.enable" = "true"

    "traefik.http.services.apollo-dsp-api.loadBalancer.server.port"          = "8000"
    "traefik.http.services.apollo-dsp-api.loadBalancer.server.scheme"        = "http"
    "traefik.http.services.apollo-dsp-api.loadBalancer.healthCheck.interval" = "30s"
    "traefik.http.services.apollo-dsp-api.loadBalancer.healthCheck.path"     = "/health"
    "traefik.http.services.apollo-dsp-api.loadBalancer.healthCheck.port"     = "8000"
    "traefik.http.services.apollo-dsp-api.loadBalancer.healthCheck.scheme"   = "http"
    "traefik.http.services.apollo-dsp-api.loadBalancer.healthCheck.timeout"  = "5s"

    // request via traefik
    "traefik.http.routers.dsp-api.rule"        = "Host(`${module.domains[local.env_prefix]["traefik"]}`) && PathPrefix(`/dsp-api`)"
    "traefik.http.routers.dsp-api.entryPoints" = "web"
    "traefik.http.routers.dsp-api.service"     = "apollo-dsp-api"
    "traefik.http.routers.dsp-api.middlewares" = join(",", [
      "dsp-api-cors@ecs",
      "dsp-api-gzip@ecs",
      "dsp-api-retry@ecs",
      "dsp-api-auth@ecs",
      "dsp-api-addAuthHeader@ecs",
      "dsp-api-stripPrefix@ecs",
      "dsp-api-addPrefix@ecs",
    ])

    "traefik.http.routers.dsp-api-ca-sporify.rule"        = "Host(`${module.domains[local.env_prefix]["traefik"]}`) && PathPrefix(`/spotify-consumer-analytics-compat`, `/apple-consumer-analytics`)"
    "traefik.http.routers.dsp-api-ca-sporify.entryPoints" = "web"
    "traefik.http.routers.dsp-api-ca-sporify.service"     = "apollo-dsp-api"
    "traefik.http.routers.dsp-api-ca-sporify.middlewares" = join(",", [
      "dsp-api-cors@ecs",
      "dsp-api-gzip@ecs",
      "dsp-api-retry@ecs",
      "dsp-api-auth@ecs",
      "dsp-api-addAuthHeader@ecs",
      "dsp-api-addPrefixCA@ecs",
    ])

    "traefik.http.middlewares.dsp-api-retry.retry.attempts"        = "3"
    "traefik.http.middlewares.dsp-api-retry.retry.initialInterval" = "100ms"

    "traefik.http.middlewares.dsp-api-auth.forwardAuth.address"             = "https://${module.domains[local.env_prefix]["auth-api"]}/authorize"
    "traefik.http.middlewares.dsp-api-auth.forwardAuth.trustForwardHeader"  = "true"
    "traefik.http.middlewares.dsp-api-auth.forwardAuth.authResponseHeaders" = "X-User-Id"

    "traefik.http.middlewares.dsp-api-addAuthHeader.headers.customRequestHeaders.Authorization" = data.aws_secretsmanager_secret_version.dsp_api_auth_key.secret_string

    "traefik.http.middlewares.dsp-api-stripPrefix.stripPrefix.prefixes"   = "/dsp-api"
    "traefik.http.middlewares.dsp-api-stripPrefix.stripPrefix.forceSlash" = "true"
    "traefik.http.middlewares.dsp-api-addPrefix.addPrefix.prefix"         = "/api"
    "traefik.http.middlewares.dsp-api-addPrefixCA.addPrefix.prefix"       = "/api/consumer_analytics"

    "traefik.http.middlewares.dsp-api-cors.headers.accessControlAllowMethods" = "GET,PUT,POST"
    "traefik.http.middlewares.dsp-api-cors.headers.accessControlAllowOriginList" = join(",", concat(formatlist("https://%s", [
      module.domains[local.env_prefix]["apolloapp"],
      module.domains.local["apolloapp"],
      ]), formatlist("http://%s", [
      module.domains.local["apolloapp"],
    ])))
    "traefik.http.middlewares.dsp-api-cors.headers.accessControlMaxAge" = "600"
    "traefik.http.middlewares.dsp-api-cors.headers.addVaryHeader"       = "true"

    "traefik.http.middlewares.dsp-api-gzip.compress" = "true"

    // direct requests
    "traefik.http.routers.dsp-api-internal.rule"        = "Host(`${module.domains[local.env_prefix]["dsp-api"]}`)"
    "traefik.http.routers.dsp-api-internal.entryPoints" = "web"
    "traefik.http.routers.dsp-api-internal.service"     = "apollo-dsp-api"
    "traefik.http.routers.dsp-api-internal.middlewares" = join(",", [
      "dsp-api-retry@ecs",
      "dsp-api-gzip@ecs",
    ])
  }

  common_tags = merge(
    local.common_tags,
    {
      project                  = "Portal",
      service                  = "ECS",
      plat_env_project_service = "${local.aggregated_tag}_PRL_ECS"
    }
  )
}

module "dsp_api_service" {
  source = "../../../modules/ecs/services/service_taskless_v3"

  env_prefix    = local.env_prefix
  project       = "dsp-api"
  project_group = local.project_group

  cluster_arn   = data.aws_ecs_cluster.main.arn
  desired_count = 0

  security_groups = [data.aws_security_group.main.id]
  subnets         = data.aws_subnets.private_subnets.ids
  vpc_id          = data.aws_vpc.main.id

  task_definition_arn = module.dsp_api_task_def.arn

  enable_ecs_managed_tags = true

  capacity_provider_strategy = {
    a = {
      base              = 1
      weight            = 2
      capacity_provider = "FARGATE_SPOT"
    },
    b = {
      base              = 0
      weight            = 1
      capacity_provider = "FARGATE"
    },
  }

  common_tags = merge(
    local.common_tags,
    {
      project                  = "Portal",
      service                  = "ECS",
      plat_env_project_service = "${local.aggregated_tag}_PRL_ECS",
      service_name             = "${local.project_group}-dsp-api",
    }
  )
}
/*
module "dsp_api_appautoscaling" {
  source = "../../../modules/appautoscaling/ecs"

  env_prefix           = local.env_prefix
  max_capacity         = 10
  min_capacity         = 2
  project              = "dsp-api"
  project_group        = local.project_group
  resource_id          = "service/${data.aws_ecs_cluster.main.cluster_name}/${module.dsp_api_service.ecs_service.name}"
  upscaling_adjustment = 1
}

resource "aws_cloudwatch_metric_alarm" "dsp_api_high_usage" {
  alarm_name          = "${local.name_prefix}-dsp-api_high_usage"
  alarm_description   = "Memory/CPU usage is higher than threshold."
  comparison_operator = "GreaterThanOrEqualToThreshold"
  evaluation_periods  = 1
  threshold           = 1
  actions_enabled     = true
  alarm_actions       = [module.dsp_api_appautoscaling.scaling_up_policy.arn]

  metric_query {
    id          = "check_thresholds"
    expression  = "(cpu >= 40 OR memory >= 60)"
    label       = "CPU and Memory 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.dsp_api_service.ecs_service.name
      }
    }
  }

  metric_query {
    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.dsp_api_service.ecs_service.name
      }
    }
  }
}

resource "aws_cloudwatch_metric_alarm" "dsp_api_low_usage" {
  alarm_name          = "${local.name_prefix}-dsp-api_low_usage"
  alarm_description   = "Memory/CPU usage is lower than threshold."
  comparison_operator = "GreaterThanOrEqualToThreshold"
  evaluation_periods  = 3
  threshold           = 1
  actions_enabled     = true
  alarm_actions       = [module.dsp_api_appautoscaling.scaling_down_policy.arn]

  metric_query {
    id          = "check_thresholds"
    expression  = "(cpu < 40 AND memory < 60)"
    label       = "CPU and Memory utilization limits"
    return_data = true
  }

  metric_query {
    id          = "cpu"
    return_data = false

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

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

  metric_query {
    id          = "memory"
    return_data = false

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

      dimensions = {
        ClusterName = data.aws_ecs_cluster.main.cluster_name
        ServiceName = module.dsp_api_service.ecs_service.name
      }
    }
  }
}
*/
