#!/bin/bash
set -euo pipefail

# Template processing and variable interpolation script for packwiz modpacks
# This script can work with existing ZIP files or create them using packwiz

# Default values
RELEASE_VERSION=""
INPUT_ZIP=""
OUTPUT_ZIP=""
OUTPUT_DIR=""
RAW_DIR=""
SIDE="client"
TEMPLATE_DIR="templates"
PACK_FILE="pack.toml"

# Configuration values
MODPACK_NAME="Tracks and Treats"
CURSEFORGE_PROJECT_ID="1188525"

# File patterns to ignore during text replacement
# This prevents binary files from being corrupted
REPLACEMENTS_IGNORE=(
    "\.jar(\.disabled|\.meta)?$"
    "\.zip$"
    "\.png$"
    "\.jpg$"
    "\.jpeg$"
    "\.gif$"
    "\.bmp$"
    "\.ico$"
    "\.exe$"
    "\.dll$"
    "\.so$"
    "\.dylib$"
    "\.class$"
    "\.dat$"
    "\.db$"
    "\.sqlite$"
)

# Print usage information
usage() {
    cat << EOF
Usage: $0 [OPTIONS]

Process templates and apply variable interpolation to packwiz modpack exports.

Options:
    -v, --version VERSION    Release version (required)
    -o, --output ZIP         Output ZIP file (mutually exclusive with --output-dir)
    -d, --output-dir DIR     Output directory (mutually exclusive with --output)
    -i, --input ZIP          Input ZIP file (optional - if not provided, packwiz export will be used)
    -r, --raw-dir DIR        Raw directory input (alternative to ZIP input/packwiz export)
    -s, --side SIDE          Side to export when using packwiz (client|server, default: client)
    -t, --templates DIR      Templates directory (default: templates)
    -p, --pack-file FILE     Pack file (default: pack.toml)
    -h, --help              Show this help message

Examples:
    # Local usage - let packwiz create the export
    $0 --version "1.7.4" --output "Tracks.and.Treats-1.7.4.zip"
    
    # CI usage - process existing export
    $0 --version "1.7.4" --input "existing-export.zip" --output "final-export.zip"
    
    # Process raw directory (for SSH upload)
    $0 --version "1.7.4" --raw-dir "." --output-dir "builds/processed"
    
    # Create server pack locally
    $0 --version "1.7.4" --side "server" --output "Tracks.and.Treats-1.7.4-server.zip"
EOF
}

# Parse command line arguments
parse_args() {
    while [[ $# -gt 0 ]]; do
        case $1 in
            -v|--version)
                RELEASE_VERSION="$2"
                shift 2
                ;;
            -o|--output)
                OUTPUT_ZIP="$2"
                shift 2
                ;;
            -d|--output-dir)
                OUTPUT_DIR="$2"
                shift 2
                ;;
            -r|--raw-dir)
                RAW_DIR="$2"
                shift 2
                ;;
            -i|--input)
                INPUT_ZIP="$2"
                shift 2
                ;;
            -s|--side)
                SIDE="$2"
                shift 2
                ;;
            -t|--templates)
                TEMPLATE_DIR="$2"
                shift 2
                ;;
            -p|--pack-file)
                PACK_FILE="$2"
                shift 2
                ;;
            -h|--help)
                usage
                exit 0
                ;;
            *)
                echo "Unknown option: $1" >&2
                usage >&2
                exit 1
                ;;
        esac
    done

    # Validate required arguments
    if [[ -z "$RELEASE_VERSION" ]]; then
        echo "Error: Release version is required" >&2
        usage >&2
        exit 1
    fi

    if [[ -z "$OUTPUT_ZIP" && -z "$OUTPUT_DIR" ]]; then
        echo "Error: Either output ZIP file or output directory is required" >&2
        usage >&2
        exit 1
    fi

    if [[ -n "$OUTPUT_ZIP" && -n "$OUTPUT_DIR" ]]; then
        echo "Error: Cannot specify both output ZIP and output directory" >&2
        usage >&2
        exit 1
    fi

    if [[ -n "$INPUT_ZIP" && -n "$RAW_DIR" ]]; then
        echo "Error: Cannot specify both input ZIP and raw directory" >&2
        usage >&2
        exit 1
    fi

    # Validate side parameter
    if [[ "$SIDE" != "client" && "$SIDE" != "server" ]]; then
        echo "Error: Side must be 'client' or 'server'" >&2
        exit 1
    fi
}

