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

provider "aws" {
  region = var.aws_region

  default_tags {
    tags = module.default_tags.tags
  }
}

provider "aws" {
  region  = var.aws_region
  alias   = "networking"
  profile = "networking"

  default_tags {
    tags = module.default_tags.tags
  }
}

terraform {
  backend "s3" {
    bucket  = "orcd-terraform-state"
    key     = "prod/documents/payoneer-webhooks-payee/terraform.tfstate"
    region  = "us-east-1"
    encrypt = "true"
  }
}

data "aws_caller_identity" "current" {}

#################################
#
# lambda configuration
#
##################################
module "lambda_documents_payoneer_webhooks_payee" {
  source                   = "git@github.com:theorchard/terraform-lambda.git//?ref=4.1.0"
  environment              = var.environment
  lambda_name              = var.service_full_name
  lambda_description       = "Receive and process Payoneer Webhook payee notifications"
  datadog_enabled          = var.datadog_enabled
  datadog_advanced_enabled = var.datadog_advanced_enabled

  application_family = var.application_family

  # lambda_function_provisioned_concurrent_executions = var.lambda_provisioned_concurrent_executions
  lambda_function_timeout = "300"
  use_container_image     = true

  vpc_id                  = var.vpc_id
  vpc_subnet_ids          = var.vpc_subnet_ids
  zappa_s3_policy_enabled = false

  lambda_function_environment_variables = {
    ENVIRONMENT = var.environment
  }

  lambda_function_reserved_concurrent_executions = "10"
}

module "lambda_documents_payoneer_webhooks_payee_owsrequest" {
  source = "git@github.com:theorchard/terraform-owsrequest.git//?ref=1.1.0"

  environment_name = var.environment
  service_name     = var.service_full_name
}

# create datadog dashboards.
module "datadog_lambda_documents_payoneer_webhooks_payee" {
  source = "git@github.com:theorchard/terraform-datadog.git//modules/lambda?ref=6.13.4"

  environment                       = var.environment
  service_name                      = var.service_full_name
  lambda_invocation_monitor_enabled = false

  notification_endpoints            = "@slack-The_Orchard-tap-alerts-prod"
  escalation_notification_endpoints = "@slack-The_Orchard-tap-alerts-prod"
}

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

  environment        = var.environment
  platform           = "python"
  service_name       = var.service_full_name
  teams              = [var.environment]
  application_family = var.application_family
}

#################################
#
# API Gateway configuration
#
##################################
resource "aws_api_gateway_rest_api" "payoneer_webhooks_payee_api" {
  name = "${var.environment}-${var.service_base_name}-api"

  disable_execute_api_endpoint = true

  tags = local.tags
  endpoint_configuration {
    types = ["EDGE"]
  }
  lifecycle {
    create_before_destroy = true
  }
}

data "aws_wafv2_web_acl" "waf" {
  name  = "${var.environment}-orcd-waf-block"
  scope = "REGIONAL"
}

resource "aws_wafv2_web_acl_association" "api_gateway_waf_association" {
  resource_arn = aws_api_gateway_stage.api_gateway_stage.arn
  web_acl_arn  = data.aws_wafv2_web_acl.waf.arn
}

resource "aws_api_gateway_rest_api_policy" "payoneer_webhooks_payee_api_policy" {
  rest_api_id = aws_api_gateway_rest_api.payoneer_webhooks_payee_api.id
  policy      = data.aws_iam_policy_document.payoneer_webhooks_payee_api_policy.json
}

data "aws_iam_policy_document" "payoneer_webhooks_payee_api_policy" {
  statement {
    effect  = "Allow"
    actions = ["execute-api:Invoke"]
    principals {
      type        = "*"
      identifiers = ["*"]
    }
    condition {
      test     = "IpAddress"
      variable = "aws:SourceIp"
      values = [
        "82.163.141.4/32",
        "193.104.115.2/32",
        "88.202.220.4/32",
        "142.154.207.1/32",
        "203.185.50.1/32",
      ]
    }
    resources = ["${aws_api_gateway_rest_api.payoneer_webhooks_payee_api.execution_arn}/*/POST/*"]
  }
}

# /{proxy+}
resource "aws_api_gateway_resource" "payoneer_webhooks_payee_api_resource_webhooks" {
  parent_id   = aws_api_gateway_rest_api.payoneer_webhooks_payee_api.root_resource_id
  rest_api_id = aws_api_gateway_rest_api.payoneer_webhooks_payee_api.id
  path_part   = "{proxy+}"
}

# API Gateway Resources method. /{proxy+}, ANY
resource "aws_api_gateway_method" "payoneer_webhooks_payee_api_method" {
  # checkov:skip=CKV_AWS_59:Access to public API Gateway methods is limited by IP addresses.
  # checkov:skip=CKV2_AWS_53:can be ignored because the validation is being handled in the lambda function
  resource_id = aws_api_gateway_resource.payoneer_webhooks_payee_api_resource_webhooks.id
  rest_api_id = aws_api_gateway_rest_api.payoneer_webhooks_payee_api.id

  http_method   = "POST"
  authorization = "NONE"
}

resource "aws_api_gateway_integration" "payoneer_webhooks_payee_integration" {
  http_method             = aws_api_gateway_method.payoneer_webhooks_payee_api_method.http_method
  resource_id             = aws_api_gateway_resource.payoneer_webhooks_payee_api_resource_webhooks.id
  rest_api_id             = aws_api_gateway_rest_api.payoneer_webhooks_payee_api.id
  type                    = "AWS_PROXY"
  integration_http_method = "POST"
  uri                     = module.lambda_documents_payoneer_webhooks_payee.lambda_invoke_arn
}

