#!/bin/bash

# AWS Lambda Layer CLI Tool
# Install: sudo ./scripts/install.sh
# Usage: aws-lambda-layer-cli zip --nodejs express,axios -n my-layer

set -e
set -u

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
MAGENTA='\033[0;35m'
CYAN='\033[0;36m'
WHITE='\033[0;37m'
NC='\033[0m' # No Color

# Styles
BOLD='\033[1m'
ITALIC='\033[3m'
UNDERLINE='\033[4m'
REVERSE='\033[7m'
STRIKETHROUGH='\033[9m'

# Paths
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
INSTALL_DIR="/usr/local/lib/aws-lambda-layer-cli"

# Determine script locations (prefer relative to script, fallback to global install)
if [ -f "$SCRIPT_DIR/create_nodejs_layer.sh" ]; then
    NODE_SCRIPT="$SCRIPT_DIR/create_nodejs_layer.sh"
else
    NODE_SCRIPT="$INSTALL_DIR/create_nodejs_layer.sh"
fi

if [ -f "$SCRIPT_DIR/create_python_layer.sh" ]; then
    PYTHON_SCRIPT="$SCRIPT_DIR/create_python_layer.sh"
else
    PYTHON_SCRIPT="$INSTALL_DIR/create_python_layer.sh"
fi

BIN_DIR="/usr/local/bin"
COMPLETION_DIR="/etc/bash_completion.d"

# Show help
show_help() {
    local version_file="$SCRIPT_DIR/VERSION.txt"
    local version="1.4.1"
    if [ -f "$version_file" ]; then
        version=$(cat "$version_file")
    fi
    printf "${BLUE}${BOLD}AWS Lambda Layer CLI Tool - ${version}${NC}\n\n"
    
    printf "${BLUE}Usage:${NC}\n"
    printf "  aws-lambda-layer-cli ${GREEN}zip${NC} ${YELLOW}--nodejs${NC} <packages> [options]\n"
    printf "  aws-lambda-layer-cli ${GREEN}zip${NC} ${YELLOW}--python${NC} <packages> [options]\n"
    printf "  aws-lambda-layer-cli ${GREEN}publish${NC} ${YELLOW}--nodejs${NC} <packages> [options]\n"
    printf "  aws-lambda-layer-cli ${GREEN}publish${NC} ${YELLOW}--python${NC} <packages> [options]\n"
    printf "  aws-lambda-layer-cli ${GREEN}help${NC}\n"
    printf "  aws-lambda-layer-cli [options]\n\n"
    
    printf "${BLUE}Commands:${NC}\n"
    printf "  ${GREEN}zip${NC}            Create and package a Lambda layer as zip file\n"
    printf "  ${GREEN}publish${NC}        Create and publish a Lambda layer to AWS (uses IAM credentials)\n"
    printf "  ${GREEN}completion${NC}     Generate shell completion scripts\n"
    printf "  ${GREEN}uninstall${NC}      Uninstall the tool and remove all files\n"
    printf "  ${GREEN}help${NC}           Show this help message\n\n"
    
    printf "${BLUE}Runtime Options:${NC}\n"
    printf "  ${YELLOW}--nodejs, --node, -n${NC}    Create a Node.js Lambda layer\n"
    printf "  ${YELLOW}--python, --py, -p${NC}      Create a Python Lambda layer\n"
    printf "  ${YELLOW}--runtime=RUNTIME${NC}       Specify runtime (nodejs or python)\n"
    printf "${BLUE}Arguments:${NC}\n"
    printf "  <packages>              Comma-separated list of packages with optional versions (required)\n"

    printf "${BLUE}Common Options:${NC}\n"
    printf "  ${YELLOW}--name${NC}                  Name for the output zip file / layer name\n"
    printf "  ${YELLOW}--description${NC}           Description for the layer (publish command only)\n"
    printf "${BLUE}AWS Options (publish command only):${NC}\n"
    printf "  ${YELLOW}--profile${NC}               AWS CLI profile to use (default: default profile)\n"
    printf "  ${YELLOW}--region${NC}                AWS region (e.g., us-east-1, ap-east-1)\n"
    printf "${BLUE}Other Options:${NC}\n"
    printf "  ${YELLOW}--version, -v${NC}           Show tool version information\n"
    printf "  ${YELLOW}--node-version${NC}          Node.js version (default: 24)\n"
    printf "  ${YELLOW}--python-version${NC}        Python version (default: 3.14)\n"
    printf "  ${YELLOW}--no-uv${NC}                 Use pip/venv instead of uv\n\n"
    
    printf "${MAGENTA}${UNDERLINE}Package Version Examples:${NC}\n"
    printf "  Node.js:    express@^4.0.0, lodash@~4.17.0, axios@>=1.6.0\n"
    printf "  Python:     numpy==1.26.0, pandas>=2.1.0, requests~=2.31.0\n\n"
    
    printf "${MAGENTA}${UNDERLINE}Examples:${NC}\n"
    printf "  aws-lambda-layer-cli ${GREEN}zip${NC} ${YELLOW}--nodejs${NC} express,lodash\n"
    printf "  aws-lambda-layer-cli ${GREEN}zip${NC} ${YELLOW}--python${NC} \"numpy==1.26.0,pandas>=2.1.0\"\n"
    printf "  aws-lambda-layer-cli ${GREEN}publish${NC} ${YELLOW}--nodejs${NC} express@4.18.2 ${YELLOW}--description${NC} \"Express layer\"\n"
    printf "  aws-lambda-layer-cli ${GREEN}publish${NC} ${YELLOW}--python${NC} numpy==1.26.0 ${YELLOW}--description${NC} \"NumPy layer\"\n"
    printf "  aws-lambda-layer-cli ${GREEN}publish${NC} ${YELLOW}--nodejs${NC} date-fns,uuid ${YELLOW}--name${NC} utility-layer ${YELLOW}--description${NC} \"Utility packages\"\n"
    printf "  aws-lambda-layer-cli ${GREEN}publish${NC} ${YELLOW}--nodejs${NC} express@4.18.2 ${YELLOW}--profile${NC} production ${YELLOW}--region${NC} ap-east-1 ${YELLOW}--description${NC} \"Express layer\"\n\n"
    
    printf "${YELLOW}${BOLD}Requirements for publish command:${NC}\n"
    printf "  - AWS CLI installed and configured\n"
    printf "  - IAM credentials with lambda:PublishLayerVersion permission\n"
    printf "  - Proper AWS region configuration\n"
}