# Extract version information from pack.toml
get_minecraft_version() {
    if [[ -f "$PACK_FILE" ]]; then
        grep -E '^minecraft\s*=' "$PACK_FILE" | sed 's/.*=\s*"\([^"]*\)".*/\1/' || echo "unknown"
    else
        echo "unknown"
    fi
}

get_forge_version() {
    if [[ -f "$PACK_FILE" ]]; then
        grep -E '^forge\s*=' "$PACK_FILE" | sed 's/.*=\s*"\([^"]*\)".*/\1/' || echo "unknown"
    else
        echo "unknown"
    fi
}

# Check if a file should be ignored for text replacement
should_ignore_file() {
    local file="$1"
    local filename=$(basename "$file")
    
    for pattern in "${REPLACEMENTS_IGNORE[@]}"; do
        if [[ "$filename" =~ $pattern ]]; then
            return 0  # Should ignore
        fi
    done
    return 1  # Should not ignore
}

# Copy templates to output directory
copy_templates() {
    local work_dir="$1"
    local raw_mode="$2"  # Pass whether we're in raw directory mode
    
    if [[ ! -d "$TEMPLATE_DIR" ]]; then
        echo "Templates directory '$TEMPLATE_DIR' not found, skipping template processing"
        return 0
    fi

    echo "Copying templates from '$TEMPLATE_DIR' to work directory"
    
    # Find all files in templates directory
    find "$TEMPLATE_DIR" -type f | while read -r template_file; do
        # Calculate relative path and destination
        local rel_path="${template_file#$TEMPLATE_DIR/}"
        
        if [[ "$raw_mode" == "true" ]]; then
            # For raw directory mode, copy directly to the same path structure
            local dest_file="$work_dir/$rel_path"
        else
            # For packwiz export mode, copy to overrides/
            local dest_file="$work_dir/overrides/$rel_path"
        fi
        
        local dest_dir=$(dirname "$dest_file")
        
        # Create destination directory if it doesn't exist
        mkdir -p "$dest_dir"
        
        # Copy the file
        cp "$template_file" "$dest_file"
        
        if [[ "$raw_mode" == "true" ]]; then
            echo "  Copied: $template_file -> $rel_path"
        else
            echo "  Copied: $template_file -> overrides/$rel_path"
        fi
    done
}

# Perform variable interpolation on all text files
perform_interpolation() {
    local work_dir="$1"
    local minecraft_version=$(get_minecraft_version)
    local forge_version=$(get_forge_version)
    
    echo "Performing variable interpolation in work directory"
    echo "  Variables:"
    echo "    MINECRAFT_VERSION: $minecraft_version"
    echo "    FORGE_VERSION: $forge_version"
    echo "    MODPACK_NAME: $MODPACK_NAME"
    echo "    MODPACK_PROJECT_ID: $CURSEFORGE_PROJECT_ID"
    echo "    MODPACK_VERSION: $RELEASE_VERSION"
    
    # Find all files in work directory
    find "$work_dir" -type f | while read -r file; do
        # Skip binary files
        if should_ignore_file "$file"; then
            continue
        fi
        
        # Check if file contains any template variables
        # Template variables must be [[UPPER_CASE_WITH_UNDERSCORES]]
        if grep -q '\[\[[A-Z_][A-Z0-9_]*\]\]' "$file" 2>/dev/null; then
            local rel_path="${file#$work_dir/}"
            echo "  Processing: $rel_path"
            
            # Create a temporary file for the replacements
            local temp_file=$(mktemp)
            
            # Perform all replacements
            sed \
                -e "s/\[\[MINECRAFT_VERSION\]\]/$minecraft_version/g" \
                -e "s/\[\[FORGE_VERSION\]\]/$forge_version/g" \
                -e "s/\[\[MODPACK_NAME\]\]/$MODPACK_NAME/g" \
                -e "s/\[\[MODPACK_PROJECT_ID\]\]/$CURSEFORGE_PROJECT_ID/g" \
                -e "s/\[\[MODPACK_VERSION\]\]/$RELEASE_VERSION/g" \
                "$file" > "$temp_file"
            
            # Replace original file with processed version
            mv "$temp_file" "$file"
        fi
    done
}

