########################################
## Adjustment File Ingestion Workflow ##
########################################

# Data sources for adjustment file lambda functions
data "aws_lambda_function" "adj_init" {
  function_name = "${var.environment}-lambda-abacus-adjustment-file-initialize"
}

data "aws_lambda_function" "adj_prep" {
  function_name = "${var.environment}-lambda-abacus-adjustment-file-prepare"
}

data "aws_lambda_function" "adj_proc" {
  function_name = "${var.environment}-lambda-abacus-adjustment-file-process-batch"
}

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

resource "aws_sfn_state_machine" "adjustment_file_workflow" {
  name     = "${var.environment}-adjustment-file-workflow"
  role_arn = aws_iam_role.file_upload_workflow_role.arn # Reusing existing role for simplicity

  definition = jsonencode({
    Comment = "Adjustment File Ingestion Workflow using Distributed Map"
    StartAt = "InitializeBatch"
    States = {
      InitializeBatch = {
        Type = "Task"
        Resource = data.aws_lambda_function.adj_init.arn
        TimeoutSeconds = 30
        ResultPath = "$.lambdaResult"
        Retry = [
          {
            ErrorEquals = ["Lambda.ServiceException", "Lambda.TooManyRequestsException", "Lambda.SdkClientException", "TransientError"]
            IntervalSeconds = 2
            MaxAttempts = 3
            BackoffRate = 2.0
          }
        ]
        Catch = [
             {
                ErrorEquals = ["States.ALL"]
                ResultPath = "$.error"
                Next = "WorkflowFailed"
             }
        ]
        Next = "ReshapeAfterInit"
      }
      ReshapeAfterInit = {
        Type = "Pass"
        Parameters = {
          "source.$" = "$.source"
          "resources.$" = "$.resources"
          "id.$" = "$.id"
          "time.$" = "$.time"
          "region.$" = "$.region"
          "account.$" = "$.account"
          "detail-type.$" = "$.lambdaResult.detail_type"
          "detail.$" = "$.lambdaResult.detail"
        }
        Next = "PrepareFile"
      }
      PrepareFile = {
        Type = "Task"
        Resource = data.aws_lambda_function.adj_prep.arn
        TimeoutSeconds = 300
        ResultPath = "$.lambdaResult"
        Retry = [
          {
            ErrorEquals = ["Lambda.ServiceException", "Lambda.TooManyRequestsException", "Lambda.SdkClientException", "TransientError"]
            IntervalSeconds = 2
            MaxAttempts = 3
            BackoffRate = 2.0
          }
        ]
        Catch = [
             {
                ErrorEquals = ["States.ALL"]
                ResultPath = "$.error"
                Next = "WorkflowFailed"
             }
        ]
        Next = "ReshapeAfterPrepare"
      }
      ReshapeAfterPrepare = {
        Type = "Pass"
        Parameters = {
          "source.$" = "$.source"
          "resources.$" = "$.resources"
          "id.$" = "$.id"
          "time.$" = "$.time"
          "region.$" = "$.region"
          "account.$" = "$.account"
          "detail-type.$" = "$.lambdaResult.detail_type"
          "detail.$" = "$.lambdaResult.detail"
        }
        Next = "DistributedBatchProcessing"
      }
      DistributedBatchProcessing = {
        Type = "Map"
        MaxConcurrency = 5
        ItemReader = {
          ReaderConfig = {
            InputType = "CSV"
            CSVHeaderLocation = "FIRST_ROW"
          }
          Resource = "arn:aws:states:::s3:getObject"
          Parameters = {
            "Bucket" = "$.detail.data.s3_bucket"
            "Key" = "$.detail.data.s3_key"
          }
        }
        # ItemBatcher = {
        #   MaxItemsPerBatch = 100000  # 100K rows per batch
        #   MaxInputBytesPerBatch = 268435456  # 256MB (Maximum allowed)
        #   BatchInput = {
        #       "$" = "$"
        #     }
        #   }
        # ResultWriter = {
        #   Resource = "arn:aws:states:::s3:putObject"
        #   Parameters = {
        #     Bucket = aws_s3_bucket.abacus_adjustments.id
        #     Prefix = "batches/"
        #   }
        # }
        ItemProcessor = {
          ProcessorConfig = {
            Mode = "DISTRIBUTED"
            ExecutionType = "STANDARD"
          }
          StartAt = "ProcessBatch"
          States = {
            ProcessBatch = {
              Type = "Task"
              Resource = data.aws_lambda_function.adj_proc.arn
              TimeoutSeconds = 300
              Retry = [
                {
                    ErrorEquals = ["Lambda.ServiceException", "Lambda.TooManyRequestsException", "Lambda.SdkClientException", "TransientError"]
                    IntervalSeconds = 2
                    MaxAttempts = 3
                    BackoffRate = 2.0
                }
              ]
              End = true
            }
          }
        }
        Label = "ProcessBatches"
        ResultPath = "$.mapResult"
        Catch = [
             {
                ErrorEquals = ["States.ALL"]
                ResultPath = "$.error"
                Next = "WorkflowFailed"
             }
        ]
        Next = "CompleteBatch"
      }
      CompleteBatch = {
        Type = "Task"
        Resource = data.aws_lambda_function.adj_comp.arn
        TimeoutSeconds = 60
        ResultPath = "$.lambdaResult"
        Retry = [
          {
            ErrorEquals = ["Lambda.ServiceException", "Lambda.TooManyRequestsException", "Lambda.SdkClientException", "TransientError"]
            IntervalSeconds = 2
            MaxAttempts = 3
            BackoffRate = 2.0
          }
        ]
        Catch = [
             {
                ErrorEquals = ["States.ALL"]
                ResultPath = "$.error"
                Next = "WorkflowFailed"
             }
        ]
        Next = "ReshapeAfterComplete"
      }
      ReshapeAfterComplete = {
        Type = "Pass"
        Parameters = {
          "source.$" = "$.source"
          "resources.$" = "$.resources"
          "id.$" = "$.id"
          "time.$" = "$.time"
          "region.$" = "$.region"
          "account.$" = "$.account"
          "detail-type.$" = "$.lambdaResult.detail_type"
          "detail.$" = "$.lambdaResult.detail"
        }
        End = true
      }
      WorkflowFailed = {
        Type = "Fail"
        Cause = "Workflow failed"
        Error = "WorkflowError"
      }
    }
  })

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

  tracing_configuration {
    enabled = true
  }

  tags = local.common_tags
}
