#!/bin/bash
set -e
export PATH=$PATH:/opt/cpanel/ea-nodejs22/bin


# ============================================================
# Laravel Deployment Script
# Supports: preview and production environments
# ============================================================
# App name is dynamically derived from .env APP_NAME value

# Source common functions library
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
if [[ -f "${SCRIPT_DIR}/scripts/_common.sh" ]]; then
    source "${SCRIPT_DIR}/scripts/_common.sh"
else
    # Minimal fallback if _common.sh not found
    log_pass() { echo "✅ $*"; }
    log_fail() { echo "❌ $*"; exit 1; }
    log_warn() { echo "⚠️  $*"; }
    log_say()  { echo "$*"; }
fi

# -------------------------
# PHP Version Configuration
# -------------------------
PHP_BIN=$(detect_php_binary 2>/dev/null || echo "php")
COMPOSER_BIN="/usr/local/bin/composer"

# Fallback to system binaries if cPanel paths don't exist
if [[ ! -f "$COMPOSER_BIN" ]]; then
    COMPOSER_BIN="composer"
fi

PHP_BIN_DIR="$(dirname "$PHP_BIN")"
export PATH="$PHP_BIN_DIR:$PATH"

# Create aliases for convenience
alias php="$PHP_BIN"
alias composer="$PHP_BIN $COMPOSER_BIN"

# Colors for output (fallback if _common.sh not sourced)
if [[ -z "${RED:-}" ]]; then
    RED='\033[0;31m'
    GREEN='\033[0;32m'
    YELLOW='\033[1;33m'
    NC='\033[0m' # No Color
fi

say()  { echo -e "${NC}$*"; }
pass() { echo -e "${GREEN}✅ $*${NC}"; }

# -------------------------
# Rollback Function
# -------------------------
rollback() {
    warn "Deployment encountered an error — attempting rollback..."
    $PHP_BIN artisan up 2>/dev/null || true
    warn "Application brought back online. Investigate the error above and redeploy."

    # Notify Slack on failure if configured
    SLACK_WEBHOOK_URL_ERR=$(grep '^SLACK_WEBHOOK_URL=' .env 2>/dev/null | cut -d '=' -f2 | tr -d '"' | tr -d "'" || echo "")
    if [[ -n "$SLACK_WEBHOOK_URL_ERR" ]]; then
        curl -sf -X POST "$SLACK_WEBHOOK_URL_ERR" \
            -H 'Content-Type: application/json' \
            -d "{\"text\":\"❌ Deploy FAILED: ${APP_NAME_DISPLAY:-app} on $(hostname) at $(date)\"}" \
            > /dev/null 2>&1 || true
    fi
}
trap rollback ERR
warn() { echo -e "${YELLOW}⚠️  $*${NC}"; }
fail() { echo -e "${RED}❌ $*${NC}"; exit 1; }

# -------------------------
# Environment Detection
# -------------------------
DEPLOY_ENV="unknown"
if [[ $PWD == *"preview"* ]]; then
    DEPLOY_ENV="preview"
    ENV_FILE=".env.preview"
elif [[ $PWD == *"production"* ]]; then
    DEPLOY_ENV="production"
    ENV_FILE=".env.production"
else
    warn "Could not detect environment from path. Assuming local."
    DEPLOY_ENV="local"
    ENV_FILE=""
fi

# Get app name from .env for display
if [[ -n "$ENV_FILE" && -f "$ENV_FILE" ]]; then
    APP_NAME_DISPLAY=$(grep "^APP_NAME=" "$ENV_FILE" | cut -d'=' -f2 | tr -d '"' | tr -d "'" | xargs)
elif [[ -f ".env" ]]; then
    APP_NAME_DISPLAY=$(grep "^APP_NAME=" .env | cut -d'=' -f2 | tr -d '"' | tr -d "'" | xargs)
else
    APP_NAME_DISPLAY="Laravel App"
fi

# Get app name slug for supervisor
APP_NAME_SLUG=$(get_app_name_slug "$ENV_FILE" 2>/dev/null || basename "$(pwd)" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9-]//g')
SUPERVISOR_PROG="${APP_NAME_SLUG}-horizon"
if [[ "$DEPLOY_ENV" == "production" ]]; then
    SUPERVISOR_PROG="${APP_NAME_SLUG}-production-horizon"