# Main function
main() {
    parse_args "$@"
    
    echo "Processing templates for modpack export"
    echo "  Release Version: $RELEASE_VERSION"
    if [[ -n "$RAW_DIR" ]]; then
        echo "  Raw Directory Input: $RAW_DIR"
    else
        echo "  Input ZIP: ${INPUT_ZIP:-<will create using packwiz>}"
    fi
    if [[ -n "$OUTPUT_ZIP" ]]; then
        echo "  Output ZIP: $OUTPUT_ZIP"
    else
        echo "  Output Directory: $OUTPUT_DIR"
    fi
    echo "  Side: $SIDE"
    echo "  Templates Directory: $TEMPLATE_DIR"
    echo "  Pack File: $PACK_FILE"
    echo ""
    
    # Create temporary working directory
    local work_dir=$(mktemp -d)
    local source_zip="$INPUT_ZIP"
    
    # Handle different input methods
    local is_raw_mode="false"
    if [[ -n "$RAW_DIR" ]]; then
        # Raw directory input - copy files directly
        echo "Copying files from raw directory: $RAW_DIR"
        if [[ ! -d "$RAW_DIR" ]]; then
            echo "Error: Raw directory not found: $RAW_DIR" >&2
            rm -rf "$work_dir"
            exit 1
        fi
        
        # Copy all files from raw directory to work directory
        if ! cp -r "$RAW_DIR"/* "$work_dir"/; then
            echo "Error: Failed to copy files from raw directory" >&2
            rm -rf "$work_dir"
            exit 1
        fi
        echo "  Copied files from: $RAW_DIR"
        is_raw_mode="true"
    elif [[ -z "$INPUT_ZIP" ]]; then
        # If no input ZIP provided, create one using packwiz
        echo "Creating packwiz export for side: $SIDE"
        
        # Check if packwiz is available
        if ! command -v packwiz &> /dev/null; then
            echo "Error: packwiz command not found. Please install packwiz first." >&2
            rm -rf "$work_dir"
            exit 1
        fi
        
        # Export using packwiz
        source_zip="$work_dir/packwiz-export.zip"
        if ! packwiz curseforge export --side "$SIDE" --output "$source_zip"; then
            echo "Error: Failed to create packwiz export" >&2
            rm -rf "$work_dir"
            exit 1
        fi
        
        if [[ ! -f "$source_zip" ]]; then
            echo "Error: Packwiz export file not found: $source_zip" >&2
            rm -rf "$work_dir"
            exit 1
        fi
        
        echo "  Created: $source_zip"
        
        # Extract the ZIP we just created
        echo "Extracting packwiz export: $source_zip"
        if ! unzip -q "$source_zip" -d "$work_dir"; then
            echo "Error: Failed to extract ZIP file" >&2
            rm -rf "$work_dir"
            exit 1
        fi
        
        # Remove the ZIP file from work directory
        rm -f "$source_zip"
        echo "  Cleaned up temporary export file"
    else
        # Handle provided ZIP input
        # Verify source ZIP exists
        if [[ ! -f "$source_zip" ]]; then
            echo "Error: Source ZIP file not found: $source_zip" >&2
            rm -rf "$work_dir"
            exit 1
        fi
        
        echo "Extracting source ZIP: $source_zip"
        # Extract to work directory
        if ! unzip -q "$source_zip" -d "$work_dir"; then
            echo "Error: Failed to extract ZIP file" >&2
            rm -rf "$work_dir"
            exit 1
        fi
    fi
    
    # Copy templates (they override existing files)
    copy_templates "$work_dir" "$is_raw_mode"
    
    # Perform variable interpolation on all files
    perform_interpolation "$work_dir"
    
    # Handle output - either ZIP or directory
    if [[ -n "$OUTPUT_ZIP" ]]; then
        # Create output ZIP
        echo "Creating output ZIP: $OUTPUT_ZIP"
        local output_dir=$(dirname "$OUTPUT_ZIP")
        mkdir -p "$output_dir"
        
        # Create ZIP from work directory
        if ! (cd "$work_dir" && zip -rq "$OLDPWD/$OUTPUT_ZIP" .); then
            echo "Error: Failed to create output ZIP" >&2
            rm -rf "$work_dir"
            exit 1
        fi
        
        # Cleanup work directory
        rm -rf "$work_dir"
        
        echo ""
        echo "Template processing completed successfully!"
        echo "Output saved to: $OUTPUT_ZIP"
    else
        # Copy processed files to output directory
        echo "Copying processed files to output directory: $OUTPUT_DIR"
        mkdir -p "$OUTPUT_DIR"
        
        # Copy all files from work directory to output directory
        if ! cp -r "$work_dir"/* "$OUTPUT_DIR"/; then
            echo "Error: Failed to copy files to output directory" >&2
            rm -rf "$work_dir"
            exit 1
        fi
        
        # Cleanup work directory
        rm -rf "$work_dir"
        
        echo ""
        echo "Template processing completed successfully!"
        echo "Output saved to: $OUTPUT_DIR"
    fi
}

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