#!/bin/bash

# Post-receive hook for automatic deployment
# Deploy develop branch to dev, main branch to production
#
# Runs as the git server user (www-data). No sudo: both deploy trees are
# group/ACL-writable for www-data, and docker exec works via the docker group.
# ACL notes: default ACLs on the trees grant rwX to www-data and cristi, so
# files created by either side stay accessible to the other. Permission
# fixups below only touch group/other bits (which extend the ACL mask,
# never shrink it) — numeric chmod (644/755) would RESET the ACL mask and
# break shared access. Do not reintroduce them.

while read oldrev newrev refname
do
    # Tag pushes carry no branch — they exist only so describe() sees them.
    [[ "$refname" == refs/tags/* ]] && continue

    branch=$(git rev-parse --symbolic --abbrev-ref $refname)

    if [ "$branch" = "develop" ]; then
        echo "🚀 Deploying develop branch to DEVELOPMENT environment..."

        # Development deployment directory
        DEPLOY_DIR="/var/www/virtuals/docker/erp-dev"
        CONTAINER_NAME="erp-php-dev"
        BACKUP_DIR="/var/www/virtuals/docker/backups"

        # Create backup directory if not exists
        mkdir -p $BACKUP_DIR

        # Create backup (code only: storage/vendor/node_modules are excluded —
        # user data is backed up separately, deps are rebuilt by composer)
        if [ -d "$DEPLOY_DIR" ]; then
            echo "📦 Creating development backup..."
            rsync -a --exclude 'storage/' --exclude 'vendor/' --exclude 'node_modules/' \
                $DEPLOY_DIR/ $BACKUP_DIR/erp-dev.backup.$(date +%Y%m%d_%H%M%S)/ \
                || echo "⚠️ Backup completed with warnings (some files unreadable)"
            # Retention: keep only the 3 newest backups
            ls -1dt $BACKUP_DIR/erp-dev.backup.* 2>/dev/null | tail -n +4 | xargs -r rm -rf
        fi

        # Deploy latest code
        echo "📥 Deploying code to development..."
        git --work-tree=$DEPLOY_DIR --git-dir=/var/www/virtuals/git.phantom.eu.org/erp.git checkout -f develop \
            || { echo "❌ DEVELOPMENT DEPLOY FAILED: git checkout"; continue; }

        # Bake the deployed version so the app can display it — the worktree
        # has no .git at runtime. Release tags live on main merge commits
        # (never ancestors of develop), so dev derives its version from the
        # latest release tag on main plus the distance to it:
        # "v1.1.0-dev.3-gabc123" = 3 develop commits ahead of release v1.1.0.
        GIT_DIR=/var/www/virtuals/git.phantom.eu.org/erp.git
        mkdir -p $DEPLOY_DIR/storage/app
        release_tag=$(git --git-dir=$GIT_DIR describe --tags --abbrev=0 --match 'v[0-9]*' main 2>/dev/null || true)
        if [ -n "$release_tag" ]; then
            ahead=$(git --git-dir=$GIT_DIR rev-list --count ${release_tag}..$newrev)
            echo "${release_tag}-dev.${ahead}-g$(git --git-dir=$GIT_DIR rev-parse --short $newrev)" \
                > $DEPLOY_DIR/storage/app/version.txt
        else
            git --git-dir=$GIT_DIR describe --tags --always $newrev \
                > $DEPLOY_DIR/storage/app/version.txt 2>/dev/null \
                || echo "dev" > $DEPLOY_DIR/storage/app/version.txt
        fi

        # Install dependencies (dev keeps dev packages: phpunit, tinker, etc.)
        echo "📦 Installing development dependencies..."
        cd $DEPLOY_DIR
        if [ -f "composer.json" ]; then
            docker exec $CONTAINER_NAME composer install --optimize-autoloader
        fi

        # Frontend build only when the container actually ships npm
        if [ -f "package.json" ] && docker exec $CONTAINER_NAME sh -c 'command -v npm' >/dev/null 2>&1; then
            docker exec $CONTAINER_NAME npm install
            docker exec $CONTAINER_NAME npm run build
        fi

        # Clear caches
        echo "🧹 Clearing development caches..."
        docker exec $CONTAINER_NAME php artisan config:clear
        docker exec $CONTAINER_NAME php artisan cache:clear
        docker exec $CONTAINER_NAME php artisan view:clear

        # Fix permissions — ACL-safe: only widen group/other bits, never
        # reset the mask, and never touch .git (cristi commits need it writable)
        echo "🔒 Fixing development permissions..."
        chown -R www-data:www-data $DEPLOY_DIR 2>/dev/null || true
        find $DEPLOY_DIR -path $DEPLOY_DIR/.git -prune -o -type d -exec chmod g+rwx,o+rx {} + 2>/dev/null
        find $DEPLOY_DIR -path $DEPLOY_DIR/.git -prune -o -type f -exec chmod g+rw,o+r {} + 2>/dev/null
        chmod 600 $DEPLOY_DIR/.env 2>/dev/null || true

        # Restart services
        echo "🔄 Restarting development services..."
        docker restart $CONTAINER_NAME

        echo "✅ Development deployment completed!"
        echo "🌐 https://erp-dev.phantom.eu.org"

    elif [ "$branch" = "main" ]; then
        echo "🏭 Deploying main branch to PRODUCTION environment..."

        # Production deployment directory
        DEPLOY_DIR="/var/www/virtuals/docker/erp-prod"
        CONTAINER_NAME="erp-php-prod"
        BACKUP_DIR="/var/www/virtuals/docker/backups"

        # Create backup directory if not exists
        mkdir -p $BACKUP_DIR

        # Create backup (code only: storage/vendor/node_modules are excluded —
        # user data is backed up separately, deps are rebuilt by composer)
        if [ -d "$DEPLOY_DIR" ]; then
            echo "📦 Creating production backup..."
            rsync -a --exclude 'storage/' --exclude 'vendor/' --exclude 'node_modules/' \
                $DEPLOY_DIR/ $BACKUP_DIR/erp-prod.backup.$(date +%Y%m%d_%H%M%S)/ \
                || echo "⚠️ Backup completed with warnings (some files unreadable)"
            # Retention: keep only the 3 newest backups
            ls -1dt $BACKUP_DIR/erp-prod.backup.* 2>/dev/null | tail -n +4 | xargs -r rm -rf
        fi

        # Deploy latest code
        echo "📥 Deploying code to production..."
        git --work-tree=$DEPLOY_DIR --git-dir=/var/www/virtuals/git.phantom.eu.org/erp.git checkout -f main \
            || { echo "❌ PRODUCTION DEPLOY FAILED: git checkout"; continue; }

        # Bake the deployed version (git describe on the pushed rev) so the
        # app can display it — the worktree has no .git at runtime.
        mkdir -p $DEPLOY_DIR/storage/app
        git --git-dir=/var/www/virtuals/git.phantom.eu.org/erp.git describe --tags --always --match 'v[0-9]*' $newrev \
            > $DEPLOY_DIR/storage/app/version.txt 2>/dev/null \
            || echo "dev" > $DEPLOY_DIR/storage/app/version.txt

        # Remove dev-only artifacts from production (they ship via git
        # checkout but are never needed at runtime). package.json is removed
        # here so the npm step below stays inert on the PHP container.
        echo "🗑️ Removing dev-only files from production..."
        rm -rf "$DEPLOY_DIR/docs" "$DEPLOY_DIR/tests" \
            "$DEPLOY_DIR/database/factories" "$DEPLOY_DIR/.devin" \
            "$DEPLOY_DIR/node_modules" "$DEPLOY_DIR/phpunit.xml" \
            "$DEPLOY_DIR/vite.config.js" "$DEPLOY_DIR/package.json" \
            "$DEPLOY_DIR/package-lock.json" "$DEPLOY_DIR/AGENTS.md" \
            "$DEPLOY_DIR/ARTISAN_COMMANDS.md"

        # Setup production environment
        echo "🔧 Setting up production environment..."
        cd $DEPLOY_DIR

        # Use production .env if exists
        if [ -f ".env.production" ]; then
            echo "📝 Using production environment file..."
            cp .env.production .env
            chmod 600 .env 2>/dev/null || true
        fi

        # Install dependencies
        echo "📦 Installing production dependencies..."
        if [ -f "composer.json" ]; then
            docker exec $CONTAINER_NAME composer install --no-dev --optimize-autoloader
        fi

        # Frontend build only when the container actually ships npm
        if [ -f "package.json" ] && docker exec $CONTAINER_NAME sh -c 'command -v npm' >/dev/null 2>&1; then
            docker exec $CONTAINER_NAME npm install
            docker exec $CONTAINER_NAME npm run build
        fi

        # Clear caches
        echo "🧹 Clearing production caches..."
        docker exec $CONTAINER_NAME php artisan config:clear
        docker exec $CONTAINER_NAME php artisan cache:clear
        docker exec $CONTAINER_NAME php artisan view:clear

        # Ensure the public storage symlink exists (host path so nginx can follow it)
        ln -sfn "$DEPLOY_DIR/storage/app/public" "$DEPLOY_DIR/public/storage"
        chown -h www-data:www-data "$DEPLOY_DIR/public/storage" 2>/dev/null || true

        # Optimize for production
        echo "⚡ Optimizing for production..."
        docker exec $CONTAINER_NAME php artisan config:cache
        docker exec $CONTAINER_NAME php artisan route:cache
        docker exec $CONTAINER_NAME php artisan view:cache

        # Fix permissions — ACL-safe (see header note)
        echo "🔒 Fixing production permissions..."
        chown -R www-data:www-data $DEPLOY_DIR 2>/dev/null || true
        find $DEPLOY_DIR -path $DEPLOY_DIR/.git -prune -o -type d -exec chmod g+rwx,o+rx {} + 2>/dev/null
        find $DEPLOY_DIR -path $DEPLOY_DIR/.git -prune -o -type f -exec chmod g+rw,o+r {} + 2>/dev/null
        chmod 600 $DEPLOY_DIR/.env 2>/dev/null || true

        # Restart services
        echo "🔄 Restarting production services..."
        docker restart $CONTAINER_NAME

        echo "✅ Production deployment completed!"
        echo "🌐 https://erp-prod.phantom.eu.org"
        echo "🔍 Test production: curl -I https://erp-prod.phantom.eu.org"

        # Production notification
        echo "📢 PRODUCTION DEPLOYMENT NOTIFICATION:"
        echo "   Branch: main"
        echo "   Commit: $(git --git-dir=/var/www/virtuals/git.phantom.eu.org/erp.git rev-parse --short $newrev)"
        echo "   Time: $(date)"
        echo "   Container: $CONTAINER_NAME"
        echo "   URL: https://erp-prod.phantom.eu.org"
        echo "   Backup: $BACKUP_DIR/erp-prod.backup.$(date +%Y%m%d_%H%M%S)"

    else
        echo "🌿 Branch $branch pushed - no deployment"
    fi
done