elif [[ "$DEPLOY_ENV" == "preview" ]]; then
    SUPERVISOR_PROG="${APP_NAME_SLUG}-preview-horizon"
fi

say ""
say "============================================================"
DEPLOY_ENV_LABEL=$(printf '%s' "$DEPLOY_ENV" | tr '[:lower:]' '[:upper:]')
say "🚀 ${APP_NAME_DISPLAY} Deployment - ${DEPLOY_ENV_LABEL}"
say "============================================================"
say "Started at: $(date)"
say ""

# -------------------------
# Pre-Deploy Safety Checks
# -------------------------
# Refuse to deploy with APP_DEBUG=true — would expose raw stack traces to end users.
if [[ "$DEPLOY_ENV" == "production" ]]; then
    APP_DEBUG_VALUE=$(grep -E "^APP_DEBUG=" .env 2>/dev/null | cut -d'=' -f2 | xargs | tr '[:upper:]' '[:lower:]')
    if [ "$APP_DEBUG_VALUE" = "true" ]; then
        fail "APP_DEBUG=true detected in production .env — refusing to deploy. Set APP_DEBUG=false first."
    fi
    say "APP_DEBUG: ${APP_DEBUG_VALUE:-false}"
fi

# -------------------------
# Step 1: Redis Health Check
# -------------------------
say "Step 1: Checking Redis availability..."

if [[ "$DEPLOY_ENV" == "local" ]]; then
    warn "Skipping Redis health check for local run (Step 12 validates if needed)"
else
    # Check PHP Redis extension is installed
    if ! $PHP_BIN -m 2>/dev/null | grep -q "^redis$"; then
        fail "PHP Redis extension (phpredis) is not installed!\nInstall it with:\n  - macOS: pecl install redis\n  - Ubuntu: apt install php-redis\n  - CentOS: yum install php-pecl-redis"
    fi
    pass "PHP Redis extension is installed"

    # Check if redis-cli is available
    if command -v redis-cli >/dev/null 2>&1; then
        # Use environment-specific file if set, otherwise fall back to .env
        ENV_SOURCE="${ENV_FILE:-.env}"
        [[ ! -f "$ENV_SOURCE" ]] && ENV_SOURCE=".env"
        REDIS_HOST=$(grep "^REDIS_HOST=" "$ENV_SOURCE" | cut -d'=' -f2 | sed 's/#.*//' | tr -d '"' | tr -d "'" | xargs || echo "127.0.0.1")
        REDIS_PORT=$(grep "^REDIS_PORT=" "$ENV_SOURCE" | cut -d'=' -f2 | sed 's/#.*//' | tr -d '"' | tr -d "'" | xargs || echo "6379")
        REDIS_PASSWORD=$(grep "^REDIS_PASSWORD=" "$ENV_SOURCE" | cut -d'=' -f2 | sed 's/#.*//' | tr -d '"' | tr -d "'" | xargs || echo "")

        # Build redis-cli command with optional auth.
        # Use REDISCLI_AUTH env var instead of -a flag to avoid password in process listing.
        REDIS_CMD="redis-cli -h $REDIS_HOST -p $REDIS_PORT"
        if [[ -n "$REDIS_PASSWORD" && "$REDIS_PASSWORD" != "null" ]]; then
            export REDISCLI_AUTH="$REDIS_PASSWORD"
        fi

        REDIS_PING=$($REDIS_CMD ping 2>/dev/null || echo "FAILED")
        if [[ "$REDIS_PING" == "PONG" ]]; then
            pass "Redis is running at $REDIS_HOST:$REDIS_PORT"
        else
            fail "Redis is not responding at $REDIS_HOST:$REDIS_PORT. Redis is REQUIRED for session, cache, and queue.\nPlease ensure Redis is installed and running:\n  - macOS: brew services start redis\n  - Linux: sudo systemctl start redis\n  - Check REDIS_HOST, REDIS_PORT, REDIS_PASSWORD in .env"
        fi
    else
        warn "redis-cli not found - skipping Redis health check"
        warn "Ensure Redis is running manually before proceeding"
    fi
fi

# -------------------------
# Step 2: Environment File Validation
# -------------------------
say "Step 2: Validating environment configuration..."

