#!/bin/bash

# CloudXM Plugin Generic Build Script
# Usage: ./build-plugin.sh <plugin_dir> [output_dir] [build_type]
# Build types: production (default), dev
#
# Parameters:
#   plugin_dir: Path to plugin directory (default: auto-detect)
#   output_dir: Where to save the built archive (default: ../public/{plugin-name})
#   build_type: 'production' or 'dev' (default: production)
#               'dev' builds force CLOUDXM_FORCE_DEV_MODE=true
#
# CI Integration:
#   In GitLab CI, build_type is auto-detected from branch name:
#   - develop/staging/*dev* branches → dev builds
#   - main/master branches → production builds
#
# This script can be copied to each plugin or used as a template

set -e  # Exit on any error

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# Parse arguments
PLUGIN_ROOT="${1:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}"
OUTPUT_DIR="${2:-}"
BUILD_TYPE="${3:-production}"  # New parameter: production or dev

# Resolve plugin root to absolute path
PLUGIN_ROOT="$(cd "$PLUGIN_ROOT" && pwd)"

# Function to log steps
log() {
    echo -e "${GREEN}✓ $1${NC}"
}

# Function to log warnings
warn() {
    echo -e "${YELLOW}⚠ $1${NC}"
}

# Function to log errors
error() {
    echo -e "${RED}❌ $1${NC}"
}

# Function to exit with error
die() {
    error "$1"
    exit 1
}

# Function to check if command exists
command_exists() {
    command -v "$1" >/dev/null 2>&1
}

# Pre-build validation
validate_environment() {
    log "Validating build environment..."

    # Check if composer.json exists
    [[ -f "$PLUGIN_ROOT/composer.json" ]] || die "composer.json not found!"

    # Check if PHP is available
    command_exists php || die "PHP not found! Please install PHP."

    # Check if composer is available
    command_exists composer || warn "Composer not found. Assuming vendor directory is ready."

    # Check if src or includes directory exists (support both modern and legacy structures)
    if [[ ! -d "$PLUGIN_ROOT/src" ]] && [[ ! -d "$PLUGIN_ROOT/includes" ]]; then
        die "Neither src/ nor includes/ directory found!"
    fi

    log "Environment validation passed!"
}

# Install/update dependencies
install_dependencies() {
    log "Installing/Updating dependencies..."

    if command_exists composer; then
        cd "$PLUGIN_ROOT"

        # Install dependencies (production mode)
        if ! composer install --no-dev --optimize-autoloader 2>/dev/null; then
            warn "composer install failed (stale lock file), running composer update..."
            composer update --no-dev --optimize-autoloader || die "Failed to run composer update"
        fi

        # Verify vendor directory exists
        [[ -d "$PLUGIN_ROOT/vendor" ]] || die "vendor/ directory not found after composer install"

        log "Dependencies installed successfully!"
    else
        warn "Composer not available - assuming vendor directory is pre-built"
        [[ -d "$PLUGIN_ROOT/vendor" ]] || warn "vendor/ directory not found!"
    fi
}

# Configure build type (dev vs production)
configure_build_type() {
    if [[ "$BUILD_TYPE" == "dev" ]]; then
        log "Configuring development build..."

        # Uncomment CLOUDXM_FORCE_DEV_MODE for dev builds
        if [[ -f "$PLUGIN_ROOT/$PLUGIN_FILE" ]]; then
            sed -i 's|// define('\''CLOUDXM_FORCE_DEV_MODE'\'', true);|define('\''CLOUDXM_FORCE_DEV_MODE'\'', true);|' "$PLUGIN_ROOT/$PLUGIN_FILE"
            log "Enabled CLOUDXM_FORCE_DEV_MODE for dev build"
        fi
    else
        log "Configuring production build..."
    fi
}

# Minify assets (if package.json and npm are available)
minify_assets() {
    log "Minifying assets..."

    if [[ -f "$PLUGIN_ROOT/package.json" ]] && command_exists npm; then
        cd "$PLUGIN_ROOT"

        # Install npm dependencies if needed
        if [[ ! -d "node_modules" ]]; then
            npm install --include=dev || warn "Failed to install npm dependencies"
        fi

        # Run build script to minify assets
        npm run build || warn "Failed to run asset build process"

        log "Assets minified successfully!"
    else
        if [[ ! -f "$PLUGIN_ROOT/package.json" ]]; then
            warn "No package.json found - skipping asset minification"
        fi
        if ! command_exists npm; then
            warn "npm not available - skipping asset minification"
        fi
    fi
}

