#!/bin/bash
# ============================================================
# ESTAIR Connect - Script de deploiement HOMOLOGATION
# Usage: ./deploy-staging.sh [service] [--skip-backup] [--skip-migrate]
#   service: auth | estair | chaps | messager | spc-last | ftp-air | frontend | all
# ============================================================

set -e

# Configuration Staging
DEPLOY_ROOT="/home/ceterisprime/public_html/app/connect"
BACKUP_DIR="$DEPLOY_ROOT/backups"
PHP_BIN="php"
COMPOSER_BIN="composer"
GIT_BRANCH="master"
DATE=$(date +%Y%m%d_%H%M%S)

# Detecter le Python 3 le plus recent disponible (3.11 > 3.9 > 3.8 > python3)
PYTHON_BIN="python3"
for py in python3.12 python3.11 python3.10 python3.9 python3.8; do
    if command -v "$py" &>/dev/null; then
        PYTHON_BIN="$py"
        break
    fi
done

# NODE_OPTIONS: tester si --openssl-legacy-provider est accepte par ce Node
# (certains builds Node/cPanel bloquent ce flag dans NODE_OPTIONS meme sur Node 17-20)
if command -v node &>/dev/null && NODE_OPTIONS="--openssl-legacy-provider" node -e "1" 2>/dev/null; then
    NODE_OPTIONS="--openssl-legacy-provider"
else
    NODE_OPTIONS=""
fi

# Git clone URL (auth via GIT_USER/GIT_TOKEN env vars if set by pipeline)
git_clone_url() {
    local REPO_SLUG=$1
    if [ -n "$GIT_USER" ] && [ -n "$GIT_TOKEN" ]; then
        echo "https://$GIT_USER:$GIT_TOKEN@bitbucket.org/alcyonpartners/$REPO_SLUG.git"
    else
        echo "https://bitbucket.org/alcyonpartners/$REPO_SLUG.git"
    fi
}

# Set git auth on existing remote (for fetch/pull on already-cloned repos)
git_set_remote_auth() {
    local REPO_SLUG=$1
    if [ -n "$GIT_USER" ] && [ -n "$GIT_TOKEN" ]; then
        git remote set-url origin "https://$GIT_USER:$GIT_TOKEN@bitbucket.org/alcyonpartners/$REPO_SLUG.git"
    fi
}

# Clear credentials from remote URL after operations
git_clear_remote_auth() {
    local REPO_SLUG=$1
    git remote set-url origin "https://bitbucket.org/alcyonpartners/$REPO_SLUG.git" 2>/dev/null || true
}

# Stop process by PID file (no sudo required)
stop_by_pidfile() {
    local PIDFILE=$1
    local NAME=$2
    if [ -f "$PIDFILE" ]; then
        local PID=$(cat "$PIDFILE" 2>/dev/null)
        if [ -n "$PID" ] && kill -0 "$PID" 2>/dev/null; then
            log_info "Arret de $NAME (PID $PID)..."
            kill "$PID" 2>/dev/null
            for i in $(seq 1 10); do
                if ! kill -0 "$PID" 2>/dev/null; then break; fi
                sleep 1
            done
            kill -9 "$PID" 2>/dev/null || true
        fi
        rm -f "$PIDFILE"
    fi
}

# Start queue worker for a Laravel service (no sudo required)
start_queue_worker() {
    local SERVICE=$1
    local QUEUES=$2
    local SERVICE_DIR="$DEPLOY_ROOT/$SERVICE"
    local PIDFILE="$SERVICE_DIR/storage/logs/queue-worker.pid"

    cd "$SERVICE_DIR"
    stop_by_pidfile "$PIDFILE" "$SERVICE queue worker"

    log_info "Demarrage du queue worker $SERVICE (queues: $QUEUES)..."
    nohup $PHP_BIN artisan queue:work database \
        --queue="$QUEUES" \
        --sleep=3 --tries=3 \
        >> storage/logs/queue-worker.log 2>&1 &
    echo $! > "$PIDFILE"
    disown
    log_info "Queue worker $SERVICE demarre (PID $(cat $PIDFILE))"
}

