# Bucket =======================================================================

resource "aws_s3_bucket" "this" {
  bucket              = var.bucket_name
  force_destroy       = var.force_destroy
  object_lock_enabled = var.object_lock_enabled

  tags = merge(var.tags, local.module_tags, {
    resource-type = "s3-bucket"
  })
}

# Object Lock Configuration ----------------------------------------------------

resource "aws_s3_bucket_object_lock_configuration" "this" {
  for_each = (
    var.object_lock_enabled && var.object_lock_default_retention != null
    ? { lock = var.object_lock_default_retention }
    : {}
  )

  bucket = aws_s3_bucket.this.id

  rule {
    default_retention {
      mode = each.value.mode
      days = each.value.days
    }
  }
}

# Object ownership -------------------------------------------------------------

resource "aws_s3_bucket_ownership_controls" "this" {
  bucket = aws_s3_bucket.this.id

  rule {
    object_ownership = var.object_ownership
  }
}

# Public access block --------------------------------------------------------

resource "aws_s3_bucket_public_access_block" "this" {
  bucket = aws_s3_bucket.this.id

  block_public_acls       = var.block_public_acls
  block_public_policy     = var.block_public_policy
  ignore_public_acls      = var.ignore_public_acls
  restrict_public_buckets = var.restrict_public_buckets
}

# Versioning -----------------------------------------------------------------

resource "aws_s3_bucket_versioning" "this" {
  bucket = aws_s3_bucket.this.id

  versioning_configuration {
    status = var.versioning_enabled ? "Enabled" : "Suspended"
  }
}

# Encryption -----------------------------------------------------------------

resource "aws_s3_bucket_server_side_encryption_configuration" "this" {
  bucket = aws_s3_bucket.this.id

  rule {
    bucket_key_enabled = var.bucket_key_enabled

    apply_server_side_encryption_by_default {
      sse_algorithm     = var.sse_algorithm
      kms_master_key_id = var.kms_key_id
    }
  }
}

# Lifecycle rules ------------------------------------------------------------

resource "aws_s3_bucket_lifecycle_configuration" "this" {
  for_each = length(var.lifecycle_rules) > 0 ? { rules = var.lifecycle_rules } : {}

  bucket = aws_s3_bucket.this.id

  dynamic "rule" {
    for_each = each.value
    content {
      id     = rule.key
      status = rule.value.enabled ? "Enabled" : "Disabled"

      dynamic "filter" {
        for_each = rule.value.prefix != null ? [rule.value.prefix] : []
        content {
          prefix = filter.value
        }
      }

      abort_incomplete_multipart_upload {
        days_after_initiation = rule.value.abort_incomplete_multipart_upload_days
      }

      dynamic "expiration" {
        for_each = rule.value.expiration_days != null ? [rule.value.expiration_days] : []
        content {
          days = expiration.value
        }
      }

      dynamic "noncurrent_version_expiration" {
        for_each = rule.value.noncurrent_version_expiration_days != null ? [rule.value.noncurrent_version_expiration_days] : []
        content {
          noncurrent_days = noncurrent_version_expiration.value
        }
      }

      dynamic "transition" {
        for_each = rule.value.transitions
        content {
          days          = transition.value.days
          storage_class = transition.value.storage_class
        }
      }
    }
  }

  depends_on = [aws_s3_bucket_versioning.this]
}

# Access logging -------------------------------------------------------------

resource "aws_s3_bucket_logging" "this" {
  for_each = var.logging_target_bucket != null ? { logging = true } : {}

  bucket        = aws_s3_bucket.this.id
  target_bucket = var.logging_target_bucket
  target_prefix = var.logging_target_prefix
}

# Bucket policy --------------------------------------------------------------

resource "aws_s3_bucket_policy" "this" {
  for_each = var.policy != null ? { policy = true } : {}

  bucket = aws_s3_bucket.this.id
  policy = var.policy

  depends_on = [aws_s3_bucket_public_access_block.this]
}

# Replication ----------------------------------------------------------------

resource "aws_s3_bucket_replication_configuration" "this" {
  for_each = length(var.replication_rules) > 0 ? { replication = var.replication_rules } : {}

  bucket = aws_s3_bucket.this.id
  role   = var.replication_role_arn

  dynamic "rule" {
    for_each = each.value
    content {
      id       = rule.key
      priority = rule.value.priority
      status   = "Enabled"

      filter {
        prefix = rule.value.prefix
      }

      delete_marker_replication {
        status = rule.value.delete_marker_replication ? "Enabled" : "Disabled"
      }

      destination {
        bucket        = rule.value.destination_bucket_arn
        account       = rule.value.destination_account_id
        storage_class = "STANDARD"

        dynamic "encryption_configuration" {
          for_each = rule.value.destination_kms_key_id != null ? [rule.value.destination_kms_key_id] : []
          content {
            replica_kms_key_id = encryption_configuration.value
          }
        }

        dynamic "access_control_translation" {
          for_each = rule.value.destination_account_id != null ? [true] : []
          content {
            owner = "Destination"
          }
        }
      }
    }
  }

  depends_on = [aws_s3_bucket_versioning.this]
}