# Clean unnecessary files
clean_temp_files() {
    log "Cleaning temporary files..."

    cd "$PLUGIN_ROOT"

    # Plugin-specific files to remove - only remove files that are NOT the main plugin file
    PLUGIN_SPECIFIC_FILES=(
        # Add any additional plugin-specific files to clean up here that are NOT the main plugin file
        # The main plugin file is automatically preserved during cleanup
    )

    # Common files and directories to remove
    TEMP_FILES=(
        "composer.lock"
        "latest.json"
        "tools/refactor-legacy-classes.php"
        "tools/build-rector-mapping.php"
        "tools/migrate-psr4.sh"
        "tools/rename-methods.php"
        "package-lock.json"
    )

    TEMP_DIRS=(
        "node_modules"
    )

    # Add plugin-specific files to cleanup
    for plugin_file in "${PLUGIN_SPECIFIC_FILES[@]}"; do
        TEMP_FILES+=("$plugin_file")
    done

    for file in "${TEMP_FILES[@]}"; do
        if [[ -f "$file" ]]; then
            rm "$file"
            log "Removed $file"
        elif [[ -L "$file" ]]; then
            rm "$file"
            log "Removed symlink $file"
        fi
    done

    # Remove directories
    for dir in "${TEMP_DIRS[@]}"; do
        if [[ -d "$dir" ]]; then
            rm -rf "$dir"
            log "Removed directory $dir/"
        fi
    done

    log "Cleanup completed!"
}


# Create archive
create_archive() {
    log "Creating plugin archive for $VERSION..."

    # Create output directory if it doesn't exist
    mkdir -p "$OUTPUT_DIR"

    # Fallback if VERSION is empty
    if [ -z "$VERSION" ]; then
        VERSION="latest"
    fi

    # Archive name - use plugin file name directly (version in filename only)
    # For CI/CD, use 'latest' for development builds, actual version for releases
    if [[ "$BUILD_TYPE" == "dev" ]] || [[ "$VERSION" == "latest" ]]; then
        ARCHIVE_NAME="$PLUGIN_NAME-vlatest.zip"
    else
        ARCHIVE_NAME="$PLUGIN_NAME-v$VERSION.zip"
    fi

    # Define exclusions for archive
    EXCLUSIONS=(
        "*.git*"
        ".git"
        "*.npm*"
        ".npm"
        "*.DS_Store*"
        "*.lock"
        "*node_modules*"
        "*tests*"
        "*latest.json*"
        "*README*"
        "*.bak*"
        "*wp-content*"  # Exclude entire wp-content directory (including symlinks/other plugins)
        "*vendor/composer/installers*"  # Exclude composer/installers (not needed at runtime)
        # NOTE: screenshots/ is intentionally NOT excluded — it is served by the distribution server
    )

    # Create a temporary directory with the correct plugin folder name (version-agnostic)
    TEMP_DIR=$(mktemp -d)
    PLUGIN_FOLDER_NAME="$PLUGIN_NAME"

    # Copy plugin files to temp directory with correct folder structure
    mkdir -p "$TEMP_DIR/$PLUGIN_FOLDER_NAME"

    # Copy all files except exclusions
    cd "$PLUGIN_ROOT"

    # Use find + cp for cross-platform compatibility (fallback if rsync not available)
    if command_exists rsync; then
        log "Using rsync for file copying..."
        # Build rsync exclude patterns
        RSYNC_EXCLUDES=""
        for exclusion in "${EXCLUSIONS[@]}"; do
            RSYNC_EXCLUDES="$RSYNC_EXCLUDES --exclude=$exclusion"
        done
        # Copy files while preserving directory structure
        rsync -av $RSYNC_EXCLUDES --prune-empty-dirs . "$TEMP_DIR/$PLUGIN_FOLDER_NAME/"
    else
        log "Using find + cp for file copying..."
        # Fallback to find + cp (works on most systems)
        find . -type f \( $(printf "! -path '*/%s*' " "${EXCLUSIONS[@]}") \) -exec cp --parents {} "$TEMP_DIR/$PLUGIN_FOLDER_NAME/" \; 2>/dev/null || \
        # If --parents fails, use tar as final fallback
        find . -type f \( $(printf "! -name '%s' " "${EXCLUSIONS[@]}") \) | tar -cf - -T - | (cd "$TEMP_DIR/$PLUGIN_FOLDER_NAME" && tar -xf -)
    fi

    # Navigate to temp directory and create zip
    cd "$TEMP_DIR"
    # Use absolute path for output directory to ensure it works from temp directory
    ABS_OUTPUT_DIR="$(cd "$PLUGIN_ROOT" && mkdir -p "$OUTPUT_DIR" && cd "$OUTPUT_DIR" && pwd)"
    ZIP_CMD="zip -r \"$ABS_OUTPUT_DIR/$ARCHIVE_NAME\" \"$PLUGIN_FOLDER_NAME\""

    # Execute zip command
    log "Executing zip command: $ZIP_CMD"
    eval "$ZIP_CMD"

    # Clean up temp directory
    cd "$PLUGIN_ROOT"
    rm -rf "$TEMP_DIR"

    log "Archive created: $OUTPUT_DIR/$ARCHIVE_NAME"

    # Show archive size
    ARCHIVE_SIZE=$(du -sh "$OUTPUT_DIR/$ARCHIVE_NAME" 2>/dev/null || echo "N/A")
    log "Archive size: $ARCHIVE_SIZE"
}