# Mapping service -> repo Bitbucket
declare -A REPO_MAP=(
    [auth]="iris_auth"
    [estair]="estair-api"
    [chaps]="chaps-api"
    [messager]="messager"
    [spc-last]="spc-last"
    [ftp_air]="watcher"
    [chaps-design]="chaps-front"
)

# Couleurs
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

log_info()  { echo -e "${GREEN}[INFO]${NC} $1"; }
log_warn()  { echo -e "${YELLOW}[WARN]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
log_step()  { echo -e "${BLUE}[DEPLOY]${NC} $1"; }

# ---- Health Check ----
health_check() {
    local SERVICE=$1
    local URL=""

    case $SERVICE in
        auth)     URL="http://localhost:8120" ;;
        estair)   URL="http://localhost:8110" ;;
        chaps)    URL="http://localhost:8111" ;;
        messager) URL="http://localhost:8112" ;;
        spc-last) URL="http://localhost:5100/api/v1/health" ;;
        frontend) URL="http://localhost:80" ;;
    esac

    sleep 3
    HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" "$URL" --max-time 15 2>/dev/null || echo "000")
    if [ "$HTTP_CODE" = "200" ] || [ "$HTTP_CODE" = "302" ]; then
        log_info "$SERVICE OK (HTTP $HTTP_CODE)"
        return 0
    else
        log_warn "$SERVICE health check: HTTP $HTTP_CODE"
        return 1
    fi
}

