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          = "devops"
}

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
  }
}

data "aws_caller_identity" "current" {}

# Terraform backends cannot contain interpolations
terraform {
  backend "s3" {
    bucket  = "dev-orcd-terraform-state"
    key     = "dev/neo4j-5/terraform.tfstate"
    region  = "us-east-1"
    encrypt = "true"
  }
}

data "aws_vpc" "vpc" {
  id = var.vpc_id
}

data "aws_subnets" "private" {
  filter {
    name   = "vpc-id"
    values = [data.aws_vpc.vpc.id]
  }

  tags = {
    tier = "private"
  }
}

data "aws_instances" "neo4j_cluster" {
  instance_tags = {
    Name = "${var.environment}-${var.service_name}-debian"
  }
}

data "aws_instance" "neo4j" {
  for_each    = toset(data.aws_instances.neo4j_cluster.ids)
  instance_id = each.key
}

data "aws_route53_zone" "dev_orchard" {
  zone_id = var.route53_zone_id
}

data "aws_ec2_managed_prefix_list" "shared_account_prefix_list" {
  name = "shared-orcd-private-subnet-prefix-list"
}

data "aws_ec2_managed_prefix_list" "vpn_sme_internal_primary" {
  name = "vpn-sme-internal-primary"
}

module "neo4j_debian_environment" {
  source = "git@github.com:theorchard/terraform-neo4j-cluster.git//debian?ref=1.1.0"

  environment             = var.environment
  service_name            = "${var.service_name}-debian"
  vpc_id                  = data.aws_vpc.vpc.id
  vpc_private_subnet_ids  = data.aws_subnets.private.ids
  data_volume_device_name = "/dev/sdb"
  data_volume_device_type = "gp3"
  data_volume_iops        = 4000
  data_volume_size        = 3500
  data_volume_throughput  = 300
  # it can't go any faster than that due to instance type limitations
  ssh_keypair_name                  = "dev_orchard_admin"
  route53_zone_id                   = "Z21XEY26C989RH"
  dbms_backup_s3_bucket             = "dev-orchdbucket"
  data_volume_delete_on_termination = true
  aws_instance_type                 = "r5.xlarge"
  user_data                         = module.chef_bootstrap_neo4j_debian.user_data_output

  desired_capacity = 0
  min_size         = 0
  max_size         = 0

  bolt_ingress_cidr_blocks = [
    "192.168.31.0/24",
    "192.168.32.0/24",
    "192.168.33.0/24",
    "192.168.40.0/22",
  ]
}

resource "aws_security_group_rule" "allow_shared_jenkins_nodes_ssh" {
  type      = "ingress"
  from_port = 22
  to_port   = 22
  protocol  = "TCP"
  prefix_list_ids = [
    data.aws_ec2_managed_prefix_list.shared_account_prefix_list.id,
    data.aws_ec2_managed_prefix_list.vpn_sme_internal_primary.id
  ]
  security_group_id = module.neo4j_debian_environment.instance_security_group_id_output
}

resource "aws_security_group_rule" "allow_shared_jenkins_nodes_neo4j" {
  type      = "ingress"
  from_port = 7687
  to_port   = 7687
  protocol  = "TCP"
  prefix_list_ids = [
    data.aws_ec2_managed_prefix_list.shared_account_prefix_list.id,
    data.aws_ec2_managed_prefix_list.vpn_sme_internal_primary.id
  ]
  security_group_id = module.neo4j_debian_environment.instance_security_group_id_output
}

module "chef_bootstrap_neo4j_debian" {
  source = "git@github.com:theorchard/terraform-chef-bootstrap.git//?ref=3.3.0"

  chef_role         = "dev_neo4j_5_debian_cluster"
  chef_environment  = var.environment
  aws_iam_role_id   = module.neo4j_debian_environment.instance_iam_role_name_output
  aws_instance_name = "${var.environment}-${var.service_name}"
}