# Main build function
main() {
    # Plugin-specific configuration (auto-detected from plugin files)
    PLUGIN_DIR_NAME="$(basename "$PLUGIN_ROOT")"

    # Find the main plugin file (WordPress standard: file with plugin headers)
    # Strategy: Try standardized naming first, then fallback to header detection
    PLUGIN_DIR_BASENAME=$(basename "$PLUGIN_ROOT")

    # CloudXM standardized naming: folder name with .php extension
    # cloudxm-plugin-woo-{name} → woocommerce-cloudxm-{name}.php
    PLUGIN_NAME_PART="${PLUGIN_DIR_BASENAME#cloudxm-plugin-woo-}"
    PLUGIN_FILE="woocommerce-cloudxm-${PLUGIN_NAME_PART}.php"

    # Verify the file exists
    if [ ! -f "$PLUGIN_ROOT/$PLUGIN_FILE" ]; then
        die "Main plugin file not found: $PLUGIN_FILE. Expected CloudXM naming convention: folder-name.php"
    fi

    # Extract plugin information from the header
    PLUGIN_NAME=$(basename "$PLUGIN_FILE" .php)
    PLUGIN_DISPLAY_NAME=$(grep "Plugin Name:" "$PLUGIN_ROOT/$PLUGIN_FILE" | sed 's/.*Plugin Name:\s*//' | sed 's/^[[:space:]]*//' | sed 's/[[:space:]]*$//')
    VERSION=$(grep "Version:" "$PLUGIN_ROOT/$PLUGIN_FILE" | sed 's/.*Version:\s*//' | tr -d '\r' | sed 's/^[[:space:]]*//' | sed 's/[[:space:]]*$//')
    PLUGIN_SLUG=$(grep "Text Domain:" "$PLUGIN_ROOT/$PLUGIN_FILE" | sed 's/.*Text Domain:\s*//' | tr -d '\r' | sed 's/^[[:space:]]*//' | sed 's/[[:space:]]*$//')

    # Clean up the slug - if it's the full plugin name, extract the meaningful part
    if [ -n "$PLUGIN_SLUG" ]; then
        # If Text Domain is the same as plugin name, extract the core slug
        if [ "$PLUGIN_SLUG" = "$PLUGIN_NAME" ]; then
            PLUGIN_SLUG="${PLUGIN_NAME#woocommerce-}"
            PLUGIN_SLUG="${PLUGIN_SLUG%-gateway}"
        fi
        # If Text Domain starts with woocommerce-, remove that prefix
        if [[ "$PLUGIN_SLUG" == woocommerce-* ]]; then
            PLUGIN_SLUG="${PLUGIN_SLUG#woocommerce-}"
        fi
        # If Text Domain ends with -gateway, remove that suffix
        if [[ "$PLUGIN_SLUG" == *-gateway ]]; then
            PLUGIN_SLUG="${PLUGIN_SLUG%-gateway}"
        fi
    else
        # Fallback if no Text Domain found
        PLUGIN_SLUG="${PLUGIN_NAME#woocommerce-}"
        PLUGIN_SLUG="${PLUGIN_SLUG%-gateway}"
    fi

    # Default output directory if not provided
    if [ -z "$OUTPUT_DIR" ]; then
        OUTPUT_DIR="$PLUGIN_ROOT/../../public/$PLUGIN_NAME"
    fi

    echo -e "${BLUE}🚀 Building $PLUGIN_NAME${NC}"
    echo "📁 Plugin root: $PLUGIN_ROOT"
    echo "📦 Output directory: $OUTPUT_DIR"
    echo "🏗️  Build type: $BUILD_TYPE"
    echo

    log "Starting build process for $PLUGIN_NAME..."

    validate_environment
    install_dependencies
    configure_build_type
    # TODO: Add minify_assets when minification setup is improved
    # minify_assets
    clean_temp_files
    create_archive

    echo
    echo -e "${GREEN}🎉 Build completed successfully!${NC}"
    echo -e "${BLUE}📦 Archive:${NC} $OUTPUT_DIR/$ARCHIVE_NAME"
}

# Run main function with error handling
trap 'error "Build failed!"; exit 1' ERR

main "$@"