#!/bin/bash
# modules/aws-utils.sh - AWS-specific operations (S3, CloudFormation, Lambda)

# Check CloudFormation stack status
function check_stack_status() {
  local stack_name="$1"
  
  # Check if stack exists and get its status
  local stack_info
  if stack_info=$(aws cloudformation describe-stacks --stack-name "$stack_name" --region "$AWS_REGION" 2>/dev/null); then
    local stack_status=$(echo "$stack_info" | grep '"StackStatus"' | head -1 | cut -d'"' -f4)
    echo "$stack_status"
    return 0
  else
    echo "DOES_NOT_EXIST"
    return 1
  fi
}

# Wait for CloudFormation stack operation to complete
function wait_for_stack_operation() {
  local stack_name="$1"
  local operation="$2"  # "create" or "update"
  
  echo "${STATUS_TIMER} Waiting for stack $operation to complete..."
  
  local timeout=$STACK_OPERATION_TIMEOUT
  local elapsed=0
  local check_interval=30
  
  while [[ $elapsed -lt $timeout ]]; do
    local status=$(check_stack_status "$stack_name")
    
    case "$status" in
      "CREATE_COMPLETE"|"UPDATE_COMPLETE")
        print_success "Stack $operation completed successfully"
        return 0
        ;;
      "CREATE_FAILED"|"UPDATE_FAILED"|"ROLLBACK_COMPLETE"|"UPDATE_ROLLBACK_COMPLETE")
        print_error "Stack $operation failed with status: $status"
        echo ""
        echo "${STATUS_ANALYZE} Checking stack events for error details..."
        aws cloudformation describe-stack-events \
          --stack-name "$stack_name" \
          --region "$AWS_REGION" \
          --query 'StackEvents[?ResourceStatus==`CREATE_FAILED` || ResourceStatus==`UPDATE_FAILED`].[Timestamp,ResourceType,LogicalResourceId,ResourceStatusReason]' \
          --output table 2>/dev/null || echo "Could not retrieve stack events"
        return 1
        ;;
      "CREATE_IN_PROGRESS"|"UPDATE_IN_PROGRESS"|"UPDATE_COMPLETE_CLEANUP_IN_PROGRESS")
        echo "${STATUS_RELOAD} Stack $operation in progress... ($elapsed/${timeout}s)"
        ;;
      "ROLLBACK_IN_PROGRESS"|"UPDATE_ROLLBACK_IN_PROGRESS")
        print_warning "Stack $operation rolling back... ($elapsed/${timeout}s)"
        ;;
      *)
        echo "${STATUS_DATA} Stack status: $status ($elapsed/${timeout}s)"
        ;;
    esac
    
    sleep $check_interval
    elapsed=$((elapsed + check_interval))
  done
  
  print_error "Stack $operation timed out after $timeout seconds"
  return 1
}

# Package Lambda function into zip file
function package_lambda() {
  local lambda_dir="${LAMBDA_SOURCE_DIR:-$DEFAULT_LAMBDA_DIR}"
  local zip_file="/tmp/lambda-${RANDOM}.zip"
  
  echo "${STATUS_PACKAGE} Creating deployment package..."
  if ! (cd "$lambda_dir" && zip -r "$zip_file" . -x "*.git*" "node_modules/.cache/*" "*.DS_Store*" 2>/dev/null); then
    print_error "Failed to create Lambda package"
    rm -f "$zip_file"
    return 1
  fi
  
  # Check package size
  local zip_size=$(stat -f%z "$zip_file" 2>/dev/null || stat -c%s "$zip_file" 2>/dev/null || echo "0")
  local zip_size_mb=$((zip_size / 1024 / 1024))
  
  if [[ $zip_size -eq 0 ]]; then
    print_error "Lambda package is empty"
    rm -f "$zip_file"
    return 1
  fi
  
  if [[ $zip_size_mb -gt $LAMBDA_SIZE_LIMIT_MB ]]; then
    print_warning "Lambda package is ${zip_size_mb}MB (AWS limit: ${LAMBDA_SIZE_LIMIT_MB}MB)"
  else
    echo "${STATUS_DATA} Package size: ${zip_size_mb}MB"
  fi
  
  echo "$zip_file"
  return 0
}

