#!/bin/bash
# WHP Release Builder
# Builds tar.gz release packages for distribution

# Exit on any error
set -e

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

# Get the directory where this script is located
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"

# Change to project root
cd "$PROJECT_ROOT"

# Auto-versioning: Create or increment VERSION file
if [ ! -f VERSION ]; then
    # Create initial version if file doesn't exist
    echo "2025.07.1" > VERSION
    echo -e "${YELLOW}Created initial VERSION file: 2025.07.1${NC}"
else
    # Read current version and increment patch number
    CURRENT_VERSION=$(cat VERSION)
    echo "Current version: $CURRENT_VERSION"
    
    # Parse version components (YYYY.MM.N format)
    if [[ $CURRENT_VERSION =~ ^([0-9]{4})\.([0-9]{2})\.([0-9]+)$ ]]; then
        YEAR="${BASH_REMATCH[1]}"
        MONTH="${BASH_REMATCH[2]}"
        PATCH="${BASH_REMATCH[3]}"
        
        # Get current date components
        CURRENT_YEAR=$(date +%Y)
        CURRENT_MONTH=$(date +%m)
        
        # If year or month changed, reset patch to 1
        if [ "$YEAR" != "$CURRENT_YEAR" ] || [ "$MONTH" != "$CURRENT_MONTH" ]; then
            NEW_VERSION="$CURRENT_YEAR.$CURRENT_MONTH.1"
            echo -e "${YELLOW}New month/year detected, resetting to $NEW_VERSION${NC}"
        else
            # Increment patch number
            NEW_PATCH=$((PATCH + 1))
            NEW_VERSION="$YEAR.$MONTH.$NEW_PATCH"
            echo -e "${YELLOW}Incrementing patch version to $NEW_VERSION${NC}"
        fi
    else
        echo -e "${RED}Error: Invalid version format in VERSION file: $CURRENT_VERSION${NC}"
        echo "Expected format: YYYY.MM.N (e.g., 2025.07.1)"
        exit 1
    fi
    
    # Update VERSION file
    echo "$NEW_VERSION" > VERSION
fi

VERSION=$(cat VERSION)
RELEASE_DIR="/tmp/whp-release-$VERSION"
RELEASES_PATH="/var/www/whp-releases"

echo -e "${GREEN}Building WHP Release $VERSION${NC}"

# Clean and create temp directory
echo "Creating temporary build directory..."
rm -rf "$RELEASE_DIR"
mkdir -p "$RELEASE_DIR"

# ======================================================
# Sync Site Builder files from its separate repository
# ======================================================
SITE_BUILDER_REPO="${SITE_BUILDER_REPO:-/root/site-builder}"

if [ -d "$SITE_BUILDER_REPO" ]; then
    echo -e "${YELLOW}Syncing Site Builder from $SITE_BUILDER_REPO${NC}"

    # Pull latest from site-builder repo
    cd "$SITE_BUILDER_REPO"
    git pull --quiet 2>/dev/null || echo -e "${YELLOW}Warning: Could not pull site-builder repo (may be fine if not tracking remote)${NC}"
    cd "$PROJECT_ROOT"

    # Ensure site-builder directory exists in web-files
    mkdir -p "$PROJECT_ROOT/web-files/site-builder"

    # Copy runtime files (preserve WHP-specific files like index.php, .user.ini)
    rsync -av --delete \
        --exclude='.git' \
        --exclude='.gitignore' \
        --exclude='.claude' \
        --exclude='node_modules' \
        --exclude='package-lock.json' \
        --exclude='package.json' \
        --exclude='tests/' \
        --exclude='test-*' \
        --exclude='docker-*' \
        --exclude='Dockerfile' \
        --exclude='docker-compose.yml' \
        --exclude='deploy.sh' \
        --exclude='router.php' \
        --exclude='*.md' \
        --exclude='.htaccess' \
        --exclude='.user.ini' \
        --exclude='.playwright-mcp' \
        --exclude='__pycache__' \
        --exclude='storage/' \
        --exclude='test-results/' \
        --exclude='screenshot-media.js' \
        --exclude='playwright.config.js' \
        --exclude='clear-data.html' \
        --exclude='.dockerignore' \
        --exclude='api/' \
        "$SITE_BUILDER_REPO/" "$PROJECT_ROOT/web-files/site-builder/"

    # Rename index.html to editor.html (WHP uses index.php as the entry point)
    if [ -f "$PROJECT_ROOT/web-files/site-builder/index.html" ]; then
        mv "$PROJECT_ROOT/web-files/site-builder/index.html" "$PROJECT_ROOT/web-files/site-builder/editor.html"
    fi

    echo -e "${GREEN}Site Builder files synced successfully${NC}"