# Show version
show_version() {
    local version_file="$SCRIPT_DIR/VERSION.txt"
    if [ -f "$version_file" ]; then
        local version=$(cat "$version_file")
        echo "v$version"
    else
        # Fallback if VERSION file is missing (e.g. during development or if moved)
        echo "v1.4.1"
    fi
}

# Check if AWS CLI is installed and configured
check_aws_cli() {
    local profile="$1"
    local region="$2"
    local aws_opts=()
    
    if ! command -v aws &> /dev/null; then
        printf "${RED}Error: AWS CLI is not installed${NC}\n"
        printf "Please install AWS CLI first:\n"
        printf "  https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html\n"
        return 1
    fi
    
    # Build AWS CLI options
    if [ -n "$profile" ]; then
        aws_opts+=("--profile" "$profile")
    fi
    if [ -n "$region" ]; then
        aws_opts+=("--region" "$region")
    fi
    
    # Check if AWS credentials are configured
    if ! aws ${aws_opts[@]+"${aws_opts[@]}"} sts get-caller-identity &> /dev/null; then
        printf "${RED}Error: AWS credentials not configured or invalid${NC}\n"
        if [ -n "$profile" ]; then
            printf "Profile: $profile\n"
        fi
        printf "Please configure AWS credentials:\n"
        printf "  aws configure"
        if [ -n "$profile" ]; then
            printf " --profile $profile"
        fi
        printf "\n"
        printf "  or set AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_DEFAULT_REGION environment variables\n"
        return 1
    fi
    
    return 0
}

