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

  default_tags {
    tags = module.default_tags.tags
  }
}

# For fargate tasks and ECS services that require networking access
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     = "qa/playwright-tests/terraform.tfstate"
    region  = "us-east-1"
    encrypt = "true"
  }
}

module "playwright_env_secret" {
  source = "git@github.com:theorchard/terraform-secrets-manager.git//?ref=1.5.1"

  environment                    = var.environment
  service_name                   = var.service_name
  secret_name                    = "playwright.env.json"
  application_family             = var.application_family
  secret_recovery_window_in_days = 7
  additional_tags = {
    secret_type = "integration-tests"
  }
}

data "aws_iam_policy_document" "secrets_manager_policy_document" {
  statement {
    effect = "Allow"

    actions = [
      "secretsmanager:GetResourcePolicy",
      "secretsmanager:GetSecretValue",
      "secretsmanager:DescribeSecret",
      "secretsmanager:ListSecretVersionIds",
    ]

    resources = [
      "arn:aws:secretsmanager:*:*:secret:${var.environment}/${var.service_name}/",
      "arn:aws:secretsmanager:*:*:secret:${var.environment}/${var.service_name}/*",
      "arn:aws:secretsmanager:*:*:secret:${var.environment}/${var.service_name}*",
      "arn:aws:secretsmanager:*:*:secret:${var.environment}/datadog/DD_API_KEY",
      "arn:aws:secretsmanager:*:*:secret:${var.environment}/datadog/DD_API_KEY*",
      "arn:aws:secretsmanager:*:*:secret:${var.environment}/e2e-test-secrets/*",
      "arn:aws:secretsmanager:*:*:secret:${var.environment}/auth0-secrets/*",
      "arn:aws:secretsmanager:*:*:secret:${var.environment}/cucumber-cypress-tests/SNOWFLAKE_KEY",
      "arn:aws:secretsmanager:*:*:secret:${var.environment}/cucumber-cypress-tests/SNOWFLAKE_KEY*",
      #       Prod secrets for prod users which are used in qa or prod playwright env
      "arn:aws:secretsmanager:*:*:secret:prod/e2e-test-secrets/*",
    ]
  }
}

# Assume role policy used by Jenkins pipeline agent role
data "aws_iam_policy_document" "jenkins_assume_role_policy" {
  statement {
    actions = ["sts:AssumeRole"]

    principals {
      type = "AWS"

      identifiers = [
        "arn:aws:iam::437795906767:role/prod-jenkins-aws-pipeline-agent",
        "arn:aws:iam::437795906767:user/aentwistle",
      ]
    }
  }
}

# SecretManager Access Policy
resource "aws_iam_policy" "secrets_manager_policy" {
  name   = "SecretManager-${var.environment}-${var.service_name}-access-policy"
  policy = data.aws_iam_policy_document.secrets_manager_policy_document.json
}

# Jenkins agents will assume this role in order to access SecretManager
resource "aws_iam_role" "jenkins_invoke_role" {
  name               = "${var.environment}-${var.service_name}-role"
  assume_role_policy = data.aws_iam_policy_document.jenkins_assume_role_policy.json
}

# Attach SecretManager access policy to Jenkins role.
resource "aws_iam_role_policy_attachment" "playwright_secrets_manager_role_policy_attachment" {
  role       = aws_iam_role.jenkins_invoke_role.id
  policy_arn = aws_iam_policy.secrets_manager_policy.arn
}

# Policy document to allow Jenkins to access S3 buckets for test results
data "aws_iam_policy_document" "jenkins_s3_role_policy_document" {
  statement {
    effect = "Allow"

    actions = [
      "s3:GetObject",
      "s3:ListBucket",
      "s3:ListObjectsV2",
      "s3:PutObject",
      "s3:DeleteObject",
    ]

    resources = [
      "arn:aws:s3:::${var.environment}-playwright-test-results",
      "arn:aws:s3:::${var.environment}-playwright-test-results/*",
    ]
  }
}

