provider "aws" {
  region = var.aws_region
}

# Terraform backends cannot contain interpolations
terraform {
  backend "s3" {
    bucket  = "qa-supply-chain-terraform-state"
    key     = "qa/vector/encoder/terraform.tfstate"
    region  = "us-east-1"
    encrypt = "true"
  }
}

data "aws_caller_identity" "current" {}

data "aws_iam_policy_document" "kms_decryption_policy" {
  statement {
    actions = [
      "kms:Decrypt",
      "kms:DescribeKey",
    ]

    resources = [
      aws_kms_key.kms_key.arn,
    ]
  }
}

data "aws_vpc" "vpc" {
  tags = {
    Name = "${var.environment}-terraform-aws-vpc"
  }
}

data "aws_subnets" "private" {
  filter {
    name   = "vpc-id"
    values = [data.aws_vpc.vpc.id]
  }
  filter {
    name = "tag:Name"
    values = [
      "*_private_subnet_*",
    ]
  }
}

# Create KMS key and policies for certain encrypted configuration
resource "aws_kms_key" "kms_key" {
  description             = "${var.environment}-${var.service_name}"
  enable_key_rotation     = true
  deletion_window_in_days = 30
  tags                    = local.tags
}

resource "aws_kms_alias" "kms_alias" {
  name          = "alias/${var.environment}-${var.service_name}"
  target_key_id = aws_kms_key.kms_key.key_id
}

# Create KMS policy
resource "aws_iam_policy" "kms_policy" {
  name   = "KMS-${var.environment}-${var.service_name}-policy"
  policy = data.aws_iam_policy_document.kms_decryption_policy.json
  tags   = local.tags
}

# RW access to encoding buckets
data "aws_iam_policy" "encoding_s3_policy" {
  for_each = {
    for policy in local.s3_policies_to_attach : policy.policy_name => policy
  }
  name = each.value.policy_name
}

data "aws_iam_policy" "s3_mezzanine_assets_dir_readonly_policy" {
  name = "S3-${var.s3_mezz_bucket}-RO"
}

# Create policy to List, Read and delete message from Encoding SQS queue
data "aws_iam_policy_document" "sqs_encoding_queue_policy_document" {
  statement {
    actions = [
      "sqs:GetQueueAttributes",
      "sqs:GetQueueUrl",
      "sqs:ListQueues",
      "sqs:SendMessageBatch",
      "sqs:SendMessage",
      "sqs:CreateQueue",
      "sqs:DeleteMessage",
      "sqs:ReceiveMessage",
    ]

    resources = [
      # To match arn:aws:sqs:us-east-1:437795906767:qa-encoding18_e0000005_d0000471
      "arn:aws:sqs:${var.aws_region}:${data.aws_caller_identity.current.account_id}:${var.environment}-encoding17_e*",
      "arn:aws:sqs:${var.aws_region}:${data.aws_caller_identity.current.account_id}:${var.environment}-encoding17_e*/*",
      "arn:aws:sqs:${var.aws_region}:${data.aws_caller_identity.current.account_id}:${var.environment}-encoding18_e*",
      "arn:aws:sqs:${var.aws_region}:${data.aws_caller_identity.current.account_id}:${var.environment}-encoding18_e*/*",
    ]
  }

  statement {
    actions = [
      "sqs:GetQueueAttributes",
      "sqs:ListQueues"
    ]

    resources = [
      "arn:aws:sqs:${var.aws_region}:${data.aws_caller_identity.current.account_id}:*",
    ]
  }
}

resource "aws_iam_policy" "sqs_encoding_queue_policy" {
  name   = "sqs-${var.environment}-encoding-queue-R-policy"
  policy = data.aws_iam_policy_document.sqs_encoding_queue_policy_document.json
}

