/* module "default_tags" {
  source             = "git@github.com:theorchard/terraform-default-tags.git//?ref=1.0.0"
  environment        = var.environment
  application_family = var.application_family
} */

provider "aws" {
  region = "us-east-1"

  /* default_tags {
    tags = module.default_tags.tags
  } */
}

data "aws_caller_identity" "current" {}

data "aws_canonical_user_id" "current" {}

terraform {
  backend "s3" {
    bucket  = "orcd-terraform-state"
    key     = "qa/lambda-abacus/terraform.tfstate"
    region  = "us-east-1"
    encrypt = "true"
  }
}

module "vpc_info" {
  source      = "git@github.com:theorchard/terraform-vpc-info.git//?ref=3.2.2"
  environment = var.environment
}

data "aws_iam_policy_document" "abacus_sales_files_bucket_write_access_document" {
  statement {
    effect = "Allow"
    resources = [
      "${var.sales_files_bucket_arn}/*"
    ]
    actions = [
      "s3:GetObject",
      "s3:DeleteObject",
      "s3:PutObject"
    ]
  }

  statement {
    effect = "Allow"
    resources = [
      var.sales_files_bucket_arn
    ]
    actions = [
      "s3:ListBucket"
    ]
  }
}

resource "aws_iam_policy" "abacus_sales_files_bucket_write_access_policy" {
  name        = "${var.environment}-abacus-sales-files-write-access-policy"
  description = "Policy for sales files bucket write permissions"
  policy      = data.aws_iam_policy_document.abacus_sales_files_bucket_write_access_document.json
}

data "aws_lambda_function" "av_scan_lambda" {
  function_name = "${var.environment}-${var.av_scan_lambda_function_name}"
}


# START - PAYMENTS GENERATE

module "lambda_abacus_payments_generate_sentry_project" {
  source = "git@github.com:theorchard/terraform-sentry.git//?ref=4.1.2"

  environment        = var.environment
  platform           = "python"
  service_name       = "${var.service_name}-payments-generate"
  teams              = ["abacus-${var.environment}"]
  application_family = var.application_family
}

module "lambda_abacus_payments_generate_owsrequest" {
  source           = "git@github.com:theorchard/terraform-owsrequest.git//?ref=1.1.0"
  environment_name = var.environment
  service_name     = "${var.service_name}-payments-generate"
}

module "lambda_abacus_payments_generate" {
  source = "git@github.com:theorchard/terraform-lambda.git//?ref=5.2.1"

  environment                                       = var.environment
  lambda_function_timeout                           = 900
  use_container_image                               = true
  lambda_description                                = "Generates a set of payments for a group of payees"
  lambda_name                                       = "${var.service_name}-payments-generate"
  vpc_id                                            = module.vpc_info.vpc_id
  vpc_subnet_ids                                    = module.vpc_info.default_private_subnet_ids
  vpc_create_security_group                         = true
  application_family                                = var.application_family
  lambda_function_provisioned_concurrent_executions = var.lambda_provisioned_concurrent_executions

  lambda_function_reserved_concurrent_executions = 2
  lambda_function_memory_size                    = 1024

  datadog_enabled          = true
  datadog_advanced_enabled = true

  lambda_function_environment_variables = {
    ENVIRONMENT = var.environment
  }

  iam_managed_policy_attachments = [
    module.lambda_abacus_payments_generate_owsrequest.policy_arn_output
  ]
}

# END - PAYMENTS GENERATE


# START - SYNC CONTRACT

module "lambda_abacus_sync_contract_sentry_project" {
  source = "git@github.com:theorchard/terraform-sentry.git//?ref=4.1.2"

  environment        = var.environment
  platform           = "python"
  service_name       = "lambda-abacus-sync-contract"
  teams              = ["abacus-${var.environment}"]
  application_family = var.application_family
}

module "lambda_abacus_sync_contract_owsrequest" {
  source           = "git@github.com:theorchard/terraform-owsrequest.git//?ref=1.1.0"
  environment_name = var.environment
  service_name     = "lambda-abacus-sync-contract"
}

module "lambda_abacus_sync_contract" {
  source = "git@github.com:theorchard/terraform-lambda.git//?ref=5.2.1"