# Get AWS account info
get_aws_account_info() {
    local profile="$1"
    local region="$2"
    local aws_opts=()
    
    # Build AWS CLI options
    if [ -n "$profile" ]; then
        aws_opts+=("--profile" "$profile")
    fi
    if [ -n "$region" ]; then
        aws_opts+=("--region" "$region")
    fi
    
    printf "${CYAN}Checking AWS account...${NC}\n"
    
    # Get account ID
    local account_id
    account_id=$(aws ${aws_opts[@]+"${aws_opts[@]}"} sts get-caller-identity --query Account --output text 2>/dev/null)
    if [ $? -eq 0 ]; then
        printf "  Account ID: ${GREEN}$account_id${NC}\n"
    else
        printf "  ${YELLOW}Could not retrieve account ID${NC}\n"
        account_id="UNKNOWN"
    fi
    
    # Display profile if specified
    if [ -n "$profile" ]; then
        printf "  Profile: ${GREEN}$profile${NC}\n"
    fi
    
    # Get account aliases
    local aliases
    aliases=$(aws ${aws_opts[@]+"${aws_opts[@]}"} iam list-account-aliases --query 'AccountAliases' --output text 2>/dev/null)
    if [ $? -eq 0 ] && [ -n "$aliases" ]; then
        printf "  Account Aliases: ${GREEN}$aliases${NC}\n"
    else
        printf "  ${YELLOW}No account aliases found${NC}\n"
    fi
    
    # Get region
    local display_region="$region"
    if [ -z "$display_region" ]; then
        if [ -n "$profile" ]; then
            display_region=$(aws ${aws_opts[@]+"${aws_opts[@]}"} configure get region 2>/dev/null)
        else
            display_region=$(aws configure get region 2>/dev/null || echo "$AWS_DEFAULT_REGION")
        fi
    fi
    if [ -n "$display_region" ]; then
        printf "  Region: ${GREEN}$display_region${NC}\n"
    else
        printf "  ${YELLOW}Region not configured${NC}\n"
    fi
    
    printf "\n"
    printf "${YELLOW}⚠️  This layer will be published to the AWS account above.${NC}\n"
    
    # Prompt user for confirmation
    read -p "Do you want to proceed? [Y/n]: " response
    response=${response:-Y}  # Default to Y if empty
    
    case "$response" in
        [Yy]|[Yy][Ee][Ss])
            printf "${GREEN}Proceeding with layer publication...${NC}\n\n"
            ;;
        *)
            printf "${RED}Publication cancelled.${NC}\n"
            exit 0
            ;;
    esac
}

# Determine compatible runtimes for AWS
get_compatible_runtimes() {
    local runtime="$1"
    local version="$2"
    
    case "$runtime" in
        nodejs)
            echo "nodejs${version}.x"
            ;;
        python)
            # AWS Lambda uses format like python3.14, not python3.14.x
            echo "python${version}"
            ;;
        *)
            echo ""
            ;;
    esac
}

# Check dependencies
check_dependencies() {
    local runtime="$1"
    
    # Check for zip
    if ! command -v zip &> /dev/null; then
        printf "${RED}Error: 'zip' command is not installed${NC}\n"
        printf "Please install zip first.\n"
        return 1
    fi
    
    # Check runtime
    if [ "$runtime" = "nodejs" ]; then
        if ! command -v node &> /dev/null; then
            printf "${RED}Error: 'node' command is not installed${NC}\n"
            printf "Please install Node.js first.\n"
            return 1
        fi
    elif [ "$runtime" = "python" ]; then
        if ! command -v python3 &> /dev/null && ! command -v python &> /dev/null; then
            printf "${RED}Error: 'python' command is not installed${NC}\n"
            printf "Please install Python first.\n"
            return 1
        fi
    fi
    return 0
}