else
    echo -e "${YELLOW}Site Builder repo not found at $SITE_BUILDER_REPO (skipping sync)${NC}"
    echo "  Set SITE_BUILDER_REPO environment variable to override the path"
fi

# Files and directories to exclude from release
EXCLUDE_PATTERNS=(
    '.git'
    '.gitignore'
    '.gitea/'
    '.cursorrules'
    '.claude/'
    'docs/'
    '*.md'
    '.dev/'
    'NextSteps.md'
    'CLAUDE.md'
    'Notes/'
    '.build-exclude'
    'test/'
    '*.log'
    '.DS_Store'
    'release-server/'
    'how_to_get_container_ip_range.txt'
    'memories.md'
    'cursor_rules.md'
    'database_schema.md'
    'PERMISSION_SYSTEM.md'
    # Staging dirs hold pre-release work that gets renamed into versioned
    # dirs further down. The rsync runs BEFORE that rename, so without these
    # excludes the staging copy ends up shipped alongside the versioned one.
    'sql/migrations/staging/'
    'scripts/updates/staging/'
)

# Build rsync exclude arguments
RSYNC_EXCLUDES=""
for pattern in "${EXCLUDE_PATTERNS[@]}"; do
    RSYNC_EXCLUDES="$RSYNC_EXCLUDES --exclude=$pattern"
done

# Lint: canonical schema must match migration-derived schema.
# scripts/regenerate-canonical-schema.sh --check exits 1 if there's drift,
# so a forgotten staging migration without a corresponding canonical update
# fails the build instead of silently shipping a broken fresh-install schema.
if [ -f ./scripts/regenerate-canonical-schema.sh ]; then
    echo -e "${YELLOW}Checking canonical schema is in sync with migrations...${NC}"
    if ! bash ./scripts/regenerate-canonical-schema.sh --check; then
        echo -e "${RED}Canonical schema drift detected -- aborting release.${NC}"
        exit 1
    fi
    echo -e "${GREEN}✓ Canonical schema is in sync${NC}"
fi

# Copy production files
echo "Copying production files..."
rsync -av $RSYNC_EXCLUDES ./ "$RELEASE_DIR/"

# Ensure required directories exist in release
mkdir -p "$RELEASE_DIR/sql/migrations"
mkdir -p "$RELEASE_DIR/scripts/updates"

