locals {
  # [Account roles]
  # The resource requires a dedicated pair account role name - database role name for each resource
  # We create a list of maps and then transform it to a single map
  account_role_grants_list = flatten([
    for role in var.roles : [
      for db_role in role.granted_account_roles : {
        parent_role_name  = role.name,
        account_role_name = db_role,
      }
    ] if role.granted_account_roles != null
  ])

  account_role_grants_map = { for role_grant in local.account_role_grants_list : "${role_grant.parent_role_name}_${role_grant.account_role_name}" => role_grant }

  # [Database roles]
  # The resource requires a dedicated pair account role name - database role name for each resource
  # We create a list of maps and then transform it to a single map
  db_role_grants_list = flatten([
    for role in var.roles : [
      for db_role in role.granted_database_roles : {
        parent_role_name   = role.name,
        database_role_name = db_role,
      }
    ] if role.granted_database_roles != null
  ])

  db_role_grants_map = { for role_grant in local.db_role_grants_list : "${role_grant.parent_role_name}_${role_grant.database_role_name}" => role_grant }

  # [snowflake_grant_application_role]
  # The resource requires a dedicated pair application_role_name & parent_role_name for each resource
  application_roles_list = flatten([
    for role in var.roles : [
      for db_role in role.granted_application_roles : {
        parent_role_name      = role.name,
        application_role_name = db_role,
      }
    ] if role.granted_application_roles != null
  ])

  application_roles_map = { for role_grant in local.application_roles_list : "${role_grant.parent_role_name}_${role_grant.application_role_name}" => role_grant }
}

resource "snowflake_account_role" "roles" {
  for_each = { for role in var.roles : role.name => role.comment }

  name    = each.key
  comment = each.value
}

resource "snowflake_grant_account_role" "grant_to_sysadmin" {
  for_each = toset([for role in var.roles : role.name if lookup(role, "grant_to_sysadmin", true)])

  role_name        = snowflake_account_role.roles[each.value].name
  parent_role_name = "SYSADMIN"
}

resource "snowflake_grant_ownership" "role_ownership" {
  for_each = { for role in var.roles : role.name => role }

  account_role_name   = each.value.owner
  outbound_privileges = "COPY"

  on {
    object_type = "ROLE"
    object_name = snowflake_account_role.roles[each.key].name
  }
}

resource "snowflake_grant_privileges_to_account_role" "account_level_grants" {
  for_each = { for role in var.roles : role.name => role.account_level_grants if role.account_level_grants != null }

  provider          = snowflake.prod_atlantis
  privileges        = each.value
  account_role_name = snowflake_account_role.roles[each.key].name
  on_account        = true
}

resource "snowflake_grant_account_role" "account_roles" {
  for_each = local.account_role_grants_map

  role_name        = each.value.account_role_name
  parent_role_name = snowflake_account_role.roles[each.value.parent_role_name].name
}

resource "snowflake_grant_database_role" "database_roles" {
  for_each = local.db_role_grants_map

  database_role_name = each.value.database_role_name
  parent_role_name   = snowflake_account_role.roles[each.value.parent_role_name].name
}

# grant application role to application
resource "snowflake_grant_application_role" "application_roles" {
  for_each = local.application_roles_map

  application_role_name    = each.value.application_role_name
  parent_account_role_name = snowflake_account_role.roles[each.value.parent_role_name].name
}

# Create SNOWFLAKE_USAGE role with all required grants in one place.
resource "snowflake_account_role" "snowflake_usage_role" {
  name    = "SNOWFLAKE_USAGE"
  comment = "SNOWFLAKE_USAGE role"
}
resource "snowflake_grant_privileges_to_account_role" "snowflake_usage_imported_privileges" {
  account_role_name = snowflake_account_role.snowflake_usage_role.name
  privileges        = ["IMPORTED PRIVILEGES"]
  on_account_object {
    object_type = "DATABASE"
    object_name = "SNOWFLAKE"
  }
}
# Grant application_role to SNOWFLAKE_USAGE role.
resource "snowflake_grant_application_role" "SNOWFLAKE_USAGE_application_roles" {
  for_each = toset([
    "SNOWFLAKE.EVENTS_VIEWER",
    "SNOWFLAKE.EVENTS_ADMIN",
  ])

  application_role_name    = each.value
  parent_account_role_name = "SNOWFLAKE_USAGE"
}
# Grant database_role to SNOWFLAKE_USAGE role.
resource "snowflake_grant_database_role" "SNOWFLAKE_USAGE_database_roles" {
  for_each = toset([
    "SNOWFLAKE.OBJECT_VIEWER",
    "SNOWFLAKE.USAGE_VIEWER",
    "SNOWFLAKE.GOVERNANCE_VIEWER",
    "SNOWFLAKE.SECURITY_VIEWER",
    "SNOWFLAKE.ORGANIZATION_USAGE_VIEWER",
    "SNOWFLAKE.ORGANIZATION_BILLING_VIEWER",
    "SNOWFLAKE.WORKLOAD_INSIGHTS_USER",
    "SNOWFLAKE.DATA_METRIC_USER",
  ])

  database_role_name = each.value
  parent_role_name   = "SNOWFLAKE_USAGE"
}