# ---- Deploiement Laravel ----
deploy_laravel() {
    local SERVICE=$1
    local DB_NAME=$2
    local SERVICE_DIR="$DEPLOY_ROOT/$SERVICE"

    log_step "========== Deploiement $SERVICE (staging) =========="

    mkdir -p "$SERVICE_DIR"

    # Verifier si le repo git est valide (nettoyer si corrompu)
    if [ -d "$SERVICE_DIR/.git" ]; then
        if ! git -C "$SERVICE_DIR" rev-parse --git-dir >/dev/null 2>&1; then
            log_warn "Repo git corrompu dans $SERVICE_DIR, suppression pour re-clone..."
            rm -rf "$SERVICE_DIR"
            mkdir -p "$SERVICE_DIR"
        fi
    fi

    # Initialiser le repo si premier deploiement
    if [ ! -d "$SERVICE_DIR/.git" ]; then
        local REPO_SLUG="${REPO_MAP[$SERVICE]}"
        if [ -z "$REPO_SLUG" ]; then
            log_error "Repo inconnu pour le service $SERVICE"
            return 1
        fi
        log_info "Premier deploiement: clone du repo $REPO_SLUG..."
        rm -rf "$SERVICE_DIR"
        git clone --branch "$GIT_BRANCH" "$(git_clone_url $REPO_SLUG)" "$SERVICE_DIR"
        cd "$SERVICE_DIR"

        # Creer .env si absent (premier deploiement)
        if [ ! -f ".env" ] && [ -f ".env.example" ]; then
            log_info "Creation du .env depuis .env.example..."
            cp .env.example .env
            # Configurer les variables staging
            sed -i "s|APP_ENV=.*|APP_ENV=staging|" .env
            sed -i "s|APP_DEBUG=.*|APP_DEBUG=false|" .env
            sed -i "s|DB_CONNECTION=.*|DB_CONNECTION=mysql|" .env
            sed -i "s|DB_HOST=.*|DB_HOST=127.0.0.1|" .env
            sed -i "s|DB_PORT=.*|DB_PORT=3306|" .env
            sed -i "s|DB_DATABASE=.*|DB_DATABASE=$DB_NAME|" .env
            sed -i "s|DB_USERNAME=.*|DB_USERNAME=ceterisprime_connect|" .env
            if [ -f "$DEPLOY_ROOT/.db_password" ]; then
                local DB_PASS=$(cat "$DEPLOY_ROOT/.db_password")
                sed -i "s|DB_PASSWORD=.*|DB_PASSWORD=$DB_PASS|" .env
            fi
            NEED_KEY_GENERATE=true
            log_info ".env staging configure"
        fi
    else
        cd "$SERVICE_DIR"

        # 1. Mode maintenance
        log_info "Activation du mode maintenance..."
        $PHP_BIN artisan down --render="errors::503" 2>/dev/null || true

        # 2. Backup BDD (optionnel)
        if [[ "$*" != *"--skip-backup"* ]]; then
            log_info "Backup de la base $DB_NAME..."
            mkdir -p "$BACKUP_DIR/$SERVICE"
            mysqldump -u ceterisprime_connect -p"$(cat $DEPLOY_ROOT/.db_password 2>/dev/null)" "$DB_NAME" \
                > "$BACKUP_DIR/$SERVICE/${DB_NAME}_${DATE}.sql" 2>/dev/null || log_warn "Backup echoue (non bloquant)"
            # Nettoyer les backups de plus de 30 jours
            find "$BACKUP_DIR/$SERVICE" -name "*.sql" -mtime +30 -delete 2>/dev/null || true
        fi

        # 3. Git pull
        local REPO_SLUG="${REPO_MAP[$SERVICE]}"
        git_set_remote_auth "$REPO_SLUG"
        log_info "Mise a jour du code depuis $GIT_BRANCH..."
        git fetch origin
        git reset --hard "origin/$GIT_BRANCH"
        git_clear_remote_auth "$REPO_SLUG"
    fi

    # 4. Composer install
    log_info "Installation des dependances PHP..."
    $COMPOSER_BIN install --no-dev --optimize-autoloader --no-interaction 2>&1

    # 4b. Generate app key (first deploy only, after composer install so vendor/ exists)
    if [ "${NEED_KEY_GENERATE:-}" = "true" ]; then
        log_info "Generation de la cle applicative..."
        $PHP_BIN artisan key:generate --force
    fi

    # 5. Migrations
    if [[ "$*" != *"--skip-migrate"* ]]; then
        log_info "Execution des migrations..."
        $PHP_BIN artisan migrate --force
    fi

    # 6. Cache (config:clear au lieu de config:cache car AUTH utilise env() en runtime)
    log_info "Optimisation du cache..."
    $PHP_BIN artisan config:clear
    $PHP_BIN artisan route:cache
    $PHP_BIN artisan view:cache
    $PHP_BIN artisan event:cache 2>/dev/null || true

    # 7. Permissions
    log_info "Ajustement des permissions..."
    chmod -R 775 storage bootstrap/cache 2>/dev/null || true
    chown -R ceterisprime:ceterisprime . 2>/dev/null || true

    # 8. Restart workers
    log_info "Restart des workers..."
    $PHP_BIN artisan queue:restart 2>/dev/null || true

    # 9. Fin maintenance
    log_info "Desactivation du mode maintenance..."
    $PHP_BIN artisan up

    # 10. Health check (non-fatal: ne pas bloquer le deploy si le service met du temps a demarrer)
    health_check "$SERVICE" || log_warn "Health check echoue pour $SERVICE (non bloquant)"

    log_info "========== $SERVICE deploye avec succes (staging) =========="
}