# Policy to allow Jenkins to access S3 buckets for test results
resource "aws_iam_policy" "jenkins_s3_role_policy" {
  name   = "${var.environment}-${var.service_name}-s3-role-policy"
  policy = data.aws_iam_policy_document.jenkins_s3_role_policy_document.json

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

# Attach the S3 access policy to the Jenkins role
resource "aws_iam_role_policy_attachment" "jenkins_s3_role_policy_attachment" {
  role       = aws_iam_role.jenkins_invoke_role.name
  policy_arn = aws_iam_policy.jenkins_s3_role_policy.arn
}

data "aws_caller_identity" "current" {}

# Policy document to allow Jenkins to trigger Fargate tasks
data "aws_iam_policy_document" "jenkins_fargate_run_task_policy_document" {
  statement {
    effect = "Allow"
    actions = [
      "ecs:RunTask",
      "ecs:StartTask",
    ]
    resources = [
      "arn:aws:ecs:*:${data.aws_caller_identity.current.account_id}:cluster/${var.environment}-${var.service_name}",
      "arn:aws:ecs:*:${data.aws_caller_identity.current.account_id}:task-definition/${var.environment}-${var.service_name}:*"
    ]
  }

  statement {
    actions = [
      "ec2:DescribeSecurityGroups",
      "ecs:DescribeClusters",
      "ecs:DescribeTasks",
      "ecs:DescribeTaskDefinition",
      "ecs:ListTasks",
      "ecs:ListTaskDefinitions",
    ]
    effect = "Allow"
    resources = [
      "*",
    ]
  }

  statement {
    actions = [
      "iam:PassRole",
    ]
    effect = "Allow"
    resources = [
      "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/${var.environment}-${var.service_name}-role",
      "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/${var.environment}-${var.service_name}-task-execution-role*",
      "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/${var.environment}-${var.service_name}-task-role"
    ]
  }
}

# Policy to allow Jenkins to trigger Fargate tasks
resource "aws_iam_policy" "jenkins_fargate_run_task_policy" {
  name   = "${var.environment}-${var.service_name}-fargate-run-task-policy"
  policy = data.aws_iam_policy_document.jenkins_fargate_run_task_policy_document.json

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

# Attach the Fargate run task policy to the Jenkins role

resource "aws_iam_role_policy_attachment" "jenkins_fargate_run_task_policy_attachment" {
  role       = aws_iam_role.jenkins_invoke_role.name
  policy_arn = aws_iam_policy.jenkins_fargate_run_task_policy.arn
}

data "aws_iam_policy_document" "jenkins_lambda_invoke_policy_document" {
  statement {
    effect = "Allow"
    actions = [
      "lambda:InvokeFunction",
    ]
    resources = [
      "arn:aws:lambda:${var.aws_region}:${data.aws_caller_identity.current.account_id}:function:${var.environment}-${var.service_name}",
      #       wildcard allows specific lambda versions to be invoked
      "arn:aws:lambda:${var.aws_region}:${data.aws_caller_identity.current.account_id}:function:${var.environment}-${var.service_name}:*"
    ]
  }
}

resource "aws_iam_policy" "jenkins_lambda_invoke_policy" {
  name   = "${var.environment}-${var.service_name}-jenkins-lambda-invoke-policy"
  policy = data.aws_iam_policy_document.jenkins_lambda_invoke_policy_document.json

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

resource "aws_iam_role_policy_attachment" "jenkins_lambda_invoke_policy_attachment" {
  role       = aws_iam_role.jenkins_invoke_role.name
  policy_arn = aws_iam_policy.jenkins_lambda_invoke_policy.arn
}

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

  environment = var.environment
}

data "aws_iam_policy_document" "playwright_dynamoDb_policy_document" {
  statement {
    effect = "Allow"

    actions = [
      "dynamodb:Query",
      "dynamodb:Scan",
      "dynamodb:DeleteItem",
    ]

    resources = [
      "arn:aws:dynamodb:us-east-1:437795906767:table/qa_statement_attachments_success",
      "arn:aws:dynamodb:us-east-1:437795906767:table/qa-accounting-statement-export",
      "arn:aws:dynamodb:us-east-1:437795906767:table/qa_statement_attachments_error",
      "arn:aws:dynamodb:us-east-1:437795906767:table/ows-accounting-owsrequest"
    ]
  }
}


resource "aws_iam_policy" "playwright_dynamoDb_policy" {
  name   = "${var.environment}-${var.service_name}-dynamodb-policy"
  policy = data.aws_iam_policy_document.playwright_dynamoDb_policy_document.json

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

data "aws_iam_policy_document" "playwright_s3_worker_read_write_policy_document" {
  statement {
    effect = "Allow"
    actions = [
      "s3:GetBucketLocation",
      "s3:GetObject*",
      "s3:ListBucket",
      "s3:PutObject*",
    ]
    resources = [
      "arn:aws:s3:::${var.environment}-neighbouring-rights",
      "arn:aws:s3:::${var.environment}-neighbouring-rights/*",
      "arn:aws:s3:::${var.environment}-encoding-direct-delivery-physical-location-9",
      "arn:aws:s3:::${var.environment}-encoding-direct-delivery-physical-location-9/*",
      "arn:aws:s3:::${var.environment}-orcdbucket",
      "arn:aws:s3:::${var.environment}-orcdbucket/qa-statement-attachments",
      "arn:aws:s3:::${var.environment}-orcdbucket/qa-statement-attachments/*",
      "arn:aws:s3:::${var.environment}-statement-detail-exports",
      "arn:aws:s3:::${var.environment}-statement-detail-exports/*",
      "arn:aws:s3:::${var.environment}-orcdbucket/qa-per-label-statement-attachments",
      "arn:aws:s3:::${var.environment}-orcdbucket/qa-per-label-statement-attachments/*",
      "arn:aws:s3:::prod-orcd-ftp",
      "arn:aws:s3:::prod-orcd-ftp/ftp/qa_vector_test/*",
      "arn:aws:s3:::qa-orcd-raw-assets",
      "arn:aws:s3:::qa-orcd-raw-assets/*",
      "arn:aws:s3:::${var.environment}-playwright-test-results",
      "arn:aws:s3:::${var.environment}-playwright-test-results/*",
    ]
  }

  statement {
    effect = "Allow"
    actions = [
      "s3:DeleteObject",
      "s3:DeleteObject*"
    ]
    resources = [
      "arn:aws:s3:::${var.environment}-neighbouring-rights/contributions/*",
      "arn:aws:s3:::${var.environment}-encoding-direct-delivery-physical-location-9/*",
      "arn:aws:s3:::${var.environment}-orcdbucket/qa-statement-attachments/*",
    ]
  }
}

resource "aws_iam_policy" "s3_playwright_read_write_policy" {
  name   = "S3-${var.environment}-${var.service_name}-read-write-policy"
  policy = data.aws_iam_policy_document.playwright_s3_worker_read_write_policy_document.json

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

module "playwright_tests_fargate_environment" {
  source = "git@github.com:theorchard/terraform-fargate.git//?ref=6.4.1"

  providers = {
    aws.dns = aws.networking
  }

  environment        = var.environment
  service_name       = var.service_name
  aws_region         = var.aws_region
  commit_sha         = "latest"
  container_port     = 9000
  task_type          = "worker"
  desired_task_count = 0
  task_cpu           = 2048
  task_memory        = 4096
  maximum_capacity   = 200
  minimum_capacity   = 0
  vpc_id             = module.vpc_info.vpc_id
  application_family = var.application_family

  iam_managed_policy_attachments = [
    aws_iam_policy.playwright_dynamoDb_policy.arn,
    aws_iam_policy.secrets_manager_policy.arn,
    aws_iam_policy.s3_playwright_read_write_policy.arn,
  ]

  fargate_service_subnets = module.vpc_info.default_private_subnet_ids

  environment_variables = [
    {
      Environment = var.environment
    },
    {
      LOGGER_DSN = "https://${var.environment}-fluentd-applications.theorchard.io:8888/application"
    },
  ]
}

module "s3_bucket" {
  source              = "git@github.com:theorchard/terraform-s3.git//modules/s3_bucket?ref=3.15.3"
  application_family  = var.application_family
  env                 = var.environment
  bucket_name         = var.bucket_name
  s3_read_only_policy = false

  apply_server_side_encryption_by_default = {
    sse_algorithm = "AES256"
  }
  lifecycle_rules_options_noncurrent_version_expiration = [
    {
      prefix  = ""
      enabled = true
      days    = 7
    }
  ]

  lifecycle_rules_options_current_version_expiration = [
    {
      prefix  = ""
      enabled = true
      days    = 14
    }
  ]
}

module "m2m_secrets" {
  source = "git@github.com:theorchard/terraform-secrets-manager.git//modules/auth0m2m?ref=1.6.1"

  for_each           = toset(var.function_names)
  environment        = var.environment
  service_name       = "${var.service_name}-${each.value}"
  application_family = var.application_family

  additional_tags = {
    secret_type = "integration-tests"
  }
}
