resource "aws_backup_vault" "vault" {
  name        = "${var.environment}-${var.service_name}-${var.location}-${var.tier}-backup-vault"
  kms_key_arn = aws_kms_key.backup_kms_key.arn

  tags = {
    Name         = "${var.environment}-${var.service_name}-${var.location}-${var.tier}-backup-vault"
    environment  = var.environment
    location     = var.location
    service_name = var.service_name
    tier         = var.tier
    terraformed  = "true"
  }
}

resource "aws_kms_key" "backup_kms_key" {
  description             = "${var.environment}-${var.service_name}-${var.location}-${var.tier}-backup-key"
  enable_key_rotation     = true
  deletion_window_in_days = 30

  tags = {
    Name         = "${var.environment}-${var.service_name}-${var.location}-${var.tier}-backup-key"
    environment  = var.environment
    location     = var.location
    service_name = var.service_name
    tier         = var.tier
    terraformed  = "true"
  }
}

resource "aws_kms_alias" "backup_kms_alias" {
  name          = "alias/${var.environment}-${var.service_name}-${var.location}-${var.tier}-backup-key"
  target_key_id = aws_kms_key.backup_kms_key.key_id
}

resource "aws_backup_plan" "plan" {
  name = "${var.environment}-${var.service_name}-${var.location}-${var.tier}-backup-plan"

  rule {
    rule_name                = "backup_rule"
    target_vault_name        = aws_backup_vault.vault.name
    schedule                 = var.backup_schedule
    start_window             = var.backup_start_window_minutes
    completion_window        = var.backup_completion_window_minutes

    recovery_point_tags = {
      environment  = var.environment
      location     = var.location
      service_name = var.service_name
      tier         = var.tier
      terraformed  = "true"
    }

    lifecycle {
      cold_storage_after = var.backup_cold_storage_after_days
      delete_after       = var.backup_delete_after_days == null ? var.backup_delete_after_days : null
    }
  }

  tags = {
    Name         = "${var.environment}-${var.service_name}-${var.location}-${var.tier}-backup-plan"
    environment  = var.environment
    location     = var.location
    service_name = var.service_name
    tier         = var.tier
    terraformed  = "true"
  }
}

data "aws_iam_policy_document" "assume_role_policy" {

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

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

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

    actions = [
      "backup-gateway:Backup",
      "backup-gateway:ListTagsForResource"
    ]

    resources = [
      "arn:aws:backup-gateway:*:*:vm/*"
    ]
  }

  statement {
    effect = "Allow"

    actions = [
      "backup-gateway:Restore",
    ]

    resources = [
      "arn:aws:backup-gateway:*:*:hypervisor/${var.backup_hypervisor_id}"
    ]
  }

  statement {
    effect = "Allow"

    actions = [
      "tag:GetResources"
    ]

    resources = [
      "*"
    ]
  }
}

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

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

    resources = [
      aws_kms_key.backup_kms_key.arn,
    ]
  }

  statement {
    effect = "Allow"

    actions = [
      "kms:CreateGrant"
    ]

    resources = [
      aws_kms_key.backup_kms_key.arn,
    ]

    condition {
      test     = "Bool"
      variable = "kms:GrantIsForAWSResource"

      values = [
        "true",
      ]
    }
  }
}

resource "aws_iam_role" "backup_role" {
  name               = "${var.environment}-${var.service_name}-${var.location}-${var.tier}-backup-role"
  assume_role_policy = data.aws_iam_policy_document.assume_role_policy.json

  tags = {
    Name         = "${var.environment}-${var.service_name}-${var.location}-${var.tier}-backup-role"
    environment  = var.environment
    location     = var.location
    service_name = var.service_name
    tier         = var.tier
    terraformed  = "true"
  }
}

# Create policies
resource "aws_iam_policy" "vm_backup_policy" {
  name   = "Backup-${var.environment}-${var.service_name}-${var.location}-${var.tier}-backup-policy"
  policy = data.aws_iam_policy_document.vm_backup_policy.json
}

resource "aws_iam_policy" "backup_kms_policy" {
  name   = "KMS-${var.environment}-${var.service_name}-${var.location}-${var.tier}-backup-policy"
  policy = data.aws_iam_policy_document.kms_policy.json
}

# Attach policies to role
resource "aws_iam_role_policy_attachment" "vm_backup_policy_attachment" {
  role       = aws_iam_role.backup_role.name
  policy_arn = aws_iam_policy.vm_backup_policy.arn
}

resource "aws_iam_role_policy_attachment" "kms_policy_attachment" {
  role       = aws_iam_role.backup_role.name
  policy_arn = aws_iam_policy.backup_kms_policy.arn
}

resource "aws_backup_selection" "backup_selection" {
  iam_role_arn = aws_iam_role.backup_role.arn
  name         = "${var.environment}-${var.service_name}-${var.location}-${var.tier}-backup-selection"
  plan_id      = aws_backup_plan.plan.id
  resources = ["*"]

  condition {
    string_equals {
      key   = "aws:ResourceTag/aws:backup-gateway:hypervisor-id"
      value = var.backup_hypervisor_id
    }
    string_equals {
      key = "aws:ResourceTag/backup_enabled"
      value = "true"
    }
  }
}