data "aws_iam_policy_document" "neo4j_dev_refresh" {
  statement {
    effect = "Allow"
    actions = [
      "s3:GetObject",
    ]
    resources = [
      "arn:aws:s3:::prod-orcdbucket/backup/neo4j/*",
    ]
  }

  statement {
    effect = "Allow"
    actions = [
      "s3:ListBucket",
    ]
    resources = [
      "arn:aws:s3:::prod-orcdbucket",
    ]

    condition {
      test     = "StringLike"
      variable = "s3:prefix"
      values = [
        "backup/neo4j/*",
      ]
    }
  }

  statement {
    effect = "Allow"
    actions = [
      "kms:Decrypt",
      "kms:DescribeKey",
    ]
    resources = [
      "arn:aws:kms:us-east-1:437795906767:key/839dc350-52d3-4bd0-b37f-da708ba77aca",
    ]
  }
}

resource "aws_iam_policy" "neo4j_dev_refresh_policy" {
  name   = "${var.environment}-${var.service_name}-direct-access-prod-backup-policy"
  policy = data.aws_iam_policy_document.neo4j_dev_refresh.json
}

resource "aws_iam_role_policy_attachment" "neo4j_dev_refresh_policy_attachment" {
  role       = module.neo4j_debian_environment.instance_iam_role_name_output
  policy_arn = aws_iam_policy.neo4j_dev_refresh_policy.arn
}

# resource "aws_route53_record" "dev_route53_record" {
#   # This is here to cover the canonical cluster url pre 4.x upgrade
#   name    = "dev-neo4j-cluster"
#   zone_id = var.route53_zone_id
#   type    = "A"
#   ttl     = var.route53_record_ttl
#   records = [
#     "10.101.2.199",
#     "10.101.5.126",
#     "10.101.6.179",
#   ]

#   # Allow DNS record updates via lifecycle hooks without Terraform trying to change things.
#   lifecycle {
#     ignore_changes = [
#       records
#     ]
#   }
# }

resource "aws_route53_record" "non_production_route53_record" {
  # This is here to cover the canonical cluster url pre 4.x upgrade
  name    = "dev-neo4j-5-cluster"
  zone_id = var.route53_zone_id
  type    = "A"
  ttl     = var.route53_record_ttl
  records = [
    "10.101.2.199",
    "10.101.5.126",
    "10.101.6.179",
  ]

  # Allow DNS record updates via lifecycle hooks without Terraform trying to change things.
  lifecycle {
    ignore_changes = [
      records
    ]
  }
}

resource "aws_route53_record" "cluster_discovery" {
  name    = "dev-neo4j-5-cluster-discovery"
  zone_id = var.route53_zone_id
  type    = "A"
  ttl     = var.route53_record_ttl
  records = [
    "10.101.3.74",
    "10.101.5.51",
    "10.101.7.147",
  ]

  # Allow DNS record updates via lifecycle hooks without Terraform trying to change things.
  lifecycle {
    ignore_changes = [
      records
    ]
  }
}

# Allow Dev cluster to read Prod S3 backup location to pull backups
data "aws_iam_policy_document" "access_prod_backup" {
  statement {
    actions = [
      "sts:AssumeRole",
    ]

    resources = [
      "arn:aws:iam::437795906767:role/dev-neo4j-cluster-access-prod-neo4j-cluster-backups-role",
    ]
  }
}

resource "aws_iam_policy" "access_prod_backup_policy" {
  name   = "${var.environment}-${var.service_name}-access-prod-backup-policy"
  policy = data.aws_iam_policy_document.access_prod_backup.json
}

resource "aws_iam_role_policy_attachment" "access_prod_backup_policy_attachment_deb" {
  role       = module.neo4j_debian_environment.instance_iam_role_name_output
  policy_arn = aws_iam_policy.access_prod_backup_policy.arn
}

resource "aws_iam_role_policy_attachment" "dev_restore_policy_attachment_deb" {
  role       = module.neo4j_debian_environment.instance_iam_role_name_output
  policy_arn = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:policy/SecretsManager-${var.environment}-neo4j-cluster-restore-policy"
}

# Datadog monitors and dashboards
module "datadog_neo4j_dashboards_and_monitors" {
  source                     = "git@github.com:theorchard/terraform-datadog.git//modules/neo4j?ref=6.16.1"
  environment                = var.environment
  service_name               = var.service_name
  neo4j_major_version_number = 5
  neo4j_monitors_enabled     = false
}

module "neo4j_user" {
  source   = "git@github.com:theorchard/terraform-secrets-manager.git//?ref=1.5.1"
  for_each = toset(var.neo4j_user_secrets_manager)

  environment        = var.environment
  service_name       = var.service_name
  secret_name        = each.value
  application_family = var.application_family
}