# Zip command handler - creates local zip files
handle_zip() {
    local runtime=""
    local packages=""
    
    # Parse runtime flag
    case "${1:-}" in
        --nodejs|--node|-n)
            runtime="nodejs"
            shift
            ;;
        --python|--py|-p)
            runtime="python"
            shift
            ;;
        --runtime=*)
            runtime="${1#*=}"
            case "$runtime" in
                nodejs)
                    shift
                    ;;
                python)
                    shift
                    ;;
                *)
                    printf "${RED}Error: Invalid runtime specified: $runtime${NC}\n"
                    printf "Valid runtimes: nodejs, python\n"
                    exit 1
                    ;;
            esac
            ;;
        --runtime)
            if [[ -n "${2:-}" && "${2:-}" != -* ]]; then
                runtime="$2"
                shift 2
                case "$runtime" in
                    nodejs|python)
                        ;;
                    *)
                        printf "${RED}Error: Invalid runtime specified: $runtime${NC}\n"
                        printf "Valid runtimes: nodejs, python\n"
                        exit 1
                        ;;
                esac
            else
                printf "${RED}Error: --runtime requires an argument${NC}\n"
                printf "Example: --runtime=nodejs or --runtime python\n"
                exit 1
            fi
            ;;
        *)
            printf "${RED}Error: Missing or invalid runtime specification${NC}\n"
            printf "Use --nodejs, --node, -n for Node.js or --python, --py, -p for Python\n"
            printf "Or use --runtime=nodejs or --runtime=python\n"
            exit 1
            ;;
    esac
    
    # Get packages as first positional argument
    if [[ -n "${1:-}" && "${1:-}" != -* ]]; then
        packages="$1"
        shift
    else
        printf "${RED}Error: Missing packages argument${NC}\n"
        printf "Usage: aws-lambda-layer zip --nodejs <packages> [options]\n"
        printf "Example: aws-lambda-layer zip --nodejs express,axios\n"
        exit 1
    fi
    
    # Check dependencies
    if ! check_dependencies "$runtime"; then
        exit 1
    fi
    
    # Create output directory if it doesn't exist
    local output_dir="output"
    mkdir -p "$output_dir"
    
    # Save current directory and change to output directory
    local current_dir=$(pwd)
    cd "$output_dir"
    
    # Pass arguments to the appropriate script with -i
    if [ "$runtime" = "nodejs" ]; then
        if [ ! -f "$NODE_SCRIPT" ]; then
            cd "$current_dir"
            printf "${RED}Error: Node.js script not found at $NODE_SCRIPT${NC}\n"
            printf "Please run scripts/install.sh first\n"
            exit 1
        fi
        printf "${BLUE}Creating Node.js Lambda layer (local zip)...${NC}\n"
        bash "$NODE_SCRIPT" -i "$packages" "$@"
        local exit_code=$?
        cd "$current_dir"
        exit $exit_code
    elif [ "$runtime" = "python" ]; then
        if [ ! -f "$PYTHON_SCRIPT" ]; then
            cd "$current_dir"
            printf "${RED}Error: Python script not found at $PYTHON_SCRIPT${NC}\n"
            printf "Please run scripts/install.sh first\n"
            exit 1
        fi
        printf "${BLUE}Creating Python Lambda layer (local zip)...${NC}\n"
        bash "$PYTHON_SCRIPT" -i "$packages" "$@"
        local exit_code=$?
        cd "$current_dir"
        exit $exit_code
    fi
}