if [[ -n "$ENV_FILE" && -f "$ENV_FILE" ]]; then
    diff .env "$ENV_FILE" || {
        fail "Env diff failed! .env does not match $ENV_FILE\nPlease check the files manually and run this script again."
    }
    pass "Environment file matches $ENV_FILE"
else
    warn "No $ENV_FILE found - skipping diff check"
fi

# Validate critical env vars exist (skip for local runs)
if [[ "$DEPLOY_ENV" != "local" ]]; then
    REQUIRED_VARS=("APP_KEY" "APP_URL" "DB_CONNECTION" "DB_DATABASE")
    for var in "${REQUIRED_VARS[@]}"; do
        if ! grep -q "^${var}=" .env; then
            fail "Missing required env var: $var"
        fi
    done

    # BREACH_AUTHORITY_EMAIL must be non-empty (key existence alone is insufficient)
    BREACH_AUTHORITY_EMAIL_VALUE=$(grep "^BREACH_AUTHORITY_EMAIL=" .env | cut -d'=' -f2 | xargs)
    if [ -z "$BREACH_AUTHORITY_EMAIL_VALUE" ]; then
        fail "BREACH_AUTHORITY_EMAIL must be set to a non-empty value"
    fi

    # BOUNCE_WEBHOOK_TOKEN must be set to a non-empty value (empty = unauthenticated open endpoint)
    BOUNCE_WEBHOOK_TOKEN_VALUE=$(grep "^BOUNCE_WEBHOOK_TOKEN=" .env | cut -d'=' -f2 | xargs)
    if [ -z "$BOUNCE_WEBHOOK_TOKEN_VALUE" ]; then
        fail "BOUNCE_WEBHOOK_TOKEN must be set to a non-empty value (protects the bounce webhook endpoint)"
    fi

    # HEALTH_CHECK_TOKEN must not be the placeholder value
    HEALTH_CHECK_TOKEN_VALUE=$(grep -E "^HEALTH_CHECK_TOKEN=" .env 2>/dev/null | cut -d'=' -f2 | tr -d '[:space:]')
    if [ "$HEALTH_CHECK_TOKEN_VALUE" = "change-me-generate-with-random-bytes" ]; then
        fail "HEALTH_CHECK_TOKEN is still the placeholder value — generate a real token with: php -r \"echo bin2hex(random_bytes(32));\""
    fi

    # DSAR_CONTACT_EMAIL must not be the placeholder value (GDPR Art. 17 erasure requests)
    DSAR_EMAIL_VALUE=$(grep -E "^DSAR_CONTACT_EMAIL=" .env 2>/dev/null | cut -d'=' -f2 | tr -d '[:space:]')
    if [[ "$DSAR_EMAIL_VALUE" == *"your-domain"* ]]; then
        fail "DSAR_CONTACT_EMAIL is still the placeholder value — set to your actual privacy contact email"
    fi

    # POSTHOG analytics advisory (not a hard failure — product analytics can be enabled post-launch)
    POSTHOG_API_KEY_VALUE=$(grep -E "^POSTHOG_API_KEY=" .env 2>/dev/null | cut -d'=' -f2 | tr -d '[:space:]')
    VITE_POSTHOG_API_KEY_VALUE=$(grep -E "^VITE_POSTHOG_API_KEY=" .env 2>/dev/null | cut -d'=' -f2 | tr -d '[:space:]')
    if [ -z "$POSTHOG_API_KEY_VALUE" ] && [ -z "$VITE_POSTHOG_API_KEY_VALUE" ]; then
        warn "PostHog is not configured — product analytics will be disabled at launch"
    fi

    # BUNDLED_AI_API_KEY rotation tracking (advisory warning — does not block deploy)
    # If bundled AI is enabled but no rotation date is tracked, warn the operator.
    BUNDLED_AI_ENABLED_VALUE=$(grep "^BUNDLED_AI_ENABLED=" .env | cut -d'=' -f2 | xargs)
    if [ "$BUNDLED_AI_ENABLED_VALUE" = "true" ] || [ "$BUNDLED_AI_ENABLED_VALUE" = "1" ]; then
        BUNDLED_AI_KEY_LAST_ROTATED_VALUE=$(grep "^BUNDLED_AI_KEY_LAST_ROTATED=" .env | cut -d'=' -f2 | xargs)
        if [ -z "$BUNDLED_AI_KEY_LAST_ROTATED_VALUE" ]; then
            warn "BUNDLED_AI_KEY_LAST_ROTATED is not set. Set it to the date BUNDLED_AI_API_KEY was last rotated (YYYY-MM-DD). Run 'php artisan security:check-key-age --type=bundled_ai_key' to check rotation status."
        fi
    fi

    # CSP enforcement check (advisory warning — does not block deploy)
    # Report-only mode silently swallows CSP violations without enforcing policy.
    CSP_REPORT_ONLY_VALUE=$(grep "^CSP_REPORT_ONLY=" .env | cut -d'=' -f2 | xargs)
    if [ "$CSP_REPORT_ONLY_VALUE" = "true" ] || [ "$CSP_REPORT_ONLY_VALUE" = "1" ]; then
        warn "CSP_REPORT_ONLY=true in production — CSP header will be Content-Security-Policy-Report-Only (not enforced). Set CSP_REPORT_ONLY=false to enforce."
    fi

    # MAIL_PORT=1025 check — Mailpit dev server port, will silently drop all emails in production.
    MAIL_PORT_VALUE=$(grep "^MAIL_PORT=" .env 2>/dev/null | cut -d'=' -f2 | xargs)
    if [ "$MAIL_PORT_VALUE" = "1025" ]; then
        warn "MAIL_PORT=1025 detected — this typically points to a local Mailpit dev server. Verify your mail provider is configured correctly (Postmark/SES use port 587)."
    fi

    # HEALTHCHECK_PING_URL check (advisory warning — does not block deploy)
    # Without this, scheduler death goes undetected until a user reports it.
    HEALTHCHECK_PING_URL_VALUE=$(grep "^HEALTHCHECK_PING_URL=" .env 2>/dev/null | cut -d'=' -f2 | xargs)
    if [ -z "$HEALTHCHECK_PING_URL_VALUE" ]; then
        warn "HEALTHCHECK_PING_URL is not set — scheduler downtime will go undetected. Create a free check at https://healthchecks.io and add the ping URL."
    fi

    pass "Required environment variables present"
