########################
## abacus-file-upload ##
########################

# Data sources for existing lambda functions
data "aws_lambda_function" "av_scan" {
  function_name = "${var.environment}-lambda-av-scan-containerized"
}

data "aws_lambda_function" "file_upload_complete" {
  function_name = "${var.environment}-lambda-abacus-file-upload-complete"
}

data "aws_lambda_function" "file_upload_initialize" {
  function_name = "${var.environment}-lambda-abacus-file-upload-initialize"
}

# CloudWatch Log Group for Step Functions
resource "aws_cloudwatch_log_group" "abacus_file_upload_workflow_logs" {
  name              = "/aws/vendedlogs/states/${var.environment}-abacus-file-upload-workflow"
  retention_in_days = 365 # 1 year retention required

  tags = {
    application_family = var.application_family
    environment        = var.environment
    service_name       = var.service_name
    terraformed        = true
  }
}

# Step Functions state machine
resource "aws_sfn_state_machine" "abacus_file_upload_workflow" {
  name     = "${var.environment}-abacus-file-upload-workflow"
  role_arn = aws_iam_role.abacus_file_upload_workflow_role.arn

  definition = jsonencode({
    Comment        = "File upload workflow with AV scan and completion handler"
    TimeoutSeconds = 1200 # 20 minutes overall timeout for entire workflow
    StartAt        = "FileUploadInitialize"
    States = {
      FileUploadInitialize = {
        Type           = "Task"
        Resource       = data.aws_lambda_function.file_upload_initialize.arn
        TimeoutSeconds = 900
        ResultPath     = "$"  # Pass the output of file_upload_initialize lambda to AVScan lambda
        Retry = [
          {
            ErrorEquals     = ["Lambda.ServiceException", "Lambda.TooManyRequestsException", "Lambda.SdkClientException"]
            IntervalSeconds = 2
            MaxAttempts     = 3
            BackoffRate     = 2.0
          },
          {
            ErrorEquals     = ["States.TaskFailed", "States.Timeout"]
            IntervalSeconds = 1
            MaxAttempts     = 2
            BackoffRate     = 1.5
          }
        ]
        Catch = [
          {
            ErrorEquals = ["States.ALL"]
            ResultPath  = "$.error"
            Next        = "FileUploadInitializeFailed"
          }
        ]
        Next = "AVScan"
      }
      AVScan = {
        Type           = "Task"
        Resource       = data.aws_lambda_function.av_scan.arn
        InputPath      = "$"
        TimeoutSeconds = 900              # 15 minutes for AV scan
        ResultPath     = "$.avScanResult" # Store AV scan result in avScanResult field
        Retry = [
          {
            ErrorEquals     = ["Lambda.ServiceException", "Lambda.TooManyRequestsException", "Lambda.SdkClientException"]
            IntervalSeconds = 2
            MaxAttempts     = 3
            BackoffRate     = 2.0
          },
          {
            ErrorEquals     = ["States.TaskFailed", "States.Timeout"]
            IntervalSeconds = 1
            MaxAttempts     = 2
            BackoffRate     = 1.5
          }
        ]
        Catch = [
          {
            ErrorEquals = ["States.ALL"]
            ResultPath  = "$.error"
            Next        = "AVScanFailed"
          }
        ]
        Next = "CheckScanResult"
      }
      CheckScanResult = {
        Type = "Choice"
        Choices = [
          {
            Variable      = "$.avScanResult.has_virus"
            BooleanEquals = true
            Next          = "SetQuarantineAction"
          }
        ]
        Default = "FileUploadComplete"
      }
      SetQuarantineAction = {
        Type       = "Pass"
        Result     = "quarantine"
        ResultPath = "$.action"
        Next       = "FileUploadComplete"
      }
      FileUploadComplete = {
        Type           = "Task"
        Resource       = data.aws_lambda_function.file_upload_complete.arn
        TimeoutSeconds = 60 # 1 minute for file upload completion
        Retry = [
          {
            ErrorEquals     = ["Lambda.ServiceException", "Lambda.TooManyRequestsException", "Lambda.SdkClientException"]
            IntervalSeconds = 2
            MaxAttempts     = 3
            BackoffRate     = 2.0
          },
          {
            ErrorEquals     = ["States.TaskFailed", "States.Timeout"]
            IntervalSeconds = 1
            MaxAttempts     = 2
            BackoffRate     = 1.5
          }
        ]
        Catch = [
          {
            ErrorEquals = ["States.ALL"]
            ResultPath  = "$.error"
            Next        = "FileUploadFailed"
          }
        ]
        End = true
      }
      AVScanFailed = {
        Type  = "Fail"
        Cause = "AV scan failed after retries"
        Error = "AVScanError"
      }
      FileUploadFailed = {
        Type  = "Fail"
        Cause = "File upload completion failed after retries"
        Error = "FileUploadCompletionError"
      }
      FileUploadInitializeFailed = {
        Type = "Fail"
        Cause = "File upload initialization failed after retries"
        Error = "FileUploadInitializeError"
      }
    }
  })

  logging_configuration {
    log_destination        = "${aws_cloudwatch_log_group.abacus_file_upload_workflow_logs.arn}:*"
    include_execution_data = true
    level                  = "ALL"
  }

  tracing_configuration {
    enabled = true
  }

  tags = {
    application_family = var.application_family
    environment        = var.environment
    service_name       = var.service_name
    terraformed        = true
  }
}