resource "snowflake_grant_privileges_to_account_role" "luminate_share_usage_imported_privileges" {
  account_role_name = "LUMINATE_SHARE_READ"
  privileges        = ["IMPORTED PRIVILEGES"]
  on_account_object {
    object_type = "DATABASE"
    object_name = "LUMINATE_DB_LISTING_DETAIL"
  }
}

resource "snowflake_grant_privileges_to_account_role" "luminate_claim_usage_imported_privileges" {
  account_role_name = "LUMINATE_SHARE_READ"
  privileges        = ["IMPORTED PRIVILEGES"]
  on_account_object {
    object_type = "DATABASE"
    object_name = "LUMINATE_DB_LISTING_CLAIM"
  }
}

# Grant APPLY MASKING POLICY privilege to MASKING_ADMIN role
resource "snowflake_grant_privileges_to_account_role" "masking_admin_apply_masking_policy" {
  account_role_name = snowflake_account_role.roles["MASKING_ADMIN"].name
  privileges        = ["APPLY MASKING POLICY"]
  on_account        = true
}


# ml classification
resource "snowflake_grant_privileges_to_database_role" "create_ml_classification_shared" {
  database_role_name = "SME_ANALYTICS.DB_SHARED_SCHEMA_READWRITE"
  privileges         = ["CREATE SNOWFLAKE.ML.CLASSIFICATION"]
  on_schema {
    schema_name = "SME_ANALYTICS.SHARED"
  }
}
resource "snowflake_grant_privileges_to_database_role" "create_ml_classification_fi" {
  database_role_name = "SME_ANALYTICS.DB_FI_SCHEMA_READWRITE"
  privileges         = ["CREATE SNOWFLAKE.ML.CLASSIFICATION"]
  on_schema {
    schema_name = "SME_ANALYTICS.FI"
  }
}

resource "snowflake_grant_privileges_to_database_role" "dbt_gsa_schema" {
  database_role_name = "SME_ANALYTICS.DB_GSA_SCHEMA_READWRITE"
  privileges = [
    "CREATE DBT PROJECT",
  ]
  on_schema {
    schema_name = "SME_ANALYTICS.GSA"
  }
}

resource "snowflake_grant_privileges_to_account_role" "snowflake_documentation_imported_privileges" {
  account_role_name = "SNOWFLAKE_DOCUMENTATION_SHARE_READ"
  privileges        = ["IMPORTED PRIVILEGES"]
  on_account_object {
    object_type = "DATABASE"
    object_name = "SNOWFLAKE_DOCUMENTATION"
  }
}

resource "snowflake_grant_privileges_to_account_role" "spotify_api_access_integration_usage_sme_analytics_france" {
  account_role_name = snowflake_account_role.roles["SME_ANALYTICS_FRANCE"].name
  privileges        = ["USAGE"]
  on_account_object {
    object_type = "INTEGRATION"
    object_name = "\"SPOTIFY_API_ACCESS_INTEGRATION\""
  }
}

resource "snowflake_grant_privileges_to_account_role" "spotify_api_access_integration_usage_sme_analytics_australia" {
  account_role_name = snowflake_account_role.roles["SME_ANALYTICS_AUSTRALIA"].name
  privileges        = ["USAGE"]
  on_account_object {
    object_type = "INTEGRATION"
    object_name = "\"SPOTIFY_API_ACCESS_INTEGRATION\""
  }
}

resource "snowflake_grant_privileges_to_account_role" "google_news_api_access_integration_usage_sme_analytics_australia" {
  account_role_name = snowflake_account_role.roles["SME_ANALYTICS_AUSTRALIA"].name
  privileges        = ["USAGE"]
  on_account_object {
    object_type = "INTEGRATION"
    object_name = "\"GOOGLE_NEWS_API_ACCESS_INTEGRATION\""
  }
}

resource "snowflake_grant_privileges_to_account_role" "powerplatform_api_access_integration_usage_sme_analytics_australia" {
  account_role_name = snowflake_account_role.roles["SME_ANALYTICS_AUSTRALIA"].name
  privileges        = ["USAGE"]
  on_account_object {
    object_type = "INTEGRATION"
    object_name = "\"POWERPLATFORM_API_ACCESS_INTEGRATION\""
  }
}

resource "snowflake_grant_privileges_to_account_role" "audiense_api_access_integration_usage_sme_analytics_australia" {
  account_role_name = snowflake_account_role.roles["SME_ANALYTICS_AUSTRALIA"].name
  privileges        = ["USAGE"]
  on_account_object {
    object_type = "INTEGRATION"
    object_name = "\"AUDIENSE_API_ACCESS_INTEGRATION\""
  }
}

resource "snowflake_grant_privileges_to_account_role" "pypi_access_integration_usage_sme_analytics_france" {
  account_role_name = snowflake_account_role.roles["SME_ANALYTICS_FRANCE"].name
  privileges        = ["USAGE"]
  on_account_object {
    object_type = "INTEGRATION"
    object_name = "\"PYPI_ACCESS_INTEGRATION\""
  }
}