else
    warn "Skipping required env var checks for local run"
fi

# -------------------------
# Step 2b: Ensure .htaccess Files (preview/production only)
# -------------------------
say ""
say "Step 2b: Ensuring .htaccess files exist..."

if [[ "$DEPLOY_ENV" == "preview" || "$DEPLOY_ENV" == "production" ]]; then
    HTACCESS_VPS_FILES=(".htaccess.vps" "public/.htaccess.vps")
    for vps_file in "${HTACCESS_VPS_FILES[@]}"; do
        if [[ -f "$vps_file" ]]; then
            target_file="${vps_file%.vps}"
            if [[ -f "$target_file" ]]; then
                warn "$target_file already exists - leaving as is"
            else
                cp "$vps_file" "$target_file"
                pass "Copied $vps_file -> $target_file"
            fi
        else
            warn "Missing $vps_file - skipping"
        fi
    done
else
    warn "Skipping .htaccess setup for local run"
fi

# -------------------------
# Step 3: File Permissions
# -------------------------
say ""
say "Step 3: Setting file permissions..."

# Ensure plugin download directory exists (not web-accessible; zips served through controller)
mkdir -p storage/app/downloads

# Only adjust runtime-writable directories; avoid touching tracked files.
find storage bootstrap/cache -type d -exec chmod 775 {} \; 2>/dev/null || true
find storage -type f -name "*.log" -exec chmod 664 {} \; 2>/dev/null || true

# Detect app user for permission setting
APP_USER=$(detect_app_user 2>/dev/null || echo "")
if [[ -n "$APP_USER" ]]; then
    sudo chown -R "$APP_USER:$APP_USER" storage bootstrap/cache 2>/dev/null || true
fi

chmod 755 deploy.sh

pass "Runtime directory permissions set"

# -------------------------
# Step 4: Maintenance Mode
# -------------------------
say ""
say "Step 4: Entering maintenance mode..."
if ! $PHP_BIN artisan down --retry=60 --refresh=15; then
    warn "artisan down returned non-zero exit — application may already be in maintenance mode"
fi
pass "Maintenance mode enabled"