# Data resource for read-only policy to the configs S3 bucket
data "aws_iam_policy_document" "s3_configs_read_only_policy" {
  statement {
    actions = [
      "s3:GetBucketLocation",
      "s3:GetObject",
    ]

    resources = [
      "arn:aws:s3:::${var.environment}-${var.config_s3_bucket_suffix}/${var.service_name}/${var.environment}/*",
    ]
  }

  statement {
    actions = [
      "s3:ListBucket",
    ]

    resources = [
      "arn:aws:s3:::${var.environment}-${var.config_s3_bucket_suffix}/",
    ]
  }

  statement {
    actions = [
      "s3:GetBucketLocation",
      "s3:ListAllMyBuckets",
    ]

    resources = [
      "*",
    ]
  }
}

# Creates policy for read-only access to the S3 bucket
resource "aws_iam_policy" "s3_configs_read_only_policy" {
  name   = "S3-${var.environment}-${var.service_name}-RO"
  policy = data.aws_iam_policy_document.s3_configs_read_only_policy.json
  tags   = local.tags
}

# common sentry in qa for all encoders
# commented out; must be imported during migration
# module "encoding_worker_sentry_project" {
#   source             = "git@github.com:theorchard/terraform-sentry.git//?ref=4.1.2"
#   service_name       = var.service_name
#   environment        = var.environment
#   teams              = [var.environment]
#   application_family = var.application_family
#   platform           = "php"
# }

# Temporary Sentry DSN secret
resource "aws_secretsmanager_secret" "sentry_dsn_secret" {
  name        = "${var.environment}/${var.service_name}/SENTRY_DSN"
  description = "Sentry DSN"
  tags        = local.tags
}

# Video Encoding Worker
module "qa_vector_encoder_video_ecs_service" {
  for_each = {
    for service in local.flattened_video_service_list : "physical_location_${service.physical_location}-encoding_priority_${service.encoding_priority}" => service
  }
  providers = {
    aws.dns = aws
  }
  source                                = "git@github.com:theorchard/terraform-fargate.git//?ref=5.6.1"
  environment                           = var.environment
  service_name                          = "${var.service_name}-video-phys-loc-${each.value.physical_location}-p${each.value.encoding_priority}"
  non_ecr_image                         = "086679231553.dkr.ecr.${var.aws_region}.amazonaws.com/${var.service_name}:latest"
  vpc_id                                = data.aws_vpc.vpc.id
  application_family                    = var.application_family
  secrets_manager_service_name          = var.service_name
  aws_region                            = var.aws_region
  commit_sha                            = "latest"
  task_type                             = "worker"
  ecs_network_mode                      = "awsvpc"
  ecs_requires_compatibilities          = ["FARGATE"]
  ecs_launch_type                       = "FARGATE"
  ordered_placement_strategy_type       = "random"
  health_check_command                  = "php --version"
  desired_task_count                    = each.value.min_task_count # Set during service creation here and controlled henceforth by autoscaling
  task_cpu                              = 256
  task_memory                           = 1024
  minimum_capacity                      = each.value.min_task_count
  maximum_capacity                      = each.value.max_task_count
  task_protection_policy_enabled        = true
  splitio_enabled                       = false
  ows_machine_to_machine_enabled        = false
  autoscaling_cpu_policy_enabled        = false
  autoscaling_memory_policy_enabled     = false
  external_autoscaling_policy_enabled   = true
  stopped_task_monitoring_enabled       = true
  fargate_spot_capacity_provider_weight = 100
  task_placement_failure_alert_enabled  = true
  fargate_service_subnets               = data.aws_subnets.private.ids

  # IAM policies used by the task role to pull configs from s3
  iam_managed_policy_attachments = [
    aws_iam_policy.kms_policy.arn,
    aws_iam_policy.s3_configs_read_only_policy.arn,
  ]