# Publish command handler - publishes layer directly to AWS
handle_publish() {
    local runtime=""
    local description=""
    local layer_name=""
    local packages=""
    local profile=""
    local region=""
    local args=()
    
    # Parse publish-specific arguments first
    local new_args=()
    while [[ $# -gt 0 ]]; do
        case "$1" in
            --description)
                if [[ -n "${2:-}" && "${2:-}" != -* ]]; then
                    description="$2"
                    shift 2
                else
                    printf "${RED}Error: --description requires an argument${NC}\n"
                    exit 1
                fi
                ;;
            --description=*)
                description="${1#*=}"
                shift
                ;;
            --name)
                if [[ -n "${2:-}" && "${2:-}" != -* ]]; then
                    layer_name="$2"
                    shift 2
                else
                    printf "${RED}Error: --name requires an argument${NC}\n"
                    exit 1
                fi
                ;;
            --name=*)
                layer_name="${1#*=}"
                shift
                ;;
            --profile)
                if [[ -n "${2:-}" && "${2:-}" != -* ]]; then
                    profile="$2"
                    shift 2
                else
                    printf "${RED}Error: --profile requires an argument${NC}\n"
                    exit 1
                fi
                ;;
            --profile=*)
                profile="${1#*=}"
                shift
                ;;
            --region)
                if [[ -n "${2:-}" && "${2:-}" != -* ]]; then
                    region="$2"
                    shift 2
                else
                    printf "${RED}Error: --region requires an argument${NC}\n"
                    exit 1
                fi
                ;;
            --region=*)
                region="${1#*=}"
                shift
                ;;
            *)
                new_args+=("$1")
                shift
                ;;
        esac
    done
    
    # Parse runtime flag from remaining arguments
    if [ ${#new_args[@]} -eq 0 ]; then
        set --
    else
        set -- "${new_args[@]}"
    fi

    case "${1:-}" in
        --nodejs|--node|-n)
            runtime="nodejs"
            shift
            ;;
        --python|--py|-p)
            runtime="python"
            shift
            ;;
        --runtime=*)
            runtime="${1#*=}"
            case "$runtime" in
                nodejs)
                    shift
                    ;;
                python)
                    shift
                    ;;
                *)
                    printf "${RED}Error: Invalid runtime specified: $runtime${NC}\n"
                    printf "Valid runtimes: nodejs, python\n"
                    exit 1
                    ;;
            esac
            ;;
        --runtime)
            if [[ -n "${2:-}" && "${2:-}" != -* ]]; then
                runtime="$2"
                shift 2
                case "$runtime" in
                    nodejs|python)
                        ;;
                    *)
                        printf "${RED}Error: Invalid runtime specified: $runtime${NC}\n"
                        printf "Valid runtimes: nodejs, python\n"
                        exit 1
                        ;;
                esac
            else
                printf "${RED}Error: --runtime requires an argument${NC}\n"
                printf "Example: --runtime=nodejs or --runtime python\n"
                exit 1
            fi
            ;;
        *)
            printf "${RED}Error: Missing or invalid runtime specification${NC}\n"
            printf "Use --nodejs, --node, -n for Node.js or --python, --py, -p for Python\n"
            printf "Or use --runtime=nodejs or --runtime=python\n"
            exit 1
            ;;
    esac
    
    # Get packages as first positional argument
    if [[ -n "${1:-}" && "${1:-}" != -* ]]; then
        packages="$1"
        shift
    else
        printf "${RED}Error: Missing packages argument${NC}\n"
        printf "Usage: aws-lambda-layer publish --nodejs <packages> [options]\n"
        printf "Example: aws-lambda-layer publish --nodejs express,axios --description \"My layer\"\n"
        exit 1
    fi
    
    # Check dependencies
    if ! check_dependencies "$runtime"; then
        exit 1
    fi
    
    # Check AWS CLI and credentials
    if ! check_aws_cli "$profile" "$region"; then
        exit 1
    fi
    
    # Show AWS account info and wait for confirmation
    get_aws_account_info "$profile" "$region"
    
    # Create output directory if it doesn't exist
    local output_dir="output"
    mkdir -p "$output_dir"
    
    # Save current directory and change to output directory
    local current_dir=$(pwd)
    cd "$output_dir"
    
    printf "${BLUE}Building Lambda layer in output directory...${NC}\n"
    
    # Build the layer using the appropriate script
    local build_args=("-i" "$packages")
    if [ -n "$layer_name" ]; then
        build_args+=("--name" "${layer_name}.zip")
    fi
    
    # Add remaining arguments
    for arg in "$@"; do
        build_args+=("$arg")
    done
    
    local zip_file=""
    if [ "$runtime" = "nodejs" ]; then
        if [ ! -f "$NODE_SCRIPT" ]; then
            cd "$current_dir"
            printf "${RED}Error: Node.js script not found${NC}\n"
            exit 1
        fi
        bash "$NODE_SCRIPT" "${build_args[@]}" 2>&1 | tee build.log
        
        # Check if build script succeeded
        if [ ${PIPESTATUS[0]} -ne 0 ]; then
            cd "$current_dir"
            printf "${RED}Error: Node.js layer build failed${NC}\n"
            printf "Check build log: $output_dir/build.log\n"
            exit 1
        fi
        
        # Extract zip file name from build output (just the filename, not full path)
        zip_file=$(grep -o "File: .*\.zip" "build.log" | cut -d' ' -f2 | tail -1)
        if [ -n "$zip_file" ]; then
            zip_file=$(basename "$zip_file")
        else
            # Try to find zip file in current directory
            zip_file=$(find . -maxdepth 1 -name "*.zip" -type f | head -1 | sed 's|^\./||')
        fi
        
        # Extract Node.js version for compatible runtimes
        local node_version=$(grep -o "Node.js version: [0-9.]*" "build.log" | cut -d' ' -f3 | tail -1)
        if [ -z "$node_version" ]; then
            node_version="24"
        fi
        local compatible_runtimes="nodejs${node_version}.x"
        
    elif [ "$runtime" = "python" ]; then
        if [ ! -f "$PYTHON_SCRIPT" ]; then
            cd "$current_dir"
            printf "${RED}Error: Python script not found${NC}\n"
            exit 1
        fi
        bash "$PYTHON_SCRIPT" "${build_args[@]}" 2>&1 | tee build.log
        
        # Check if build script succeeded
        if [ ${PIPESTATUS[0]} -ne 0 ]; then
            cd "$current_dir"
            printf "${RED}Error: Python layer build failed${NC}\n"
            printf "Check build log: $output_dir/build.log\n"
            exit 1
        fi
        
        # Extract zip file name from build output (just the filename, not full path)
        zip_file=$(grep -o "File: .*\.zip" "build.log" | cut -d' ' -f2 | tail -1)
        if [ -n "$zip_file" ]; then
            zip_file=$(basename "$zip_file")
        else
            # Try to find zip file in current directory
            zip_file=$(find . -maxdepth 1 -name "*.zip" -type f | head -1 | sed 's|^\./||')
        fi
        
        # Extract Python version for compatible runtimes
        local python_version=$(grep -o "Python: [0-9.]*" "build.log" | cut -d' ' -f2 | tail -1)
        if [ -z "$python_version" ]; then
            python_version="3.14"
        fi
        local compatible_runtimes="python${python_version}"
    fi
    
    # Check if zip file was created
    if [ -z "$zip_file" ] || [ ! -f "$zip_file" ]; then
        cd "$current_dir"
        printf "${RED}Error: Failed to create layer zip file${NC}\n"
        printf "Check build log: $output_dir/build.log\n"
        exit 1
    fi
    
    # Extract package info for layer naming and description
    local packages_info=""
    if [ "$runtime" = "nodejs" ]; then
        packages_info=$(grep -o "Installed packages: .*" "build.log" | cut -d' ' -f3- | tail -1)
    elif [ "$runtime" = "python" ]; then
        packages_info=$(grep -o "Installed packages: .*" "build.log" | cut -d' ' -f3- | tail -1)
    fi
    
    # Determine layer name - use just the first package name if not specified
    if [ -z "$layer_name" ]; then
        # Extract first package name from packages list
        local first_package=$(echo "$packages" | cut -d',' -f1)
        # Remove version specifiers to get just the package name
        if [ "$runtime" = "nodejs" ]; then
            # For Node.js: remove @version, handle scoped packages like @aws-sdk/client-s3
            layer_name=$(echo "$first_package" | sed 's/@[0-9^~<>=].*$//' | sed 's/^@//' | tr '/' '-')
        else
            # For Python: remove ==version, >=version, etc.
            layer_name=$(echo "$first_package" | sed 's/[=<>~!].*$//')
        fi
    fi
    
    # Determine description - use package name with version
    local final_description=""
    if [ -n "$description" ]; then
        final_description="$description - $packages_info"
    else
        final_description="$packages_info"
    fi
    
    # Limit description length (AWS limit is 256 characters)
    if [ ${#final_description} -gt 256 ]; then
        final_description="${final_description:0:253}..."
    fi
    
    printf "\n${CYAN}Publishing Lambda layer to AWS...${NC}\n"
    printf "  Layer name: ${GREEN}$layer_name${NC}\n"
    printf "  Description: ${GREEN}$final_description${NC}\n"
    printf "  Compatible runtimes: ${GREEN}$compatible_runtimes${NC}\n"
    printf "  Zip file: ${GREEN}$zip_file${NC}\n\n"
    
    # Confirm publish
    read -p "Do you want to publish this layer? [Y/n]: " confirm_publish
    confirm_publish=${confirm_publish:-Y}
    
    case "$confirm_publish" in
        [Yy]|[Yy][Ee][Ss])
            ;;
        *)
            printf "${YELLOW}Publishing cancelled.${NC}\n"
            exit 0
            ;;
    esac
    
    # Build AWS CLI options for publish
    local publish_aws_opts=()
    if [ -n "$profile" ]; then
        publish_aws_opts+=("--profile" "$profile")
    fi
    if [ -n "$region" ]; then
        publish_aws_opts+=("--region" "$region")
    fi
    
    # Publish the layer
    printf "${YELLOW}Executing: aws lambda publish-layer-version${NC}\n"
    if [ -n "$profile" ]; then
        printf "  --profile \"$profile\"\n"
    fi
    if [ -n "$region" ]; then
        printf "  --region \"$region\"\n"
    fi
    printf "  --layer-name \"$layer_name\"\n"
    printf "  --description \"$final_description\"\n"
    printf "  --zip-file \"fileb://$(convert_path "$current_dir/$output_dir/$zip_file")\"\n"
    printf "  --compatible-runtimes \"$compatible_runtimes\"\n\n"
    
    # Run AWS CLI command and capture output and exit code
    aws ${publish_aws_opts[@]+"${publish_aws_opts[@]}"} lambda publish-layer-version \
        --layer-name "$layer_name" \
        --description "$final_description" \
        --zip-file "fileb://$(convert_path "$current_dir/$output_dir/$zip_file")" \
        --compatible-runtimes "$compatible_runtimes" \
        --query '[LayerVersionArn, Version, Description]' \
        --output table 2>&1 | tee publish.log
    
    local aws_exit_code=${PIPESTATUS[0]}
    
    if [ $aws_exit_code -eq 0 ]; then
        printf "\n${GREEN}✅ Lambda layer published successfully!${NC}\n"
        
        # Extract layer ARN from log
        local layer_arn=$(grep -o "arn:aws:lambda:[^:]*:[0-9]*:layer:$layer_name:[0-9]*" "publish.log" | tail -1)
        if [ -n "$layer_arn" ]; then
            printf "  Layer ARN: ${CYAN}$layer_arn${NC}\n"
            
            # Show usage example
            printf "\n${YELLOW}Usage example in Lambda function:${NC}\n"
            printf "  layers:\n"
            printf "    - $layer_arn\n"
            printf "\n${YELLOW}To attach to existing Lambda function:${NC}\n"
            printf "  aws lambda update-function-configuration \\\\\n"
            printf "    --function-name YOUR_FUNCTION_NAME \\\\\n"
            printf "    --layers $layer_arn\n"
        fi
    else
        cd "$current_dir"
        printf "\n${RED}❌ Failed to publish Lambda layer${NC}\n"
        printf "Check publish log: $output_dir/publish.log\n"
        printf "\n${YELLOW}Common issues:${NC}\n"
        printf "1. IAM permissions missing (lambda:PublishLayerVersion)\n"
        printf "2. Layer name already exists (try different --name)\n"
        printf "3. Zip file too large (max 50MB for direct upload)\n"
        printf "4. Network connectivity issues\n"
        exit 1
    fi
    
    # Return to original directory
    cd "$current_dir"
    
    printf "\n${GREEN}✅ All done! Layer is now available in your AWS account.${NC}\n"
    printf "📁 Zip file saved: ${CYAN}$output_dir/$zip_file${NC}\n"
}