  environment                                       = var.environment
  lambda_function_timeout                           = 900
  use_container_image                               = true
  lambda_description                                = "Synchronize contract information between ABACUS and legacy."
  lambda_name                                       = "lambda-abacus-sync-contract"
  vpc_id                                            = module.vpc_info.vpc_id
  vpc_subnet_ids                                    = module.vpc_info.default_private_subnet_ids
  vpc_create_security_group                         = true
  application_family                                = var.application_family
  lambda_function_provisioned_concurrent_executions = var.lambda_provisioned_concurrent_executions

  lambda_function_reserved_concurrent_executions = 2
  lambda_function_memory_size                    = 1024

  datadog_enabled          = true
  datadog_advanced_enabled = true

  lambda_function_environment_variables = {
    ENVIRONMENT = var.environment
  }

  iam_managed_policy_attachments = [
    module.lambda_abacus_sync_contract_owsrequest.policy_arn_output
  ]
}

# END - SYNC CONTRACT

# START - PAYONEER PAYMENTS PAYOUT

module "lambda_abacus_payoneer_payments_payout_sentry_project" {
  source = "git@github.com:theorchard/terraform-sentry.git//?ref=4.1.2"

  environment        = var.environment
  platform           = "python"
  service_name       = "${var.service_name}-payoneer-payments-payout"
  teams              = ["abacus-${var.environment}"]
  application_family = var.application_family

}

module "lambda_abacus_payoneer_payments_payout_owsrequest" {
  source           = "git@github.com:theorchard/terraform-owsrequest.git//?ref=1.1.0"
  environment_name = var.environment
  service_name     = "${var.service_name}-payoneer-payments-payout"
}

module "lambda_abacus_payoneer_payments_payout" {
  source = "git@github.com:theorchard/terraform-lambda.git//?ref=5.2.1"

  environment                                       = var.environment
  lambda_function_timeout                           = 900
  use_container_image                               = true
  lambda_description                                = "Create the payments batches and send it to payoneer"
  lambda_name                                       = "${var.service_name}-payoneer-payments-payout"
  vpc_id                                            = module.vpc_info.vpc_id
  vpc_subnet_ids                                    = module.vpc_info.default_private_subnet_ids
  vpc_create_security_group                         = true
  application_family                                = var.application_family
  lambda_function_provisioned_concurrent_executions = var.lambda_provisioned_concurrent_executions

  lambda_function_reserved_concurrent_executions = 2
  lambda_function_memory_size                    = 1024

  datadog_enabled          = true
  datadog_advanced_enabled = true

  lambda_function_environment_variables = {
    ENVIRONMENT = var.environment
  }

  iam_managed_policy_attachments = [
    module.lambda_abacus_payoneer_payments_payout_owsrequest.policy_arn_output
  ]
}

# END - PAYONEER PAYMENTS PAYOUT


# START - RESERVES TAKE

module "lambda_abacus_reserves_take_sentry_project" {
  source = "git@github.com:theorchard/terraform-sentry.git//?ref=4.1.2"

  environment        = var.environment
  platform           = "python"
  service_name       = "lambda-abacus-reserves-take"
  teams              = ["abacus-${var.environment}"]
  application_family = var.application_family
}

module "lambda_abacus_reserves_take_owsrequest" {
  source           = "git@github.com:theorchard/terraform-owsrequest.git//?ref=1.1.0"
  environment_name = var.environment
  service_name     = "lambda-abacus-reserves-take"
}

module "lambda_abacus_reserves_take" {
  source = "git@github.com:theorchard/terraform-lambda.git//?ref=5.2.1"

  environment                                       = var.environment
  lambda_function_timeout                           = 900
  use_container_image                               = true
  lambda_description                                = "Creates contract reserves entries on accounting run's commit."
  lambda_name                                       = "lambda-abacus-reserves-take"
  vpc_id                                            = module.vpc_info.vpc_id
  vpc_subnet_ids                                    = module.vpc_info.default_private_subnet_ids
  vpc_create_security_group                         = true
  application_family                                = var.application_family
  lambda_function_provisioned_concurrent_executions = var.lambda_provisioned_concurrent_executions

  lambda_function_reserved_concurrent_executions = 2
  lambda_function_memory_size                    = 1024