  environment_variables = [
    {
      Environment = var.environment
    },
    {
      PHP_ENTRYPOINT = "encode_tracks.php"
    },
    {
      ALLOWED_ENCODER_IDS = var.video_encoder_id
    },
    {
      ART_DB_IP = "qa.db.qaorch.com"
    },
    {
      ASPERA_MIN_RATE = "300"
    },
    {
      WGET_IP = "webservices.qaorch.com"
    },
    {
      API_GATEWAY = var.extended_ddex_api_gateway_url
    },
    {
      OWS_DELIVERY_METADATA = "qa-ows-delivery-metadata.theorchard.io"
    },
    {
      DB_IP = "qadddb.qaorch.com"
    },
    {
      ENCODING_PRIORITIES = each.value.encoding_priority
    },
    {
      LOCAL_SOURCE = "/var/app/source/"
    },
    {
      LOG_LEVEL = "7"
    },
    {
      OPERATING_SYSTEM = "LINUX_64"
    },
    {
      PHYSICAL_LOCATION_ID = each.value.physical_location
    },
    {
      PRIV_KEY = "/var/app/.ssh/id_dsa"
    },
    {
      PUB_KEY = "/var/app/.ssh/id_dsa.pub"
    },
    {
      REVERSE_DMS_PRIORITY = "0"
    },
    {
      S3_CONFIG_LOCATION = "${var.environment}-${var.config_s3_bucket_suffix}/${var.service_name}/${var.environment}/${var.video_encoder_id}/${each.value.physical_location}"
    },
    {
      SAVE = "/var/app/direct_delivery/"
    },
    {
      SCRIPT_COUNT = "5"
    },
    {
      SSH_KEY_DIR = "/var/app/.ssh/"
    },
    {
      STDOUT = "1"
    },
    {
      STORED_VIDEO_FORMATS = "mpg,3gp,stored_mov,mp4,wmv,ts,mxf,H264_SD,H264_HD"
    },
    {
      TARGET = "/var/app/encoding_tmp/"
    },
    {
      WEBSERVICE_URL = "webservice.qaorch.com"
    },
    {
      INCLUDED_DMS_LIST = var.physical_location_dms_include[each.value.physical_location]
    },
    {
      CURL_FORBID_REUSE = "true"
    },
  ]
  secrets = [
    {
      SENTRY_DSN = "${var.environment}/${var.service_name}/SENTRY_DSN"
    },
    {
      STORAGE_CREDENTIALS = "${var.environment}/${var.service_name}/${each.value.physical_location}/STORAGE_CREDENTIALS"
    }
  ]
}

# ows-request dynamo db policy
module "vector_encoder_service_owsrequest" {
  source = "git@github.com:theorchard/terraform-owsrequest.git//?ref=1.1.0"

  environment_name   = var.environment
  service_name       = var.service_name
  policy_description = "A policy to access dynamo owsrequest table"
}

# Audio Encoding Worker
module "qa_vector_encoder_audio_ecs_service" {
  for_each = {
    for service in local.flattened_audio_service_list : "physical_location_${service.physical_location}-encoding_priority_${service.encoding_priority}" => service
  }
  providers = {
    aws.dns = aws
  }
  source                                = "git@github.com:theorchard/terraform-fargate.git//?ref=5.6.1"
  environment                           = var.environment
  service_name                          = "${var.service_name}-audio-phys-loc-${each.value.physical_location}-p${each.value.encoding_priority}"
  non_ecr_image                         = "086679231553.dkr.ecr.${var.aws_region}.amazonaws.com/vector-worker:latest"
  vpc_id                                = data.aws_vpc.vpc.id
  application_family                    = var.application_family
  secrets_manager_service_name          = var.service_name
  aws_region                            = var.aws_region
  commit_sha                            = "latest"
  task_type                             = "worker"
  ecs_network_mode                      = "awsvpc"
  ecs_requires_compatibilities          = ["FARGATE"]
  ecs_launch_type                       = "FARGATE"
  ordered_placement_strategy_type       = "random"
  health_check_command                  = "php --version"
  desired_task_count                    = each.value.min_task_count # Set during service creation here and controlled henceforth by autoscaling
  task_cpu                              = 256
  task_memory                           = 1024
  minimum_capacity                      = each.value.min_task_count
  maximum_capacity                      = each.value.max_task_count
  task_protection_policy_enabled        = true
  splitio_enabled                       = false
  ows_machine_to_machine_enabled        = false
  autoscaling_cpu_policy_enabled        = false
  autoscaling_memory_policy_enabled     = false
  external_autoscaling_policy_enabled   = true
  stopped_task_monitoring_enabled       = true
  fargate_spot_capacity_provider_weight = 100
  task_placement_failure_alert_enabled  = true
  fargate_service_subnets               = data.aws_subnets.private.ids

