module "default_tags" {
  source             = "git@github.com:theorchard/terraform-default-tags.git//?ref=2.0.0"
  environment        = var.environment
  application_family = var.application_family
  service_name       = var.service_name
  team_name          = var.team_name
}

provider "aws" {
  region = var.aws_region

  default_tags {
    tags = module.default_tags.tags
  }
}

provider "aws" {
  region  = var.aws_region
  alias   = "networking"
  profile = "networking"

  default_tags {
    tags = module.default_tags.tags
  }
}

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

data "aws_caller_identity" "current" {}

module "vpc_info" {
  source = "git@github.com:theorchard/terraform-vpc-info.git//?ref=3.1.0"

  environment = var.environment
}

data "aws_route53_zone" "route53_zone" {
  name         = "theorchard.io."
  private_zone = false
}

# Policy for read-only access to the S3 bucket
data "aws_iam_policy" "s3_configs_read_only_policy" {
  name = "S3-${var.environment}-${var.config_service_name}-RO"
}

# Policy for KMS access to encrypted config objects in the S3 bucket
data "aws_iam_policy" "orchard_repo_cron_worker_kms_policy" {
  name = "KMS-${var.environment}-${var.config_service_name}-policy"
}

# Create KMS key and policies for EFS volume backups
resource "aws_kms_key" "efs_kms_key" {
  description             = "${var.environment}-${var.service_name}-efs"
  enable_key_rotation     = true
  deletion_window_in_days = 30

  tags = {
    environment        = var.environment
    service_name       = var.service_name
    application_family = var.application_family
    terraformed        = true
  }
}

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

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

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

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

# Create efs file system for shared mounts
module "efs_volume" {
  source = "git@github.com:theorchard/terraform-efs.git//?ref=4.1.0"

  providers = {
    aws.dns = aws.networking
  }

  environment        = var.environment
  service_name       = var.service_name
  application_family = var.application_family
  vpc_id             = module.vpc_info.vpc_id
  subnet_ids         = module.vpc_info.default_private_subnet_ids
  # UID of worker user created by parent image: https://github.com/theorchard/docker-parent-images/blob/master/centos7/Dockerfile#L3
  owner_gid                = "1010"
  owner_uid                = "1010"
  access_point_permissions = "700"
}

data "aws_iam_policy_document" "assume_role_policy_document" {
  statement {
    effect  = "Allow"
    actions = ["sts:AssumeRole"]

    principals {
      type        = "Service"
      identifiers = ["backup.amazonaws.com"]
    }
  }
}

# This rule will allow the fargate security group to acess the EFS filesystem
resource "aws_security_group_rule" "allow_efs_sg_inbound" {
  for_each = local.service_name_to_queue_map

  from_port                = 2049
  to_port                  = 2049
  protocol                 = "tcp"
  security_group_id        = module.efs_volume.efs_security_group_id_output
  source_security_group_id = module.hfa_fargate_environment[each.key].fargate_security_group_id
  type                     = "ingress"
}

data "aws_elasticache_replication_group" "split_synchronizer_redis_cache" {
  replication_group_id = "${var.environment}-split-synchronizer"
}

module "hfa_fargate_environment" {
  for_each = local.service_name_to_queue_map
  source   = "git@github.com:theorchard/terraform-fargate.git//?ref=6.5.0"

  providers = {
    aws.dns = aws.networking
  }

  environment                        = var.environment
  service_name                       = each.value["service_name"]
  aws_region                         = var.aws_region
  application_family                 = var.application_family
  non_ecr_image                      = "${data.aws_caller_identity.current.account_id}.dkr.ecr.${var.aws_region}.amazonaws.com/${var.config_service_name}:latest"
  task_type                          = "worker"
  health_check_command               = "pgrep php"
  deployment_minimum_healthy_percent = "100"
  autoscaling_cpu_policy_enabled     = false
  autoscaling_memory_policy_enabled  = false
  desired_task_count                 = 0
  minimum_capacity                   = 0
  maximum_capacity                   = 1
  task_cpu                           = 2048
  task_memory                        = 4096
  container_port                     = 8080
  health_check_grace_period_seconds  = 300
  container_start_period_seconds     = 300
  target_deregistration_delay        = 300
  cloudwatch_event_enabled           = each.value["schedule_enabled"]
  cloudwatch_event_schedule          = each.value["schedule"]
  vpc_id                             = module.vpc_info.vpc_id
  fargate_service_subnets            = module.vpc_info.default_private_subnet_ids
  task_protection_policy_enabled     = true
  iam_managed_policy_attachments = [
    data.aws_iam_policy.orchard_repo_cron_worker_kms_policy.arn,
    data.aws_iam_policy.s3_configs_read_only_policy.arn,
    module.efs_volume.efs_iam_policy_arn_output,
  ]

  docker_volumes = [
    {
      name            = "${var.environment}-${each.value["service_name"]}"
      file_system_id  = module.efs_volume.efs_file_system_id_output
      access_point_id = module.efs_volume.efs_access_point_id_output
    }
  ]

  docker_volume_mount_points = [
    {
      source_volume  = "${var.environment}-${each.value["service_name"]}"
      container_path = var.efs_volume_container_path
    }
  ]

  environment_variables = [
    {
      Environment = var.environment
    },
    {
      APPLICATION_ENV = "production"
    },
    {
      DD_TRACE_ANALYTICS_ENABLED = "true"
    },
    {
      DD_TRACE_APP_NAME = each.value["service_name"]
    },
    {
      DD_TRACE_GLOBAL_TAGS = "env:${var.environment}"
    },
    {
      PATH_FROM_REPO_ROOT_OF_PHP_SCRIPT_TO_RUN = each.value["script_to_run"]
    },
    {
      PHP_DISPLAY_ERRORS = "false"
    },
    {
      PHP_MEMORY_LIMIT = "1536M"
    },
    {
      SCRIPT_ARGUMENTS = each.value["script_arguments"]
    },
    {
      S3_CONFIG_LOCATION = "${var.config_s3_bucket}/${var.config_service_name}/${var.environment}"
    },
    {
      LC_ALL = "en_US.UTF-8"
    },
    {
      LANG = "en_US.UTF-8"
    },
    {
      LANGUAGE = "en_US.UTF-8"
    },
    {
      SENTRY_DSN = "https://c0e8157de78d448ca46774ca98f7c094@o22178.ingest.us.sentry.io/67618"
    },
    {
      SPLITIO_REDIS_HOST = data.aws_elasticache_replication_group.split_synchronizer_redis_cache.primary_endpoint_address
    },
    {
      SPLITIO_REDIS_PORT = data.aws_elasticache_replication_group.split_synchronizer_redis_cache.port
    },
  ]
  secrets = [
    {
      SPLITIO_API_KEY = "${var.environment}/split/API_KEY"
    },
  ]
}

module "hfa-cron-cache" {
  source = "git@github.com:theorchard/terraform-elasticache.git//?ref=3.1.1"

  providers = {
    aws.dns = aws.networking
  }

  environment                      = var.environment
  service_name                     = var.service_name
  cache_engine                     = "memcached"
  memcached_engine_version         = "1.6.6"
  cache_subnet_group_name          = "${var.environment}-elasticache-subnet-group"
  cache_node_count                 = 1
  cache_node_type                  = "cache.t4g.micro"
  cache_parameter_group_name       = "default.memcached1.6"
  application_family               = var.application_family
  route53_zone_id                  = data.aws_route53_zone.route53_zone.zone_id
  vpc_id                           = module.vpc_info.vpc_id
  cache_transit_encryption_enabled = false
}