  datadog_enabled          = true
  datadog_advanced_enabled = true

  lambda_function_environment_variables = {
    ENVIRONMENT         = var.environment
    SNOWFLAKE_ACCOUNT   = var.lambda_snowflake_account
    SNOWFLAKE_DATABASE  = var.lambda_snowflake_database
    SNOWFLAKE_SCHEMA    = var.lambda_snowflake_schema
    SNOWFLAKE_WAREHOUSE = var.lambda_snowflake_warehouse
    SNOWFLAKE_ROLE      = var.lambda_snowflake_role
    SNOWFLAKE_USER      = var.lambda_snowflake_user
  }

  iam_managed_policy_attachments = [
    module.lambda_abacus_reserves_take_owsrequest.policy_arn_output
  ]
}

module "lambda_abacus_reserves_take_secrets" {
  source   = "git@github.com:theorchard/terraform-secrets-manager.git//?ref=1.5.1"
  for_each = toset(var.secrets_manager_secret_names)

  application_family = var.application_family
  environment        = var.environment
  service_name       = "${var.service_name}-reserves-take"
  secret_name        = each.value
}

# END - RESERVES TAKE

# START - RESERVES RELEASE

module "lambda_abacus_reserves_release_sentry_project" {
  source = "git@github.com:theorchard/terraform-sentry.git//?ref=4.1.2"

  environment        = var.environment
  platform           = "python"
  service_name       = "${var.service_name}-reserves-release"
  teams              = ["abacus-${var.environment}"]
  application_family = var.application_family

}

module "lambda_abacus_reserves_release_owsrequest" {
  source           = "git@github.com:theorchard/terraform-owsrequest.git//?ref=1.1.0"
  environment_name = var.environment
  service_name     = "${var.service_name}-reserves-release"
}

module "lambda_abacus_reserves_release" {
  source = "git@github.com:theorchard/terraform-lambda.git//?ref=5.2.1"

  environment                                       = var.environment
  lambda_function_timeout                           = 900
  use_container_image                               = true
  lambda_description                                = "Credits back reserve amount to an account's ledger"
  lambda_name                                       = "${var.service_name}-reserves-release"
  vpc_id                                            = module.vpc_info.vpc_id
  vpc_subnet_ids                                    = module.vpc_info.default_private_subnet_ids
  vpc_create_security_group                         = true
  application_family                                = var.application_family
  lambda_function_provisioned_concurrent_executions = var.lambda_provisioned_concurrent_executions

  lambda_function_reserved_concurrent_executions = 2
  lambda_function_memory_size                    = 1024

  datadog_enabled          = true
  datadog_advanced_enabled = true

  lambda_function_environment_variables = {
    ENVIRONMENT = var.environment
  }

  iam_managed_policy_attachments = [
    module.lambda_abacus_reserves_release_owsrequest.policy_arn_output
  ]
}

# END - RESERVES RELEASE


# START - RESERVES SCHEDULE

module "lambda_abacus_reserves_schedule_sentry_project" {
  source = "git@github.com:theorchard/terraform-sentry.git//?ref=4.1.2"

  environment        = var.environment
  platform           = "python"
  service_name       = "lambda-abacus-reserves-schedule"
  teams              = ["abacus-${var.environment}"]
  application_family = var.application_family
}

module "lambda_abacus_reserves_schedule_owsrequest" {
  source           = "git@github.com:theorchard/terraform-owsrequest.git//?ref=1.1.0"
  environment_name = var.environment
  service_name     = "lambda-abacus-reserves-schedule"
}

module "lambda_abacus_reserves_schedule" {
  source = "git@github.com:theorchard/terraform-lambda.git//?ref=5.2.1"

  environment                                       = var.environment
  lambda_function_timeout                           = 900
  use_container_image                               = true
  lambda_description                                = "Divide the taken reserve value across the installment schedule."
  lambda_name                                       = "lambda-abacus-reserves-schedule"
  vpc_id                                            = module.vpc_info.vpc_id
  vpc_subnet_ids                                    = module.vpc_info.default_private_subnet_ids
  vpc_create_security_group                         = true
  application_family                                = var.application_family
  lambda_function_provisioned_concurrent_executions = var.lambda_provisioned_concurrent_executions