  # IAM policies used by the task role to pull configs from s3
  iam_managed_policy_attachments = [
    aws_iam_policy.kms_policy.arn,
    aws_iam_policy.s3_configs_read_only_policy.arn,
  ]

  environment_variables = [
    {
      Environment = var.environment
    },
    {
      PHP_ENTRYPOINT = "encode_tracks.php"
    },
    {
      ALLOWED_ENCODER_IDS = var.audio_encoder_id
    },
    {
      ART_DB_IP = "qa.db.qaorch.com"
    },
    {
      WGET_IP = "webservices.qaorch.com"
    },
    {
      API_GATEWAY = var.extended_ddex_api_gateway_url
    },
    {
      aspera_delivery = "0"
    },
    {
      ASPERA_MIN_RATE = "45"
    },
    {
      DB_IP = "qadddb.qaorch.com"
    },
    {
      ENCODING_PRIORITIES = each.value.encoding_priority
    },
    {
      LOCAL_SOURCE = "/var/app/source/"
    },
    {
      LOG_LEVEL = "7"
    },
    {
      PHYSICAL_LOCATION_ID = each.value.physical_location
    },
    {
      PRIV_KEY = "/var/app/.ssh/id_dsa"
    },
    {
      PUB_KEY = "/var/app/.ssh/id_dsa.pub"
    },
    {
      REVERSE_DMS_PRIORITY = "0"
    },
    {
      S3_CONFIG_LOCATION = "${var.environment}-${var.config_s3_bucket_suffix}/${var.service_name}/${var.environment}/${var.audio_encoder_id}/${each.value.physical_location}"
    },
    {
      SAVE = "/var/app/direct_delivery/"
    },
    {
      SCRIPT_COUNT = "10"
    },
    {
      SSH_KEY_DIR = "/var/app/.ssh/"
    },
    {
      STORED_VIDEO_FORMATS = "mpg,3gp,stored_mov,mp4,wmv,ts,mxf,H264_SD,H264_HD"
    },
    {
      TARGET = "/var/app/encoding_tmp/"
    },
    {
      WEBSERVICE_URL = "webservice.qaorch.com"
    },
    {
      KNOWN_HOSTS = "/var/app/.ssh/known_hosts"
    },
    {
      ECHO_STEPS = "1"
    },
    {
      RSA_PUBKEY_DMS_LIST = "198,253,454"
    },
    {
      STORED_FORMATS = "vantrix,mp3_standard,wav40,wav_full,wav30,mp3_standard_clip,flac,mp3_high_standard,mp3_high_standard_clip"
    },
    {
      dd_db_port = "3306"
    },
    {
      no_video_encoding = "1"
    },
    {
      EXCLUDE_DMS_PRIORITY = "0" # this is not there in the new Configurator
    },
    {
      LARGE_FILESIZE = "2040109470"
    },
    {
      PRODUCT_STORE_MAPPING_URL = "https://qa-ows-product-store-mapping.theorchard.io"
    },
    {
      INCLUDED_DMS_LIST = var.physical_location_dms_include[each.value.physical_location]
    },
    {
      CURL_FORBID_REUSE = "true"
    },
  ]
  secrets = [
    {
      SENTRY_DSN = "${var.environment}/${var.service_name}/SENTRY_DSN"
    },
    {
      STORAGE_CREDENTIALS = "${var.environment}/${var.service_name}/${each.value.physical_location}/STORAGE_CREDENTIALS"
    }
  ]
}