# -------------------------
# Step 5: Composer Dependencies
# -------------------------
say ""
say "Step 5: Installing PHP dependencies..."

COMPOSER_RUN="$PHP_BIN $COMPOSER_BIN"
if [[ "$DEPLOY_ENV" == "local" ]] && command -v composer >/dev/null 2>&1; then
    COMPOSER_RUN="composer"
fi

if [[ "$DEPLOY_ENV" == "production" ]]; then
    # Warn if QUEUE_CONNECTION is still database — Horizon requires Redis in production
    QUEUE_CONNECTION_VALUE=$(grep -E "^QUEUE_CONNECTION=" .env 2>/dev/null | cut -d'=' -f2 | tr -d '[:space:]')
    if [ "${QUEUE_CONNECTION_VALUE:-database}" = "database" ]; then
        warn "QUEUE_CONNECTION=database in production — Horizon requires Redis for proper queue monitoring. Set QUEUE_CONNECTION=redis."
    fi

    say "Production mode: installing without dev dependencies..."
    $COMPOSER_RUN install --no-dev --no-interaction --prefer-dist --optimize-autoloader
elif [[ "$DEPLOY_ENV" == "preview" ]]; then
    say "Preview mode: installing with dev dependencies..."
    $COMPOSER_RUN install --no-interaction --prefer-dist --optimize-autoloader
else
    say "Local mode: installing with dev dependencies..."
    $COMPOSER_RUN install --no-interaction --prefer-dist --optimize-autoloader
fi
pass "Composer dependencies installed"

# -------------------------
# Step 6: Clear All Caches
# -------------------------
say ""
say "Step 6: Clearing caches..."

$PHP_BIN artisan clear-compiled
$PHP_BIN artisan route:clear
$PHP_BIN artisan config:clear
$PHP_BIN artisan view:clear
$PHP_BIN artisan event:clear

pass "All caches cleared"

# -------------------------
# Step 7: NPM Build
# -------------------------
say ""
say "Step 7: Building frontend assets..."

rm -f public/hot public_html/hot
npm ci --prefer-offline

# Generate Ziggy routes before building (required for TypeScript route helpers)
$PHP_BIN artisan ziggy:generate

npm run build

pass "Frontend assets built"

# -------------------------
# Step 8: Database Migrations
# -------------------------
say ""
say "Step 8: Running database migrations..."

say "Step 8a: Validating migrations for rollback safety..."
if $PHP_BIN artisan migrate:validate; then
    pass "Migration validation passed"
else
    fail "Migration validation failed - aborting deployment"
fi

$PHP_BIN artisan migrate --force

# Generate API documentation (if Scribe is installed)
if $PHP_BIN artisan list 2>/dev/null | grep -q "scribe:generate"; then
    $PHP_BIN artisan scribe:generate --no-extraction 2>/dev/null || warn "Scribe generation failed - continuing"
    pass "API documentation generated"
fi

$PHP_BIN artisan optimize:clear
pass "Database migrations complete"

# -------------------------
# Step 8b: Seed Marketing Content
# -------------------------
say ""
say "Step 8b: Syncing marketing blog content..."
$PHP_BIN artisan db:seed --class=MarketingContentSeeder --force
pass "Marketing content synced"

# -------------------------
# Step 9: Rebuild Caches
# -------------------------
say ""
say "Step 9: Rebuilding optimization caches..."

$PHP_BIN artisan config:cache
$PHP_BIN artisan route:cache
$PHP_BIN artisan view:cache
$PHP_BIN artisan event:cache

pass "Optimization caches rebuilt"

# -------------------------
# Step 10: Exit Maintenance Mode
# -------------------------
say ""
say "Step 10: Exiting maintenance mode..."
$PHP_BIN artisan up
pass "Application is live"

# Health check against /up endpoint after exiting maintenance mode
APP_URL_CHECK=$(grep '^APP_URL=' .env 2>/dev/null | cut -d '=' -f2 | tr -d '"' | tr -d "'" || echo "")
if [[ -n "$APP_URL_CHECK" ]]; then
    say "  Verifying /up endpoint..."
    HEALTH_CODE=$(curl -sf -o /dev/null -w "%{http_code}" --max-time 15 "${APP_URL_CHECK}/up" 2>/dev/null || echo "000")
    if [[ "$HEALTH_CODE" == "200" ]]; then
        pass "Health check passed (HTTP 200)"
    else
        warn "Health check returned HTTP $HEALTH_CODE — application may not be fully ready"
    fi