  lambda_function_reserved_concurrent_executions = 2
  lambda_function_memory_size                    = 1024

  datadog_enabled          = true
  datadog_advanced_enabled = true

  lambda_function_environment_variables = {
    ENVIRONMENT = var.environment
  }

  iam_managed_policy_attachments = [
    module.lambda_abacus_reserves_schedule_owsrequest.policy_arn_output
  ]
}

# END - RESERVES SCHEDULE

# START - SYNC CONTRACT SAP

module "lambda_abacus_sync_contract_sap_sentry_project" {
  source = "git@github.com:theorchard/terraform-sentry.git//?ref=4.1.2"

  environment        = var.environment
  platform           = "python"
  service_name       = "lambda-abacus-sync-contract-sap"
  teams              = ["abacus-${var.environment}"]
  application_family = var.application_family
}

module "lambda_abacus_sync_contract_sap_owsrequest" {
  source           = "git@github.com:theorchard/terraform-owsrequest.git//?ref=1.1.0"
  environment_name = var.environment
  service_name     = "lambda-abacus-sync-contract-sap"
}

module "lambda_abacus_sync_contract_sap" {
  source = "git@github.com:theorchard/terraform-lambda.git//?ref=5.2.1"

  environment                                       = var.environment
  lambda_function_timeout                           = 900
  use_container_image                               = true
  lambda_description                                = "Sends new contract and account records to the SAP system."
  lambda_name                                       = "lambda-abacus-sync-contract-sap"
  vpc_id                                            = module.vpc_info.vpc_id
  vpc_subnet_ids                                    = module.vpc_info.default_private_subnet_ids
  vpc_create_security_group                         = true
  application_family                                = var.application_family
  lambda_function_provisioned_concurrent_executions = var.lambda_provisioned_concurrent_executions

  lambda_function_reserved_concurrent_executions = 2
  lambda_function_memory_size                    = 1024

  datadog_enabled          = true
  datadog_advanced_enabled = true

  lambda_function_environment_variables = {
    ENVIRONMENT = var.environment
    SAP_ENV     = var.sap_env
    SAP_API     = var.sap_api

    MYSQL_DB_HOST = var.lambda_abacus_mysql_host
    MYSQL_DB_NAME = var.lambda_abacus_mysql_database
    MYSQL_DB_USER = var.lambda_abacus_mysql_user
  }

  iam_managed_policy_attachments = [
    module.lambda_abacus_sync_contract_sap_owsrequest.policy_arn_output
  ]
}

module "lambda_abacus_sync_contract_sap_secrets" {
  source   = "git@github.com:theorchard/terraform-secrets-manager.git//?ref=1.5.1"
  for_each = toset(var.sync_contract_sap_secrets_manager_secret_names)

  application_family = var.application_family
  environment        = var.environment
  service_name       = "${var.service_name}-sync-contract-sap"
  secret_name        = each.value
}

# END - SYNC CONTRACT SAP

# START - CORRECTION APPLY

module "lambda_abacus_correction_apply_sentry_project" {
  source = "git@github.com:theorchard/terraform-sentry.git//?ref=4.1.2"

  environment        = var.environment
  platform           = "python"
  service_name       = "${var.service_name}-correction-apply"
  teams              = ["abacus-${var.environment}"]
  application_family = var.application_family
}

module "lambda_abacus_correction_apply_owsrequest" {
  source           = "git@github.com:theorchard/terraform-owsrequest.git//?ref=1.1.0"
  environment_name = var.environment
  service_name     = "${var.service_name}-correction-apply"
}

module "lambda_abacus_correction_apply" {
  source = "git@github.com:theorchard/terraform-lambda.git//?ref=5.2.1"

  environment                                       = var.environment
  lambda_function_timeout                           = 900
  use_container_image                               = true
  lambda_description                                = "Create ledger entries for transaction corrections."
  lambda_name                                       = "${var.service_name}-correction-apply"
  vpc_id                                            = module.vpc_info.vpc_id
  vpc_subnet_ids                                    = module.vpc_info.default_private_subnet_ids
  vpc_create_security_group                         = true
  application_family                                = var.application_family
  lambda_function_provisioned_concurrent_executions = var.lambda_provisioned_concurrent_executions

