resource "snowflake_grant_privileges_to_account_role" "all_objects_in_database" {
  count             = var.role_type == "account" ? 1 : 0
  privileges        = var.privileges
  account_role_name = var.role_name

  on_schema_object {
    all {
      object_type_plural = var.object_type_plural
      in_database        = var.database_name
    }
  }
}

resource "snowflake_grant_privileges_to_database_role" "all_objects_in_database" {
  count              = var.role_type == "database" ? 1 : 0
  privileges         = var.privileges
  database_role_name = "${var.database_name}.${var.role_name}"

  on_schema_object {
    all {
      object_type_plural = var.object_type_plural
      in_database        = var.database_name
    }
  }
}

resource "snowflake_grant_privileges_to_account_role" "future_objects_in_database" {
  count             = var.role_type == "account" ? 1 : 0
  privileges        = var.privileges
  account_role_name = var.role_name

  on_schema_object {
    future {
      object_type_plural = var.object_type_plural
      in_database        = var.database_name
    }
  }
}

resource "snowflake_grant_privileges_to_database_role" "future_objects_in_database" {
  count              = var.role_type == "database" ? 1 : 0
  privileges         = var.privileges
  database_role_name = "${var.database_name}.${var.role_name}"

  on_schema_object {
    future {
      object_type_plural = var.object_type_plural
      in_database        = var.database_name
    }
  }
}

# Also make explicit schema-level grants for the provided schemas. This may appear to be redundant
# given the database-level grants above. However, since there are no explicit dependencies between
# those Terraform resources and the schemas, it is possible that the schemas could be created after
# the "on all" grants have been applied but before the "on future" grants become effective.
# Making explicit grants for the provided schemas guarantees us against that scenario.
resource "snowflake_grant_privileges_to_account_role" "all_objects_in_schema" {
  for_each = var.role_type == "account" ? var.schemas : toset([])

  privileges        = var.privileges
  account_role_name = var.role_name

  on_schema_object {
    all {
      object_type_plural = var.object_type_plural
      in_schema          = "\"${var.database_name}\".\"${each.value}\""
    }
  }
}

resource "snowflake_grant_privileges_to_database_role" "all_objects_in_schema" {
  for_each = var.role_type == "database" ? var.schemas : toset([])

  privileges         = var.privileges
  database_role_name = "${var.database_name}.${var.role_name}"

  on_schema_object {
    all {
      object_type_plural = var.object_type_plural
      in_schema          = "\"${var.database_name}\".\"${each.value}\""
    }
  }
}

# Also make explicit schema-level future grants for the provided schemas. This may appear to be redundant
# given the database-level future grants above. However, when future grants are defined on the same object type
# for a database and a schema in the same database, the schema-level grants take precedence over the database level grants,
# even if the grants are for different roles. By explicitly configuring schema-level future grants for the provided schemas,
# we guarantee that the role has the correct privileges on future objects in those schemas.
# Reference: https://docs.snowflake.com/en/sql-reference/sql/grant-privilege#considerations
resource "snowflake_grant_privileges_to_account_role" "future_objects_in_schema" {
  for_each = var.role_type == "account" ? var.schemas : toset([])

  privileges        = var.privileges
  account_role_name = var.role_name

  on_schema_object {
    future {
      object_type_plural = var.object_type_plural
      in_schema          = "\"${var.database_name}\".\"${each.value}\""
    }
  }
}

resource "snowflake_grant_privileges_to_database_role" "future_objects_in_schema" {
  for_each = var.role_type == "database" ? var.schemas : toset([])

  privileges         = var.privileges
  database_role_name = "${var.database_name}.${var.role_name}"

  on_schema_object {
    future {
      object_type_plural = var.object_type_plural
      in_schema          = "\"${var.database_name}\".\"${each.value}\""
    }
  }
}