resource "snowflake_grant_privileges_to_account_role" "lorelai_agent_create_agent_dev_schema" {
  account_role_name = snowflake_account_role.roles["LORELAI_AGENT_DB_DEPLOYMENT_ROLE"].name
  privileges        = ["CREATE AGENT"]
  on_schema {
    schema_name = "LORELAI_AGENT.DEV"
  }
}

resource "snowflake_grant_privileges_to_account_role" "spotify_api_access_integration_usage_sme_analytics_us_rca" {
  account_role_name = snowflake_account_role.roles["SME_ANALYTICS_US_RCA"].name
  privileges        = ["USAGE"]
  on_account_object {
    object_type = "INTEGRATION"
    object_name = "\"SPOTIFY_API_ACCESS_INTEGRATION\""
  }
}

resource "snowflake_grant_privileges_to_account_role" "spotify_api_access_integration_usage_sme_analytics_epic" {
  account_role_name = snowflake_account_role.roles["SME_ANALYTICS_EPIC"].name
  privileges        = ["USAGE"]
  on_account_object {
    object_type = "INTEGRATION"
    object_name = "\"SPOTIFY_API_ACCESS_INTEGRATION\""
  }
}

resource "snowflake_grant_privileges_to_account_role" "google_api_access_integration_usage_sme_analytics_spain" {
  account_role_name = snowflake_account_role.roles["SME_ANALYTICS_SPAIN"].name
  privileges        = ["USAGE"]
  on_account_object {
    object_type = "INTEGRATION"
    object_name = "\"GOOGLE_API_ACCESS_INTEGRATION\""
  }
}

resource "snowflake_grant_privileges_to_account_role" "apple_api_access_integration_usage_sme_analytics_spain" {
  account_role_name = snowflake_account_role.roles["SME_ANALYTICS_SPAIN"].name
  privileges        = ["USAGE"]
  on_account_object {
    object_type = "INTEGRATION"
    object_name = "\"APPLE_API_ACCESS_INTEGRATION\""
  }
}

resource "snowflake_grant_privileges_to_account_role" "tiktok_api_access_integration_usage_sme_analytics_spain" {
  account_role_name = snowflake_account_role.roles["SME_ANALYTICS_SPAIN"].name
  privileges        = ["USAGE"]
  on_account_object {
    object_type = "INTEGRATION"
    object_name = "\"TIKTOK_API_ACCESS_INTEGRATION\""
  }
}

resource "snowflake_grant_privileges_to_account_role" "deezer_api_access_integration_usage_sme_analytics_epic" {
  account_role_name = snowflake_account_role.roles["SME_ANALYTICS_EPIC"].name
  privileges        = ["USAGE"]
  on_account_object {
    object_type = "INTEGRATION"
    object_name = "\"DEEZER_API_ACCESS_INTEGRATION\""
  }
}

resource "snowflake_grant_privileges_to_account_role" "prod_orcd_ftp_qqmedia_integration_usage" {
  account_role_name = snowflake_account_role.roles["SME_ANALYTICS_GSA"].name
  privileges        = ["USAGE"]
  on_account_object {
    object_type = "INTEGRATION"
    object_name = "\"PROD_ORCD_FTP_QQMEDIA_S3_INTEGRATION\""
  }
}

resource "snowflake_grant_privileges_to_account_role" "prod_rdb_linkfire_s3_integration_usage_sdc_reporting_db" {
  account_role_name = snowflake_account_role.roles["SDC_REPORTING_DB_LINKFIRE"].name
  privileges        = ["USAGE"]
  on_account_object {
    object_type = "INTEGRATION"
    object_name = "\"PROD_DELPHI_SNOWFLAKE_RDB_LINKFIRE_S3_INTEGRATION\""
  }
}

resource "snowflake_grant_privileges_to_account_role" "prod_rdb_linkfire_stage_write_sdc_reporting_db" {
  account_role_name = snowflake_account_role.roles["SDC_REPORTING_DB_LINKFIRE"].name
  privileges        = ["READ", "WRITE"]
  on_schema_object {
    object_type = "STAGE"
    object_name = "\"REPORTING_DB_SYNC\".\"LINKFIRE\".\"prod-rdb-linkfire-s3-stage\""
  }
}

resource "snowflake_grant_privileges_to_account_role" "grant_create_secret_sme_analytics_us_rca" {
  account_role_name = "SME_ANALYTICS_US_RCA"
  privileges        = ["CREATE SECRET"]
  on_schema {
    schema_name = "SME_ANALYTICS.US_RCA"
  }
}

resource "snowflake_grant_privileges_to_account_role" "spotify_api_access_integration_usage_sme_analytics_gsa" {
  account_role_name = snowflake_account_role.roles["SME_ANALYTICS_GSA"].name
  privileges        = ["USAGE"]
  on_account_object {
    object_type = "INTEGRATION"
    object_name = "\"SPOTIFY_API_ACCESS_INTEGRATION\""
  }
}
