data "aws_s3_bucket" "backup" {
  bucket = var.backup_bucket
}

data "aws_kms_key" "backup" {
  key_id = var.backup_kms_key_id
}

resource "aws_iam_policy" "backup_upload" {
  name   = "${var.environment}-${var.backup_service_name}-backup-upload-access-policy"
  policy = data.aws_iam_policy_document.s3_backup_read_write_policy.json
}

data "aws_ecr_repository" "neo4j_cluster_backup" {
  name        = "neo4j-cluster-backup"
  registry_id = module.aws_accounts.all_accounts["shared"]
}

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

module "ecr_policy" {
  source = "git@github.com:theorchard/terraform-iam-policy-templates.git//documents/ecr/repository?ref=0.4.0"

  repositories = [data.aws_ecr_repository.neo4j_cluster_backup.arn]
  action_types = ["read"]
}

resource "aws_iam_policy" "ecr" {
  name   = "${var.environment}-${var.backup_service_name}-ecr-access-policy"
  policy = module.ecr_policy.policy.json
}

data "aws_iam_policy_document" "s3_backup_read_write_policy" {
  statement {
    actions = [
      "s3:GetObject",
      "s3:PutObject",
      "s3:PutObject*",
      "s3:DeleteObject",
    ]

    resources = [
      "${data.aws_s3_bucket.backup.arn}/backup/neo4j/*"
    ]
  }

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

    resources = [data.aws_s3_bucket.backup.arn]
  }

  statement {
    actions = [
      "s3:ListAllMyBuckets"
    ]

    resources = [
      "*"
    ]
  }

  statement {
    actions = [
      "s3:ListBucket"
    ]

    resources = [data.aws_s3_bucket.backup.arn]

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

  statement {
    actions = [
      "kms:ReEncrypt*",
      "kms:GenerateDataKey*",
      "kms:Encrypt",
      "kms:DescribeKey",
      "kms:Decrypt"
    ]

    resources = [data.aws_kms_key.backup.arn]
  }
}


module "secrets" {
  source   = "git@github.com:theorchard/terraform-secrets-manager.git//?ref=1.6.1"
  for_each = var.backup_service_secret_names

  application_family = "data-platform"
  environment        = var.environment
  secret_name        = each.value
  service_name       = var.backup_service_name
}

data "aws_availability_zones" "azs" {
  exclude_zone_ids = ["use1-az3"]
}

data "aws_subnets" "backups_private_subnets" {
  filter {
    name   = "vpc-id"
    values = [module.vpc_info.vpc_id]
  }
  filter {
    name   = "tag:Name"
    values = ["*_private_subnet_*"]
  }

  filter {
    name   = "availability-zone-id"
    values = data.aws_availability_zones.azs.zone_ids
  }
}

locals {
  aws_account_id = data.aws_caller_identity.current.account_id
}

resource "aws_iam_policy" "secrets" {
  policy = data.aws_iam_policy_document.secrets.json
  name   = "${var.environment}-${var.backup_service_name}-secrets"
}

data "aws_iam_policy_document" "secrets" {
  statement {
    actions = [
      "secretsmanager:ListSecretVersionIds",
      "secretsmanager:GetSecretValue",
      "secretsmanager:GetResourcePolicy",
      "secretsmanager:DescribeSecret"
    ]
    resources = [
      "arn:aws:secretsmanager:*:*:secret:prod/neo4j-cluster-backup-fargate/*",
      "arn:aws:secretsmanager:*:*:secret:prod/neo4j-cluster-backup-fargate/",
      "arn:aws:secretsmanager:*:*:secret:qa/neo4j-cluster-restore/*",
      "arn:aws:secretsmanager:*:*:secret:qa/neo4j-cluster-restore/",
      "arn:aws:secretsmanager:*:*:secret:prod/datadog/DD_API_KEY*",
      "arn:aws:secretsmanager:*:*:secret:prod/datadog/DD_APP_KEY*",
    ]
  }
}

data "aws_lambda_function" "datadog_lambda_function" {
  function_name = "DatadogLambdaFunction"
}


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

  chef_role         = "prod_neo4j_backup"
  chef_environment  = var.environment
  aws_iam_role_id   = aws_iam_role.backup.id
  aws_instance_name = "${var.environment}-${var.backup_host_service_name}"
}

data "aws_ami" "debian_13" {
  most_recent = true

  owners = [
    "086679231553",
  ]

  filter {
    name = "virtualization-type"

    values = [
      "hvm",
    ]
  }

  filter {
    name   = "name"
    values = ["debian-13-amd64-*"]
  }

  filter {
    name   = "architecture"
    values = ["x86_64"]
  }
}