# ---- Deploiement SPC-LAST ----
deploy_spc_last() {
    local SERVICE_DIR="$DEPLOY_ROOT/spc-last"

    log_step "========== Deploiement SPC-Last (staging) =========="

    mkdir -p "$SERVICE_DIR"

    # Verifier si le repo git est valide (nettoyer si corrompu)
    if [ -d "$SERVICE_DIR/.git" ]; then
        if ! git -C "$SERVICE_DIR" rev-parse --git-dir >/dev/null 2>&1; then
            log_warn "Repo git corrompu, suppression pour re-clone..."
            rm -rf "$SERVICE_DIR"
            mkdir -p "$SERVICE_DIR"
        fi
    fi

    # Initialiser le repo si premier deploiement, sinon git pull
    if [ ! -d "$SERVICE_DIR/.git" ]; then
        log_info "Premier deploiement: clone du repo spc-last..."
        rm -rf "$SERVICE_DIR"
        git clone --branch "$GIT_BRANCH" "$(git_clone_url spc-last)" "$SERVICE_DIR"
        cd "$SERVICE_DIR"
        git_clear_remote_auth "spc-last"
    else
        cd "$SERVICE_DIR"

        # Git pull
        git_set_remote_auth "spc-last"
        log_info "Mise a jour du code depuis $GIT_BRANCH..."
        git fetch origin
        git reset --hard "origin/$GIT_BRANCH"
        git_clear_remote_auth "spc-last"
    fi

    # 1. Arreter gunicorn existant (via PID file, sans sudo)
    stop_by_pidfile "$SERVICE_DIR/logs/gunicorn.pid" "gunicorn spc-flask"

    # 3. Installer les dependances Python
    log_info "Installation des dependances Python..."
    if [ -d "venv" ] && [ ! -f "venv/bin/activate" ]; then
        log_warn "venv corrompu (activate manquant), suppression et re-creation..."
        rm -rf venv
    fi
    # Recreer le venv si Python trop vieux (< 3.8 ne supporte pas Flask 3+ / watchdog 3+)
    if [ -d "venv" ] && [ -f "venv/bin/python" ]; then
        VENV_PY_MINOR=$(venv/bin/python -c "import sys; print(sys.version_info.minor)" 2>/dev/null || echo "6")
        if [ "$VENV_PY_MINOR" -lt 8 ]; then
            log_warn "venv utilise Python 3.$VENV_PY_MINOR (< 3.8), suppression pour re-creation avec $PYTHON_BIN..."
            rm -rf venv
        fi
    fi
    if [ ! -d "venv" ]; then
        log_info "Creation du virtualenv..."
        log_info "Utilisation de $PYTHON_BIN ($(${PYTHON_BIN} --version 2>&1))"
        $PYTHON_BIN -m venv venv || {
            log_error "Echec creation virtualenv. Verifiez que python3-venv est installe (apt install python3-venv)."
            return 1
        }
    fi
    source venv/bin/activate
    pip install --upgrade pip --quiet
    pip install -r requirements.txt --quiet
    deactivate

    # 4. Creer les dossiers necessaires
    mkdir -p logs traces

    # 5. Demarrer gunicorn en daemon mode (sans sudo)
    log_info "Demarrage de gunicorn spc-flask (port 5100 staging)..."
    source venv/bin/activate
    gunicorn \
        --bind 127.0.0.1:5100 \
        --workers 2 \
        --threads 2 \
        --timeout 600 \
        --pid logs/gunicorn.pid \
        --access-logfile logs/gunicorn_access.log \
        --error-logfile logs/gunicorn_error.log \
        --log-level info \
        --daemon \
        --chdir v2/api \
        flask_server:app
    deactivate

    if [ -f "logs/gunicorn.pid" ]; then
        log_info "Gunicorn demarre (PID $(cat logs/gunicorn.pid))"
    else
        log_warn "Gunicorn PID file non trouve - verifier les logs dans logs/gunicorn_error.log"
    fi

    # 6. Health check (non-fatal)
    sleep 5
    health_check "spc-last" || log_warn "Health check spc-last echoue (non bloquant)"

    log_step "========== SPC-Last deploye avec succes (staging) =========="
}