  lambda_function_reserved_concurrent_executions = 2
  lambda_function_memory_size                    = 1024

  datadog_enabled          = true
  datadog_advanced_enabled = true

  lambda_function_environment_variables = {
    ENVIRONMENT = var.environment
  }

  iam_managed_policy_attachments = [
    module.lambda_abacus_correction_apply_owsrequest.policy_arn_output
  ]
}

# END - CORRECTION APPLY

# START - AUTO ADD CONTRIBUTIONS

module "lambda_abacus_schedule_auto_add_sentry_project" {
  source = "git@github.com:theorchard/terraform-sentry.git//?ref=4.1.2"

  environment        = var.environment
  platform           = "python"
  service_name       = "${var.service_name}-schedule-auto-add"
  teams              = ["abacus-${var.environment}"]
  application_family = var.application_family
}

module "lambda_abacus_schedule_auto_add" {
  source = "git@github.com:theorchard/terraform-lambda.git//?ref=5.2.1"

  environment                                       = var.environment
  lambda_function_timeout                           = 900
  use_container_image                               = true
  lambda_description                                = "Add contributions to auto_add schedules."
  lambda_name                                       = "${var.service_name}-schedule-auto-add"
  vpc_id                                            = module.vpc_info.vpc_id
  vpc_subnet_ids                                    = module.vpc_info.default_private_subnet_ids
  vpc_create_security_group                         = true
  application_family                                = var.application_family
  lambda_function_provisioned_concurrent_executions = var.lambda_provisioned_concurrent_executions
  datadog_advanced_enabled                          = false

  lambda_function_reserved_concurrent_executions = 2
  lambda_function_memory_size                    = 1024

  lambda_function_environment_variables = {
    ENVIRONMENT         = var.environment
    GRAPHQL_GATEWAY_URL = var.graphql_url
  }

  msk_event_enabled                          = true
  event_source_mapping_msk_cluster_name      = var.trigger_msk_cluster_name
  event_source_mapping_msk_cluster_uuid      = var.trigger_msk_cluster_uuid
  event_source_mapping_batch_size            = 1
  kafka_topics                               = [var.contribution_metadata_topic]
  event_source_mapping_starting_position     = "LATEST"
  datadog_advanced_merge_xray_traces_enabled = false
  datadog_advanced_trace_enabled             = true

}

module "lambda_abacus_schedule_auto_add_secrets" {
  source   = "git@github.com:theorchard/terraform-secrets-manager.git//?ref=1.5.1"
  for_each = toset(var.schedule_auto_add_secrets_manager_secret_names)

  application_family = var.application_family
  environment        = var.environment
  service_name       = "${var.service_name}-schedule-auto-add"
  secret_name        = each.value
}

# END - AUTO ADD CONTRIBUTIONS