resource "aws_launch_template" "backup" {
  description             = "${var.environment}-${var.backup_host_service_name}"
  disable_api_stop        = false
  disable_api_termination = true
  ebs_optimized           = true
  image_id                = data.aws_ami.debian_13.id
  instance_type           = "i7ie.3xlarge"
  key_name                = "orchard_admin"
  name                    = "${var.environment}-${var.backup_host_service_name}"
  user_data               = base64encode(module.chef_bootstrap_neo4j_backup.user_data_output)
  update_default_version  = true
  vpc_security_group_ids  = [aws_security_group.backup.id]

  block_device_mappings {
    device_name = data.aws_ami.debian_13.root_device_name

    ebs {
      volume_type           = "gp3"
      volume_size           = 50
      encrypted             = true
      delete_on_termination = true
    }
  }

  metadata_options {
    http_endpoint = "enabled"
    http_tokens   = "required"
  }

  iam_instance_profile {
    name = aws_iam_instance_profile.backup.name
  }

  monitoring {
    enabled = true
  }

  tag_specifications {
    resource_type = "volume"
    tags = merge(module.default_tags.tags, {
      Name = "${var.environment}-${var.backup_host_service_name}"
    })
  }

  tags = {
    Name = "${var.environment}-${var.backup_host_service_name}"
  }

  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_autoscaling_group" "backup" {
  name                      = "${var.environment}-${var.backup_host_service_name}"
  min_size                  = 0
  max_size                  = 1
  desired_capacity          = 1
  default_cooldown          = 300
  health_check_type         = "EC2"
  health_check_grace_period = 300
  wait_for_capacity_timeout = "10m"
  vpc_zone_identifier       = module.vpc_info.default_private_subnet_ids
  launch_template {
    id      = aws_launch_template.backup.id
    version = "$Latest"
  }

  dynamic "tag" {
    for_each = merge(module.default_tags.tags, {
      Name = "${var.environment}-${var.backup_host_service_name}"
    })
    content {
      key                 = tag.key
      value               = tag.value
      propagate_at_launch = true
    }
  }

  lifecycle {
    create_before_destroy = true
    ignore_changes        = [desired_capacity]
  }
}


resource "aws_security_group" "backup" {
  name        = "${var.environment}-${var.backup_host_service_name}-security-group"
  description = "${var.environment}-${var.backup_host_service_name}-security-group"
  vpc_id      = module.vpc_info.vpc_id

  tags = {
    eiso-exception = "aws.08.30"
  }
}

resource "aws_security_group_rule" "ssh" {
  type              = "ingress"
  from_port         = 22
  to_port           = 22
  protocol          = "TCP"
  security_group_id = aws_security_group.backup.id
  cidr_blocks       = var.ssh_ingress_cidr_blocks
}

resource "aws_security_group_rule" "ssh_prefix_list" {
  type              = "ingress"
  from_port         = 22
  to_port           = 22
  protocol          = "TCP"
  security_group_id = aws_security_group.backup.id
  prefix_list_ids   = [data.aws_ec2_managed_prefix_list.vpn_sme_internal_primary.id]
}

resource "aws_security_group_rule" "allow_instance_egress" {
  type              = "egress"
  from_port         = 0
  to_port           = 0
  protocol          = "-1"
  cidr_blocks       = ["0.0.0.0/0"]
  security_group_id = aws_security_group.backup.id
}

resource "aws_iam_role" "backup" {
  name               = "${var.environment}-${var.backup_host_service_name}-asg-role"
  assume_role_policy = data.aws_iam_policy_document.assume_instance_role.json
}

resource "aws_iam_instance_profile" "backup" {
  name = "${var.environment}-${var.backup_host_service_name}-asg-instance-profile"
  role = aws_iam_role.backup.name
}

resource "aws_iam_role_policy_attachment" "backup_upload" {
  policy_arn = aws_iam_policy.backup_upload.arn
  role       = aws_iam_role.backup.name
}

resource "aws_iam_role_policy_attachment" "backup_secrets" {
  policy_arn = aws_iam_policy.secrets.arn
  role       = aws_iam_role.backup.name
}

resource "aws_iam_role_policy_attachment" "backup_ecr" {
  policy_arn = aws_iam_policy.ecr.arn
  role       = aws_iam_role.backup.name
}

data "aws_iam_policy_document" "assume_instance_role" {
  statement {
    actions = [
      "sts:AssumeRole",
    ]

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

data "aws_iam_policy_document" "autoscaling_policy" {
  statement {
    effect = "Allow"
    actions = [
      "autoscaling:SetDesiredCapacity",
    ]
    resources = [
      aws_autoscaling_group.backup.arn
    ]
  }
}

resource "aws_iam_role_policy" "autoscaling_policy" {
  name   = "${var.environment}-${var.backup_host_service_name}-asg-policy"
  role   = aws_iam_role.backup.name
  policy = data.aws_iam_policy_document.autoscaling_policy.json
}

resource "aws_autoscaling_schedule" "start_neo4j_backup_instance" {
  scheduled_action_name  = "start-neo4j-backup-instance"
  autoscaling_group_name = aws_autoscaling_group.backup.name

  recurrence       = "0 4 * * *"
  min_size         = 0
  desired_capacity = 1
  max_size         = 1
}
