############################################
# IAM role
############################################
module "role" {
  source = "../lambda_execution_role"
  name   = "${var.name}-lambda-${var.stage}"
}

############################################
# Cloudwatch log group
############################################
resource "aws_cloudwatch_log_group" "api_logs" {
  name              = "/aws/apigateway/${var.name}-${var.stage}"
  retention_in_days = 14
}

############################################
# Install python packages
############################################
resource "null_resource" "pip_install" {
  count = var.requirements_file != null ? 1 : 0

  triggers = {
    always_run = timestamp()
  }

  provisioner "local-exec" {
    command = "pip install -r ${var.requirements_file} -t ${var.source_dir} --platform manylinux2014_x86_64 --implementation cp --python-version 3.11 --only-binary=:all: --upgrade"
  }
}

############################################
# Zip the source code
############################################
data "archive_file" "this" {
  depends_on  = [null_resource.pip_install]
  type        = "zip"
  source_dir  = var.source_dir
  output_path = "${path.module}/lambda_package.zip"
  excludes    = var.zip_excludes
}

############################################
# Upload zip to S3
############################################
resource "aws_s3_object" "lambda_zip" {
  bucket = var.artifact_bucket
  key    = "env:/${var.stage}/${var.name}.zip"
  source = data.archive_file.this.output_path
  etag   = data.archive_file.this.output_md5
}

############################################
# Lambda
############################################
module "lambda" {
  source = "../lambda_service_zip"

  name             = "${var.name}-${var.stage}"
  role_arn         = module.role.role_arn
  s3_bucket        = var.artifact_bucket
  s3_key           = aws_s3_object.lambda_zip.key
  source_code_hash = data.archive_file.this.output_base64sha256
  handler          = var.handler
  runtime          = var.runtime
  timeout          = var.timeout
  memory_size      = var.memory_size
  environment      = var.environment
}

############################################
# API Gateway
############################################
resource "aws_apigatewayv2_api" "this" {
  name          = "${var.name}-api-${var.stage}"
  protocol_type = "HTTP"
}

resource "aws_apigatewayv2_stage" "this" {
  api_id      = aws_apigatewayv2_api.this.id
  name        = "$default"
  auto_deploy = true

  access_log_settings {
    destination_arn = aws_cloudwatch_log_group.api_logs.arn

    format = jsonencode({
      requestId  = "$context.requestId"
      domainName = "$context.domainName"
      path       = "$context.path"
      status     = "$context.status"
      sourceIp   = "$context.identity.sourceIp"
      userAgent  = "$context.identity.userAgent"
    })
  }
}

resource "aws_apigatewayv2_integration" "this" {
  api_id                 = aws_apigatewayv2_api.this.id
  integration_type       = "AWS_PROXY"
  integration_uri        = module.lambda.lambda_arn
  payload_format_version = "2.0"
}

resource "aws_apigatewayv2_route" "catch_all" {
  api_id    = aws_apigatewayv2_api.this.id
  route_key = "$default"
  target    = "integrations/${aws_apigatewayv2_integration.this.id}"
}

resource "aws_lambda_permission" "apigw_invoke" {
  statement_id  = "AllowAPIGatewayInvoke"
  action        = "lambda:InvokeFunction"
  function_name = module.lambda.lambda_arn
  principal     = "apigateway.amazonaws.com"
  source_arn    = "${aws_apigatewayv2_api.this.execution_arn}/*/*"
}