# Handle staging migrations - move them to proper version folder
STAGING_CHANGES=false
if [ -d "sql/migrations/staging" ] && [ "$(ls -A sql/migrations/staging 2>/dev/null)" ]; then
    echo -e "${YELLOW}Found staging migrations, organizing for version $VERSION${NC}"
    
    # Create version directory
    mkdir -p "sql/migrations/$VERSION"
    
    # Move staging migrations to version folder  
    mv sql/migrations/staging/* "sql/migrations/$VERSION/"
    
    # Remove empty staging directory
    rmdir sql/migrations/staging 2>/dev/null || true
    
    echo "Staging migrations moved to sql/migrations/$VERSION/"
    STAGING_CHANGES=true
fi

# Handle staging shell scripts - move them to proper version folder
if [ -d "scripts/updates/staging" ] && [ "$(ls -A scripts/updates/staging 2>/dev/null)" ]; then
    echo -e "${YELLOW}Found staging update scripts, organizing for version $VERSION${NC}"
    
    # Create version directory
    mkdir -p "scripts/updates/$VERSION"
    
    # Move staging scripts to version folder  
    mv scripts/updates/staging/* "scripts/updates/$VERSION/"
    
    # Remove empty staging directory
    rmdir scripts/updates/staging 2>/dev/null || true
    
    echo "Staging update scripts moved to scripts/updates/$VERSION/"
    STAGING_CHANGES=true
fi

# Commit organized staging content back to git
if [ "$STAGING_CHANGES" = true ]; then
    if git status --porcelain | grep -E "(sql/|scripts/)" > /dev/null; then
        echo "Committing organized staging content to git..."
        git add sql/ scripts/
        git commit -m "Organize staging content for release $VERSION

- Move staging migrations to sql/migrations/$VERSION/
- Move staging update scripts to scripts/updates/$VERSION/
- Update complete-database-setup.sql with new schema changes

Auto-generated commit from build-release.sh

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>"
        
        # Push to remote if on a branch that tracks remote
        if git rev-parse --abbrev-ref --symbolic-full-name @{u} >/dev/null 2>&1; then
            echo "Pushing organized content to remote..."
            git push
        else
            echo -e "${YELLOW}Note: Not pushing to remote (no upstream branch configured)${NC}"
        fi
    fi
fi

# Get list of all version directories (from both migrations and scripts) sorted by version (exclude staging)
ALL_VERSIONS=()

# Collect migration versions
if [ -d "sql/migrations" ]; then
    cd "$PROJECT_ROOT/sql/migrations"
    MIGRATION_VERSIONS=($(ls -d */ 2>/dev/null | sed 's/\///' | grep -v '^staging$' | sort -V))
    cd "$PROJECT_ROOT"
    ALL_VERSIONS+=(${MIGRATION_VERSIONS[@]})
fi

# Collect script versions
if [ -d "scripts/updates" ]; then
    cd "$PROJECT_ROOT/scripts/updates"
    SCRIPT_VERSIONS=($(ls -d */ 2>/dev/null | sed 's/\///' | grep -v '^staging$' | sort -V))
    cd "$PROJECT_ROOT"
    ALL_VERSIONS+=(${SCRIPT_VERSIONS[@]})
fi