fi

# -------------------------
# Step 11: Restart Queue Workers
# -------------------------
say ""
say "Step 11: Restarting queue workers..."
$PHP_BIN artisan queue:restart
pass "Queue restart signal sent"

# -------------------------
# Step 11b: Restart Horizon (if enabled)
# -------------------------
say ""
say "Step 11b: Restarting Horizon supervisor..."

# Check if Horizon feature is enabled
FEATURE_HORIZON=$(grep "^FEATURE_HORIZON=" .env 2>/dev/null | cut -d'=' -f2 | tr -d '"' | tr -d "'" | tr '[:upper:]' '[:lower:]' | xargs || echo "false")

if [[ "$FEATURE_HORIZON" == "true" ]] || [[ "$FEATURE_HORIZON" == "1" ]]; then
    if command -v supervisorctl &> /dev/null; then
        if supervisorctl status 2>/dev/null | grep -q "$SUPERVISOR_PROG"; then
            supervisorctl restart "$SUPERVISOR_PROG"
            pass "Horizon restarted via Supervisor"
        else
            warn "Horizon program ($SUPERVISOR_PROG) not found in Supervisor - skipping"
        fi
    else
        warn "supervisorctl not found - ensure Horizon is restarted manually"
    fi
else
    say "  Horizon not enabled (FEATURE_HORIZON != true) - skipping"
fi

# ============================================================
# APPLICATION-SPECIFIC VALIDATION CHECKS
# ============================================================

say ""
say "============================================================"
say "📋 Running Application Validation Checks..."
say "============================================================"


# -------------------------
# Step 12: Redis Connection Test via Laravel (if using Redis)
# -------------------------
say ""
say "Step 12: Testing Redis connection via Laravel (if configured)..."

# Check if any driver uses Redis
NEEDS_REDIS=false
for DRIVER_VAR in SESSION_DRIVER CACHE_STORE QUEUE_CONNECTION; do
    DRIVER_VALUE=$(grep "^${DRIVER_VAR}=" .env 2>/dev/null | cut -d'=' -f2 | tr -d '"' | tr -d "'" | xargs)
    if [[ "$DRIVER_VALUE" == "redis" ]]; then
        NEEDS_REDIS=true
        break
    fi
done

if [[ "$NEEDS_REDIS" == "false" ]]; then
    say "  No Redis-backed drivers configured - skipping"