# ---- Deploiement FTP_AIR ----
deploy_ftp_air() {
    local SERVICE_DIR="$DEPLOY_ROOT/ftp_air"

    log_step "========== Deploiement FTP_AIR (staging) =========="

    mkdir -p "$SERVICE_DIR"

    # Verifier si le repo git est valide (nettoyer si corrompu)
    if [ -d "$SERVICE_DIR/.git" ]; then
        if ! git -C "$SERVICE_DIR" rev-parse --git-dir >/dev/null 2>&1; then
            log_warn "Repo git corrompu, suppression pour re-clone..."
            rm -rf "$SERVICE_DIR"
            mkdir -p "$SERVICE_DIR"
        fi
    fi

    # Initialiser le repo si premier deploiement, sinon git pull
    if [ ! -d "$SERVICE_DIR/.git" ]; then
        log_info "Premier deploiement: clone du repo watcher..."
        rm -rf "$SERVICE_DIR"
        git clone --branch "$GIT_BRANCH" "$(git_clone_url watcher)" "$SERVICE_DIR"
        cd "$SERVICE_DIR"
        git_clear_remote_auth "watcher"
    else
        cd "$SERVICE_DIR"

        # Git pull
        git_set_remote_auth "watcher"
        log_info "Mise a jour du code depuis $GIT_BRANCH..."
        git fetch origin
        git reset --hard "origin/$GIT_BRANCH"
        git_clear_remote_auth "watcher"
    fi

    # 2. Installer les dependances Python
    log_info "Installation des dependances Python..."
    if [ -d "venv" ] && [ ! -f "venv/bin/activate" ]; then
        log_warn "venv corrompu (activate manquant), suppression et re-creation..."
        rm -rf venv
    fi
    # Recreer le venv si Python trop vieux (< 3.8 ne supporte pas Flask 3+ / watchdog 3+)
    if [ -d "venv" ] && [ -f "venv/bin/python" ]; then
        VENV_PY_MINOR=$(venv/bin/python -c "import sys; print(sys.version_info.minor)" 2>/dev/null || echo "6")
        if [ "$VENV_PY_MINOR" -lt 8 ]; then
            log_warn "venv utilise Python 3.$VENV_PY_MINOR (< 3.8), suppression pour re-creation avec $PYTHON_BIN..."
            rm -rf venv
        fi
    fi
    if [ ! -d "venv" ]; then
        log_info "Creation du virtualenv..."
        log_info "Utilisation de $PYTHON_BIN ($(${PYTHON_BIN} --version 2>&1))"
        $PYTHON_BIN -m venv venv || {
            log_error "Echec creation virtualenv. Verifiez que python3-venv est installe (apt install python3-venv)."
            return 1
        }
    fi
    source venv/bin/activate
    pip install --upgrade pip --quiet
    pip install -r requirements.txt --quiet
    deactivate

    # 3. Creer les dossiers necessaires
    mkdir -p logs

    # 4. Redemarrer le service (supervisord ou systemd selon config)
    log_info "Restart du watcher FTP_AIR..."
    sudo supervisorctl restart staging-ftp-air 2>/dev/null || log_warn "Restart ftp_air echoue (service peut-etre pas configure)"

    log_step "========== FTP_AIR deploye avec succes (staging) =========="
}