resource "aws_api_gateway_deployment" "payoneer_webhooks_payee_deployment" {
  rest_api_id = aws_api_gateway_rest_api.payoneer_webhooks_payee_api.id

  triggers = {
    redeployment = sha1(jsonencode([
      aws_api_gateway_resource.payoneer_webhooks_payee_api_resource_webhooks.id,
      aws_api_gateway_method.payoneer_webhooks_payee_api_method.id,
      aws_api_gateway_integration.payoneer_webhooks_payee_integration.id,
      aws_api_gateway_rest_api_policy.payoneer_webhooks_payee_api_policy.id,
      aws_api_gateway_rest_api_policy.payoneer_webhooks_payee_api_policy.policy,
      "Bump this up to force a re-deploy: 4"
    ]))
  }

  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_api_gateway_stage" "api_gateway_stage" {
  # checkov:skip=CKV2_AWS_51:isn't relevant because the backend is a lambda function
  # checkov:skip=CKV2_AWS_77:Ensure AWS API Gateway Rest API attached WAFv2 WebACL is configured with AMR for Log4j Vulnerability
  deployment_id = aws_api_gateway_deployment.payoneer_webhooks_payee_deployment.id
  rest_api_id   = aws_api_gateway_rest_api.payoneer_webhooks_payee_api.id
  stage_name    = "payoneer_webhooks_payee"

  access_log_settings {
    destination_arn = aws_cloudwatch_log_group.payoneer_webhooks_payee_log_group.arn
    format = jsonencode({
      "requestId" : "$context.requestId",
      "ip" : "$context.identity.sourceIp",
      "caller" : "$context.identity.caller",
      "user" : "$context.identity.user",
      "requestTime" : "$context.requestTime",
      "httpMethod" : "$context.httpMethod",
      "resourcePath" : "$context.resourcePath",
      "status" : "$context.status",
      "protocol" : "$context.protocol",
      "responseLength" : "$context.responseLength",
      "integrationErrorMessage" : "$context.integrationErrorMessage"
    })
  }

  tags = local.tags
}

resource "aws_lambda_permission" "payoneer_webhooks_payee_api_gateway_permission" {
  statement_id  = "AllowExecutionFromAPIGateway"
  action        = "lambda:InvokeFunction"
  function_name = module.lambda_documents_payoneer_webhooks_payee.lambda_arn
  principal     = "apigateway.amazonaws.com"
  source_arn    = "${aws_api_gateway_rest_api.payoneer_webhooks_payee_api.execution_arn}/*"
}

resource "aws_cloudwatch_log_group" "payoneer_webhooks_payee_log_group" {
  name = "/aws/apigateway/${var.environment}-${var.service_base_name}-api"

  retention_in_days = 365
  tags              = local.tags
}

data "aws_acm_certificate" "tls_cert" {
  domain   = var.acm_certificate_domain
  statuses = ["ISSUED"]
}

resource "aws_api_gateway_domain_name" "domain_name" {
  domain_name              = "${var.environment}-${var.service_base_name}.${data.aws_route53_zone.route53_zone.name}"
  regional_certificate_arn = data.aws_acm_certificate.tls_cert.arn
  security_policy          = "TLS_1_2"

  endpoint_configuration {
    types = ["REGIONAL"]
  }

  tags = local.tags
}

resource "aws_api_gateway_base_path_mapping" "path_mapping" {
  api_id      = aws_api_gateway_rest_api.payoneer_webhooks_payee_api.id
  stage_name  = aws_api_gateway_stage.api_gateway_stage.stage_name
  domain_name = aws_api_gateway_domain_name.domain_name.domain_name
}

data "aws_route53_zone" "route53_zone" {
  name = var.route53_zone_name
}

data "aws_route53_zone" "route53_zone_networking" {
  provider = aws.networking
  name     = "theorchard.io"
}

resource "aws_route53_record" "payoneer_webhooks_payee_api_route53_record" {
  name    = aws_api_gateway_domain_name.domain_name.domain_name
  type    = "A"
  zone_id = data.aws_route53_zone.route53_zone.id

  alias {
    evaluate_target_health = true
    name                   = aws_api_gateway_domain_name.domain_name.regional_domain_name
    zone_id                = aws_api_gateway_domain_name.domain_name.regional_zone_id
  }
}

resource "aws_route53_record" "payoneer_webhooks_payee_api_route53_record_networking" {
  provider = aws.networking
  name     = aws_api_gateway_domain_name.domain_name.domain_name
  type     = "A"
  zone_id  = data.aws_route53_zone.route53_zone_networking.id

  alias {
    evaluate_target_health = true
    name                   = aws_api_gateway_domain_name.domain_name.regional_domain_name
    zone_id                = aws_api_gateway_domain_name.domain_name.regional_zone_id
  }
}

resource "aws_api_gateway_method_settings" "all" {
  rest_api_id = aws_api_gateway_rest_api.payoneer_webhooks_payee_api.id
  stage_name  = aws_api_gateway_stage.api_gateway_stage.stage_name
  method_path = "*/*"

  settings {
    metrics_enabled        = true
    logging_level          = "ERROR"
    throttling_burst_limit = 10000
    throttling_rate_limit  = 5000
    cache_data_encrypted   = true
  }
}

module "m2m_secrets" {
  source             = "git@github.com:theorchard/terraform-secrets-manager.git//modules/auth0m2m?ref=1.6.1"
  environment        = var.environment
  service_name       = var.service_full_name
  application_family = var.application_family
}