# Upload Lambda package to S3
function upload_lambda_to_s3() {
  local zip_file="$1"
  local s3_key="$2"
  
  echo "${STATUS_UPLOAD} Uploading to s3://$BUCKET_NAME/$s3_key"
  
  # Upload with detailed error handling
  local upload_output
  if upload_output=$(aws s3 cp "$zip_file" "s3://$BUCKET_NAME/$s3_key" --region "$AWS_REGION" 2>&1); then
    print_success "Lambda package uploaded successfully"
    return 0
  else
    print_error "Failed to upload Lambda package to S3"
    echo "${STATUS_ANALYZE} Upload error details:"
    echo "$upload_output"
    return 1
  fi
}

# Package and upload Lambda function
function package_and_upload_lambda() {
  local lambda_dir="${LAMBDA_SOURCE_DIR:-$DEFAULT_LAMBDA_DIR}"
  local s3_key=$(build_lambda_s3_key)
  
  echo "${STATUS_PACKAGE} Packaging Lambda function from: $lambda_dir"
  
  # Validate Lambda directory
  if ! validate_lambda_directory; then
    return 1
  fi
  
  # Validate S3 setup before packaging
  if ! validate_s3_setup; then
    return 1
  fi
  
  # Package Lambda
  local zip_file=$(package_lambda)
  if [[ $? -ne 0 ]]; then
    return 1
  fi
  
  # Upload to S3
  if upload_lambda_to_s3 "$zip_file" "$s3_key"; then
    # Update environment variables
    update_env_var "LAMBDA_S3_KEY" "$s3_key"
    
    # Use tag as version if on tagged commit, otherwise use commit hash
    local version_id
    if [[ "$DEPLOY_ON_TAGS" == "true" ]] && is_on_tagged_commit; then
      version_id="$(get_latest_tag)"
    else
      version_id="$(get_git_commit)"
    fi
    
    update_env_var "VERSION" "$version_id"
    update_env_var "GIT_COMMIT" "$(git rev-parse HEAD)"
    update_env_var "GIT_BRANCH" "$(get_git_branch)"
    
    # Add tag info if available
    local latest_tag=$(get_latest_tag)
    if [[ -n "$latest_tag" ]]; then
      update_env_var "GIT_TAG" "$latest_tag"
    fi
    
    # Clean up temp file
    rm -f "$zip_file"
    return 0
  else
    rm -f "$zip_file"
    return 1
  fi
}

# Parse CloudFormation deployment errors
function parse_cfn_deployment_error() {
  local deploy_output="$1"
  
  if echo "$deploy_output" | grep -q "No changes to deploy"; then
    print_info "This is actually success - no changes were needed"
    return 0
  elif echo "$deploy_output" | grep -q "ValidationError"; then
    echo "${STATUS_CONFIG} Template validation error:"
    echo "   → Check your CloudFormation template syntax"
    echo "   → Verify all required parameters are provided"
    echo "   → Run: aws cloudformation validate-template --template-body file://$TEMPLATE_FILE"
  elif echo "$deploy_output" | grep -q "AlreadyExistsException"; then
    echo "${STATUS_CONFIG} Stack already exists in CREATE_FAILED state:"
    echo "   → Delete failed stack: aws cloudformation delete-stack --stack-name $STACK_NAME"
    echo "   → Wait for deletion: aws cloudformation wait stack-delete-complete --stack-name $STACK_NAME"
    echo "   → Then re-run this script"
  elif echo "$deploy_output" | grep -q "AccessDenied\|Forbidden"; then
    echo "${STATUS_CONFIG} Permission error:"
    echo "   → Check AWS credentials: aws sts get-caller-identity"
    echo "   → Ensure CloudFormation permissions: cloudformation:*"
    echo "   → Check resource-specific permissions (Lambda, S3, etc.)"
  elif echo "$deploy_output" | grep -q "LimitExceeded"; then
    echo "${STATUS_CONFIG} AWS service limits exceeded:"
    echo "   → Check AWS service quotas in the console"
    echo "   → You may need to request limit increases"
  else
    echo "${STATUS_CONFIG} General troubleshooting:"
    echo "   → Check stack events: aws cloudformation describe-stack-events --stack-name $STACK_NAME"
    echo "   → Review template parameters and resources"
    echo "   → Verify all dependencies exist (VPCs, subnets, etc.)"
  fi
  
  return 1
}