# ---- Deploiement Frontend Angular ----
deploy_frontend() {
    local SERVICE_DIR="$DEPLOY_ROOT/chaps-design"

    log_step "========== Deploiement Frontend Angular (staging) =========="

    mkdir -p "$SERVICE_DIR"

    # Verifier si le repo git est valide (nettoyer si corrompu)
    if [ -d "$SERVICE_DIR/.git" ]; then
        if ! git -C "$SERVICE_DIR" rev-parse --git-dir >/dev/null 2>&1; then
            log_warn "Repo git corrompu, suppression pour re-clone..."
            rm -rf "$SERVICE_DIR"
            mkdir -p "$SERVICE_DIR"
        fi
    fi

    # Initialiser le repo si premier deploiement
    if [ ! -d "$SERVICE_DIR/.git" ]; then
        log_info "Premier deploiement: clone du repo chaps-front..."
        rm -rf "$SERVICE_DIR"
        git clone --branch "$GIT_BRANCH" "$(git_clone_url chaps-front)" "$SERVICE_DIR"
    fi

    cd "$SERVICE_DIR"

    # 1. Git pull
    git_set_remote_auth "chaps-front"
    log_info "Mise a jour du code depuis $GIT_BRANCH..."
    git fetch origin
    git reset --hard "origin/$GIT_BRANCH"
    git_clear_remote_auth "chaps-front"

    # 2. Installer les dependances
    log_info "Installation des dependances Node.js..."
    export NODE_OPTIONS="$NODE_OPTIONS"
    npm ci --production=false 2>&1

    # 3. Build staging (environment non-prod, URLs staging)
    log_info "Build staging Angular..."
    npm run build:staging 2>&1

    # 4. Verifier que le build a produit les fichiers
    if [ ! -d "dist/ESTAIR/browser" ]; then
        log_error "Le build Angular n'a pas produit dist/ESTAIR/browser/"
        return 1
    fi

    # 5. Ajuster les permissions
    chmod -R 755 dist/
    chown -R ceterisprime:ceterisprime dist/ 2>/dev/null || true

    log_info "Frontend Angular deploye (fichiers statiques dans dist/ESTAIR/browser/)"

    # 6. Health check (non-fatal)
    health_check "frontend" || log_warn "Health check frontend echoue (non bloquant)"

    log_step "========== Frontend deploye avec succes (staging) =========="
}

# ---- Execution ----

SERVICE=${1:-all}
EXTRA_ARGS="${@:2}"

case $SERVICE in
    auth)
        deploy_laravel "auth" "ceterisprime_auth" $EXTRA_ARGS
        ;;
    estair)
        deploy_laravel "estair" "ceterisprime_estair" $EXTRA_ARGS
        # Demarrer queue worker ESTAIR (sans sudo)
        start_queue_worker "estair" "notifications_high,notifications,notifications_low,bulk_notifications,spc_selling,default"
        ;;
    chaps)
        deploy_laravel "chaps" "ceterisprime_chaps" $EXTRA_ARGS
        ;;
    messager)
        deploy_laravel "messager" "ceterisprime_messager" $EXTRA_ARGS
        # Demarrer queue worker MESSAGER (sans sudo)
        start_queue_worker "messager" "default,bmp_operations,spc_appro,air_parse,bmp_daily_collection,estair_default"
        ;;
    spc-last)
        deploy_spc_last
        ;;
    ftp-air)
        deploy_ftp_air
        ;;
    frontend)
        deploy_frontend
        ;;
    all)
        log_step "Deploiement de TOUS les services (staging)..."

        deploy_laravel "auth" "ceterisprime_auth" $EXTRA_ARGS
        deploy_laravel "estair" "ceterisprime_estair" $EXTRA_ARGS
        deploy_laravel "chaps" "ceterisprime_chaps" $EXTRA_ARGS
        deploy_laravel "messager" "ceterisprime_messager" $EXTRA_ARGS
        deploy_spc_last
        deploy_ftp_air
        deploy_frontend

        # Reload Apache
        log_info "Reload Apache..."
        sudo systemctl reload httpd 2>/dev/null || sudo systemctl reload apache2 2>/dev/null || log_warn "Reload Apache echoue"

        # Demarrer les queue workers (sans sudo)
        start_queue_worker "estair" "notifications_high,notifications,notifications_low,bulk_notifications,spc_selling,default"
        start_queue_worker "messager" "default,bmp_operations,spc_appro,air_parse,bmp_daily_collection,estair_default"

        echo ""
        log_info "============================================"
        log_info "  TOUS les services staging ont ete deployes !"
        log_info "============================================"
        ;;
    *)
        echo "Usage: $0 [auth|estair|chaps|messager|spc-last|ftp-air|frontend|all] [--skip-backup] [--skip-migrate]"
        exit 1
        ;;
esac