# START - INVOKE POLICY
# Note the statement for lambda:InvokeFunction allows both unqualified and and qualified (:*) access
data "aws_iam_policy_document" "abacus_lambdas_invoke" {
  statement {
    effect = "Allow"
    resources = [
      module.lambda_abacus_snapshot_contracts.lambda_arn,
      module.lambda_abacus_contract_lifecycle_automation.lambda_arn,
      module.lambda_abacus_schedule_auto_add.lambda_arn,
      module.lambda_abacus_sync_account.lambda_arn,
      module.lambda_abacus_commit_ledger_account_contract.lambda_arn,
      module.lambda_abacus_commit_royalties.lambda_arn,
      module.lambda_abacus_commit_mechanicals.lambda_arn,
      module.lambda_abacus_correction_apply.lambda_arn,
      module.lambda_abacus_correction_stage.lambda_arn,
      module.lambda_abacus_file_upload_complete.lambda_arn,
      module.lambda_abacus_file_upload_initialize.lambda_arn,
      module.lambda_abacus_ledger_accounting_run_balance.lambda_arn,
      module.lambda_abacus_payoneer_payments_payout.lambda_arn,
      module.lambda_abacus_payments_generate.lambda_arn,
      module.lambda_abacus_reserves_release.lambda_arn,
      module.lambda_abacus_reserves_take.lambda_arn,
      module.lambda_abacus_reserves_schedule.lambda_arn,
      module.lambda_abacus_royalty_collection_territory_backfill.lambda_arn,
      module.lambda_abacus_sync_contract.lambda_arn,
      module.lambda_abacus_sync_contract_sap.lambda_arn,
      data.aws_lambda_function.av_scan_lambda.arn,
      "${module.lambda_abacus_snapshot_contracts.lambda_arn}:*",
      "${module.lambda_abacus_contract_lifecycle_automation.lambda_arn}:*",
      "${module.lambda_abacus_schedule_auto_add.lambda_arn}:*",
      "${module.lambda_abacus_sync_account.lambda_arn}:*",
      "${module.lambda_abacus_commit_ledger_account_contract.lambda_arn}:*",
      "${module.lambda_abacus_commit_mechanicals.lambda_arn}:*",
      "${module.lambda_abacus_commit_royalties.lambda_arn}:*",
      "${module.lambda_abacus_correction_apply.lambda_arn}:*",
      "${module.lambda_abacus_correction_stage.lambda_arn}:*",
      "${module.lambda_abacus_file_upload_complete.lambda_arn}:*",
      "${module.lambda_abacus_file_upload_initialize.lambda_arn}:*",
      "${module.lambda_abacus_ledger_accounting_run_balance.lambda_arn}:*",
      "${module.lambda_abacus_payoneer_payments_payout.lambda_arn}:*",
      "${module.lambda_abacus_payments_generate.lambda_arn}:*",
      "${module.lambda_abacus_reserves_release.lambda_arn}:*",
      "${module.lambda_abacus_reserves_take.lambda_arn}:*",
      "${module.lambda_abacus_reserves_schedule.lambda_arn}:*",
      "${module.lambda_abacus_royalty_collection_territory_backfill.lambda_arn}:*",
      "${module.lambda_abacus_sync_contract.lambda_arn}:*",
      "${module.lambda_abacus_sync_contract_sap.lambda_arn}:*",
      "${data.aws_lambda_function.av_scan_lambda.arn}:*",
    ]
    actions = [
      "lambda:InvokeFunction"
    ]
  }
  statement {
    effect = "Allow"
    resources = [
      "arn:aws:s3:::${var.environment}-lambda-abacus-ci-cd",
      "arn:aws:s3:::${var.environment}-lambda-abacus-ci-cd/*"
    ]
    actions = [
      "s3:AbortMultipartUpload",
      "s3:DeleteObject",
      "s3:DeleteObjectVersion",
      "s3:GetBucketLocation",
      "s3:GetBucketVersioning",
      "s3:GetLifecycleConfiguration",
      "s3:GetObject",
      "s3:GetObjectAcl",
      "s3:GetObjectTorrent",
      "s3:GetObjectVersion",
      "s3:CopyObject",
      "s3:GetObjectVersionAcl",
      "s3:GetObjectVersionTorrent",
      "s3:GetReplicationConfiguration",
      "s3:List*",
      "s3:PutObject",
      "s3:PutObjectAcl",
      "s3:PutObjectVersionAcl",
      "s3:ReplicateDelete",
      "s3:ReplicateObject",
      "s3:RestoreObject",
    ]
  }
}

resource "aws_iam_policy" "abacus_lambdas_invoke_policy" {
  name        = "${var.environment}-lambda-abacus-generic-invoke-policy"
  description = "Policy for invoking abacus lambdas"
  policy      = data.aws_iam_policy_document.abacus_lambdas_invoke.json
}

resource "aws_iam_group_policy_attachment" "abacus_lambda_generic_test_group_invoke_policy_attachment" {
  group      = var.test_group_name
  policy_arn = aws_iam_policy.abacus_lambdas_invoke_policy.arn
}

# END - INVOKE POLICY

# START - CI/CD RESOURCES
module "ci_cd_bucket" {
  source = "git@github.com:theorchard/terraform-s3.git//modules/s3_bucket?ref=3.15.1"

  env                = var.environment
  bucket_name        = "lambda-abacus-ci-cd"
  application_family = var.application_family

  apply_server_side_encryption_by_default = {
    sse_algorithm = "AES256"
  }
}
# END - CI/CD RESOURCES