# Handle completion command
handle_completion() {
    local shell=""
    local show_help=false
    
    if [ $# -eq 0 ]; then
        show_help=true
    fi

    while [[ $# -gt 0 ]]; do
        case "$1" in
            --zsh)
                shell="zsh"
                shift
                ;;
            --bash)
                shell="bash"
                shift
                ;;
            --help|-h)
                show_help=true
                shift
                ;;
            *)
                shift
                ;;
        esac
    done
    
    if [ "$show_help" = true ] || [ -z "$shell" ]; then
        printf "${BLUE}Usage:${NC}\n"
        printf "  aws-lambda-layer-cli ${GREEN}completion${NC} [options]\n\n"
        printf "${BLUE}Options:${NC}\n"
        printf "  ${YELLOW}--zsh${NC}     Output zsh completion script\n"
        printf "  ${YELLOW}--bash${NC}    Output bash completion script\n\n"
        printf "${MAGENTA}${UNDERLINE}Examples:${NC}\n"
        printf "  # Load completion in current shell\n"
        printf "  source <(aws-lambda-layer-cli ${GREEN}completion${NC} ${YELLOW}--bash${NC})\n\n"
        printf "  # Add to .zshrc\n"
        printf "  aws-lambda-layer-cli ${GREEN}completion${NC} ${YELLOW}--zsh${NC} >> ~/.zshrc\n"
        return 0
    fi
    
    # Find completion directory
    # If running from source: ../completion
    # If installed: $INSTALL_DIR/completion
    local completion_dir=""
    if [ -d "$SCRIPT_DIR/../completion" ]; then
        completion_dir="$SCRIPT_DIR/../completion"
    elif [ -d "$INSTALL_DIR/completion" ]; then
        completion_dir="$INSTALL_DIR/completion"
    else
        printf "${RED}Error: Completion directory not found${NC}\n" >&2
        return 1
    fi
    
    if [ "$shell" = "zsh" ]; then
        local file="$completion_dir/aws-lambda-layer-completion.zsh"
        if [ -f "$file" ]; then
            # Remove the auto-execution line if present
            sed 's/_aws-lambda-layer "\$@"//g' "$file"
            printf "\n# Register completion\n"
            printf "if type compdef &>/dev/null; then\n"
            printf "  compdef _aws-lambda-layer aws-lambda-layer\n"
            printf "fi\n"
        else
            printf "${RED}Error: Completion script not found for zsh${NC}\n" >&2
            return 1
        fi
    else
        local file="$completion_dir/aws-lambda-layer-completion.bash"
        if [ -f "$file" ]; then
            cat "$file"
        else
            printf "${RED}Error: Completion script not found for bash${NC}\n" >&2
            return 1
        fi
    fi
}