else
    # Use inline PHP to test Redis connection (avoids PsySH trust issues)
    REDIS_TEST=$($PHP_BIN -r "
        require 'vendor/autoload.php';
        \$app = require_once 'bootstrap/app.php';
        \$app->make('Illuminate\Contracts\Console\Kernel')->bootstrap();
        try {
            \Illuminate\Support\Facades\Redis::ping();
            echo 'PONG';
        } catch (Exception \$e) {
            echo 'FAILED: ' . \$e->getMessage();
        }
    " 2>&1 || echo "FAILED: Script execution error")

    if [[ "$REDIS_TEST" == "PONG" ]]; then
        pass "Laravel can connect to Redis"
    else
        fail "Laravel cannot connect to Redis!\nCheck your REDIS_* configuration in .env\nError: $REDIS_TEST"
    fi
fi

# -------------------------
# Step 13: Configuration Validation
# -------------------------
say ""
say "Step 13: Validating application configuration..."

pass "Configuration validation passed"

# -------------------------
# Step 14: HTTP Health Checks
# -------------------------
say ""
say "Step 14: Running HTTP health checks..."

APP_URL_VALUE=$(grep '^APP_URL=' .env | cut -d '=' -f2 | tr -d '"' | tr -d "'")
HEALTH_TOKEN_VALUE=$(grep '^HEALTH_CHECK_TOKEN=' .env 2>/dev/null | cut -d '=' -f2 | tr -d '"' | tr -d "'" | xargs 2>/dev/null || echo "")

sleep 5

if [[ -n "$HEALTH_TOKEN_VALUE" ]]; then
    say "  Running release verification against ${APP_URL_VALUE}/health..."
    RELEASE_EXIT=0
    HEALTH_URL="${APP_URL_VALUE}/health" HEALTH_TOKEN="$HEALTH_TOKEN_VALUE" \
        bash "${SCRIPT_DIR}/scripts/release-verify.sh" || RELEASE_EXIT=$?

    if [[ $RELEASE_EXIT -eq 0 ]]; then
        pass "Application health check passed (healthy)"
    elif [[ $RELEASE_EXIT -eq 1 ]]; then
        warn "Application is degraded — operational but investigation recommended"
    else
        rollback
        fail "Application health check failed — application is unhealthy or unreachable"
    fi
else
    warn "HEALTH_CHECK_TOKEN not set — falling back to basic /up check"
    HEALTH_CODE=$(curl -s -o /dev/null -w "%{http_code}" --max-time 15 "${APP_URL_VALUE}/up" 2>/dev/null || echo "000")
    if [[ "$HEALTH_CODE" == "200" ]]; then
        pass "Basic health check passed (HTTP 200 from /up)"
    else
        warn "Basic health check returned HTTP $HEALTH_CODE"
    fi
fi

# -------------------------
# Step 15: Scheduled Tasks Check
# -------------------------
say ""
say "Step 15: Verifying scheduled tasks..."

SCHEDULE_CHECK=$($PHP_BIN artisan schedule:list 2>/dev/null | grep -c "artisan" || echo "0")
if [[ "$SCHEDULE_CHECK" -gt 0 ]]; then
    pass "Found $SCHEDULE_CHECK scheduled artisan commands"
else
    warn "No scheduled commands found - check routes/console.php"
fi

# ============================================================
# OPTIONAL POST-DEPLOY ACTIONS
# ============================================================

# -------------------------
# Step 16: Rebuild Sitemaps (if feature enabled)
# -------------------------
say ""
say "Step 16: Refreshing sitemap cache (if enabled)..."

FEATURE_SITEMAP=$(grep "^FEATURE_SITEMAP=" .env 2>/dev/null | cut -d'=' -f2 | tr -d '"' | tr -d "'" | tr '[:upper:]' '[:lower:]' | xargs || echo "false")

if [[ "$FEATURE_SITEMAP" == "true" ]] || [[ "$FEATURE_SITEMAP" == "1" ]]; then
    if $PHP_BIN artisan sitemap:refresh --force 2>/dev/null; then
        pass "Sitemap cache refreshed successfully"
    else
        warn "Sitemap refresh failed - will be regenerated on next request"
    fi
else
    say "  Sitemap feature not enabled (FEATURE_SITEMAP != true) - skipping"
fi

# ============================================================
# DEPLOYMENT COMPLETE
# ============================================================

say ""
say "============================================================"
pass "🎉 DEPLOYMENT COMPLETE - ${DEPLOY_ENV_LABEL}"
say "============================================================"

# Slack notification on success (optional — only if SLACK_WEBHOOK_URL is set)
SLACK_WEBHOOK_URL=$(grep '^SLACK_WEBHOOK_URL=' .env 2>/dev/null | cut -d '=' -f2 | tr -d '"' | tr -d "'" || echo "")
if [[ -n "$SLACK_WEBHOOK_URL" ]]; then
    curl -sf -X POST "$SLACK_WEBHOOK_URL" \
        -H 'Content-Type: application/json' \
        -d "{\"text\":\"✅ Deploy succeeded: ${APP_NAME_DISPLAY} (${DEPLOY_ENV_LABEL}) on $(hostname) at $(date)\"}" \
        > /dev/null 2>&1 || true
fi
say ""
say "Application: $APP_NAME_DISPLAY"
say "Environment: $DEPLOY_ENV"
say "URL: $APP_URL"
say "Completed at: $(date)"
say ""
say "Post-deployment scripts:"
say "  ./scripts/vps-verify.sh          - Full VPS verification"
if [[ "$FEATURE_HORIZON" == "true" ]] || [[ "$FEATURE_HORIZON" == "1" ]]; then
    say "  ./scripts/test-horizon.sh        - Test Horizon queue processing"
    say ""
    say "First-time Horizon setup (run once per server):"
    say "  ./scripts/setup-horizon.sh       - Install Supervisor config & start Horizon"
fi
say ""