# Remove duplicates and sort
if [ ${#ALL_VERSIONS[@]} -gt 0 ]; then
    UNIQUE_VERSIONS=($(printf '%s\n' "${ALL_VERSIONS[@]}" | sort -V | uniq))
    TOTAL=${#UNIQUE_VERSIONS[@]}
    echo "Found $TOTAL total versions (migrations + scripts)"
    
    if [ $TOTAL -gt 10 ]; then
        # Keep only the last 10 versions
        echo -e "${YELLOW}Trimming to last 10 versions${NC}"
        KEEP_FROM=$((TOTAL - 10))
        
        # Copy only the last 10 versions for both migrations and scripts
        for ((i=$KEEP_FROM; i<$TOTAL; i++)); do
            VERSION_DIR="${UNIQUE_VERSIONS[$i]}"
            echo "  Including: $VERSION_DIR"
            
            # Copy migration if it exists for this version
            if [ -d "sql/migrations/$VERSION_DIR" ]; then
                cp -r "sql/migrations/$VERSION_DIR" "$RELEASE_DIR/sql/migrations/"
            fi
            
            # Copy scripts if they exist for this version
            if [ -d "scripts/updates/$VERSION_DIR" ]; then
                cp -r "scripts/updates/$VERSION_DIR" "$RELEASE_DIR/scripts/updates/"
            fi
        done
        
        OLDEST_VERSION="${UNIQUE_VERSIONS[$KEEP_FROM]}"
    else
        # Copy all versions
        OLDEST_VERSION="${UNIQUE_VERSIONS[0]}"
        
        # Copy all migrations
        if [ -d "sql/migrations" ]; then
            cp -r sql/migrations/* "$RELEASE_DIR/sql/migrations/" 2>/dev/null || true
        fi
        
        # Copy all scripts
        if [ -d "scripts/updates" ]; then
            cp -r scripts/updates/* "$RELEASE_DIR/scripts/updates/" 2>/dev/null || true
        fi
    fi
else
    echo -e "${YELLOW}No migration or script versions found${NC}"
    OLDEST_VERSION="$VERSION"
fi

# Create migration and update history file
echo "Creating update history..."
cat > "$RELEASE_DIR/UPDATE_HISTORY.json" <<EOF
{
  "current_version": "$VERSION",
  "oldest_supported": "$OLDEST_VERSION",
  "migration_count": $(ls -d "$RELEASE_DIR"/sql/migrations/*/ 2>/dev/null | wc -l || echo 0),
  "script_count": $(ls -d "$RELEASE_DIR"/scripts/updates/*/ 2>/dev/null | wc -l || echo 0),
  "total_versions": $(ls -d "$RELEASE_DIR"/sql/migrations/*/ "$RELEASE_DIR"/scripts/updates/*/ 2>/dev/null | sed 's|.*/||' | sort -V | uniq | wc -l || echo 0),
  "build_date": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
  "build_host": "$(hostname)"
}
EOF

# Create legacy migration history file for backward compatibility
cat > "$RELEASE_DIR/MIGRATION_HISTORY.json" <<EOF
{
  "current_version": "$VERSION",
  "oldest_supported": "$OLDEST_VERSION",
  "migration_count": $(ls -d "$RELEASE_DIR"/sql/migrations/*/ 2>/dev/null | wc -l || echo 0),
  "build_date": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
  "build_host": "$(hostname)"
}
EOF

# Create tar.gz
echo "Creating release archive..."
cd /tmp
tar -czf "whp-$VERSION.tar.gz" "whp-release-$VERSION/"

# Calculate file size and checksum
FILE_SIZE=$(stat -c%s "whp-$VERSION.tar.gz" 2>/dev/null || stat -f%z "whp-$VERSION.tar.gz" 2>/dev/null)
FILE_CHECKSUM=$(sha256sum "whp-$VERSION.tar.gz" | cut -d' ' -f1)

echo -e "${GREEN}Release package created:${NC}"
echo "  File: whp-$VERSION.tar.gz"
echo "  Size: $(numfmt --to=iec-i --suffix=B $FILE_SIZE 2>/dev/null || echo "$FILE_SIZE bytes")"
echo "  SHA256: $FILE_CHECKSUM"

# If releases path exists (on build server), deploy it
if [ -d "$RELEASES_PATH" ]; then
    echo "Deploying to releases directory..."
    mkdir -p "$RELEASES_PATH/releases"
    mv "whp-$VERSION.tar.gz" "$RELEASES_PATH/releases/"
    
    # Create metadata file
    cat > "$RELEASES_PATH/releases/whp-$VERSION.json" <<EOF
{
  "version": "$VERSION",
  "filename": "whp-$VERSION.tar.gz",
  "size": $FILE_SIZE,
  "checksum": "$FILE_CHECKSUM",
  "oldest_supported": "$OLDEST_VERSION",
  "release_date": "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
}
EOF
    
    # Update latest.json
    cp "$RELEASES_PATH/releases/whp-$VERSION.json" "$RELEASES_PATH/latest.json"
    
    echo -e "${GREEN}Release deployed to whp-releases.cloud-hosting.io${NC}"
else
    # Keep the file in /tmp for manual deployment
    echo -e "${YELLOW}Release package saved to: /tmp/whp-$VERSION.tar.gz${NC}"
    echo "Deploy manually to your release server"
    
    # Also create the metadata file
    cat > "/tmp/whp-$VERSION.json" <<EOF
{
  "version": "$VERSION",
  "filename": "whp-$VERSION.tar.gz",
  "size": $FILE_SIZE,
  "checksum": "$FILE_CHECKSUM",
  "oldest_supported": "$OLDEST_VERSION",
  "release_date": "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
}
EOF
    echo "Metadata saved to: /tmp/whp-$VERSION.json"
fi

# Cleanup
rm -rf "$RELEASE_DIR"

echo -e "${GREEN}Build complete!${NC}"