# Function to convert file paths for compatibility across environments
convert_path() {
    local input_path="$1"
    case "$(uname -s)" in
        Linux)
            if grep -qEi "microsoft|wsl" /proc/version &>/dev/null; then
                # WSL detected, no conversion needed
                echo "$input_path"
            else
                # Native Linux
                echo "$input_path"
            fi
            ;;
        Darwin)
            # macOS
            echo "$input_path"
            ;;
        CYGWIN*|MINGW*|MSYS*)
            # Git Bash or Cygwin on Windows
            # Prefer C:/ style to avoid fileb:// URI parsing issues with backslashes
            if command -v cygpath >/dev/null 2>&1; then
                cygpath -m "$input_path"
            else
                echo "$input_path"
            fi
            ;;
        *)
            # Default case (no conversion)
            echo "$input_path"
            ;;
    esac
}

# Handle uninstall
handle_uninstall() {
    local uninstall_script="$SCRIPT_DIR/uninstall.sh"
    
    # Check if uninstall script exists in script dir
    if [ ! -f "$uninstall_script" ]; then
        # Check install dir
        uninstall_script="$INSTALL_DIR/uninstall.sh"
    fi
    
    if [ -f "$uninstall_script" ]; then
        exec "$uninstall_script" "$@"
    else
        printf "${RED}Error: Uninstall script not found${NC}\n" >&2
        printf "Please run the uninstall script manually or remove the installation directory.\n" >&2
        exit 1
    fi
}

# Main command parsing
main() {
    if [ $# -eq 0 ]; then
        show_help
        exit 0
    fi
    
    case "$1" in
        zip)
            shift
            handle_zip "$@"
            ;;
        publish)
            shift
            handle_publish "$@"
            ;;
        uninstall)
            shift
            handle_uninstall "$@"
            ;;
        completion)
            shift
            handle_completion "$@"
            ;;
        help|--help|-h)
            show_help
            ;;
        --version|-v)
            show_version
            ;;
        *)
            printf "${RED}Error: Unknown command '$1'${NC}\n" >&2
            printf "Available commands: zip, publish\n" >&2
            printf "Use --help for more information\n" >&2
            exit 1
            ;;
    esac
}

# Run main function with all arguments
main "$@"