#!/usr/bin/env bash
# 06-switch — adoção do PGDATA (quando necessário) + down seguro + vendor novo + up.
#
# A stack viva pode ser a do nome novo ou a anterior do checkout (ADR-055). Em ambos os
# casos `tools/pgdata-adopt.sh --check` decide: 0 = bind ativo; 10 = copiar o cluster do
# volume anônimo para ${DATA_PATH}/pgdata (com o postgres parado); 11/12 = ambíguo/
# inacessível, aborta (o backup já foi feito). A cópia acontece antes do down e do up novo.
# O banco nunca é apagado (down sem -v); o vendor e a imagem anteriores são recuperáveis.
set -Eeuo pipefail
# shellcheck source=../lib/common.sh
. "$(dirname "$0")/../lib/common.sh"

phase_begin "06-switch"

project_resolve

if [ "$DRY_RUN" = 1 ]; then
    log "[dry-run] pgdata-adopt --check na stack '${STACK_PROJECT}' (10 ⇒ cópia do volume para ${DATA_PATH_V}/pgdata)"
    if [ "$STACK_PROJECT" != "$PROJECT_NAME" ]; then
        log "[dry-run] docker compose -p ${STACK_PROJECT} down --remove-orphans (adoção)"
    else
        log "[dry-run] docker compose -p ${PROJECT_NAME} down --remove-orphans"
    fi
    log "[dry-run] preservaria vendor atual; composer install --no-dev --no-scripts (novo vendor)"
    log "[dry-run] docker compose -p ${PROJECT_NAME} up -d --remove-orphans --wait --wait-timeout 300"
    phase_end
    exit 0
fi

# ------------------------------------------------- 1) PGDATA + derrubar a stack viva
if [ "${#STACK_COMPOSE[@]}" -gt 0 ]; then
    adopt_rc=0
    bash "$ROOT/tools/pgdata-adopt.sh" --check --project "$STACK_PROJECT" --data-path "$DATA_PATH_V" || adopt_rc=$?
    case "$adopt_rc" in
        0) log "PGDATA já é o bind ativo; nada a copiar" ;;
        10)
            log "PGDATA no volume anônimo da stack ${STACK_PROJECT}: copiando para ${DATA_PATH_V}/pgdata"
            run bash "$ROOT/tools/pgdata-adopt.sh" --copy --project "$STACK_PROJECT" --data-path "$DATA_PATH_V"
            ;;
        11) die "PGDATA ambíguo (já há um cluster no bind do host). Intervenção manual necessária; backup preservado." ;;
        12) die "PGDATA inacessível no layout antigo. Intervenção manual necessária; backup preservado." ;;
        *) die "pgdata-adopt retornou código inesperado: ${adopt_rc}" ;;
    esac

    if [ "$STACK_PROJECT" != "$PROJECT_NAME" ]; then
        log "adotando '${STACK_PROJECT}' como '${PROJECT_NAME}': derrubando a stack antiga"
        run "${STACK_COMPOSE[@]}" down --remove-orphans
    else
        run "${COMPOSE[@]}" down --remove-orphans
    fi
else
    run "${COMPOSE[@]}" down --remove-orphans
fi

# ------------------------------------------------- 2) vendor novo (sem banco)
vendor_pre=''
if [ -d "$ROOT/vendor" ]; then
    ensure_dir "$ROOT/storage/framework"
    vendor_pre="$ROOT/storage/framework/vendor.pre-${RUN_ID}"
    mv "$ROOT/vendor" "$vendor_pre"
    state_set VENDOR_PRE "$vendor_pre"
    log "vendor anterior preservado em ${vendor_pre}"
fi

log "+ composer install (imagem nova, sem scripts; banco ainda parado)"
if ! docker run --rm \
    --entrypoint composer \
    --user "$(id -u):$(id -g)" \
    -e HOME=/tmp \
    -v "$ROOT":/var/www/html"$MOUNT_LABEL" \
    -w /var/www/html \
    "$PHP_IMAGE:$PHP_TAG" \
    install --no-dev --no-scripts --prefer-dist --no-progress \
    --optimize-autoloader --classmap-authoritative --no-interaction; then
    if [ -d "$ROOT/vendor" ]; then
        mv "$ROOT/vendor" "$ROOT/storage/framework/vendor.failed-${RUN_ID}" || true
    fi
    if [ -n "$vendor_pre" ] && [ -d "$vendor_pre" ]; then
        mv "$vendor_pre" "$ROOT/vendor"
    fi
    warn "composer install falhou; religando a stack com o vendor anterior"
    "${COMPOSE[@]}" up -d --remove-orphans --wait --wait-timeout 300 || true
    die "composer install falhou — atualização abortada (backup preservado)"
fi

# ------------------------------------------------- 3) subir o projeto novo
if ! "${COMPOSE[@]}" up -d --remove-orphans --wait --wait-timeout 300; then
    dump_compose_logs
    warn "up com a imagem nova falhou; tentando a imagem :previous"
    if docker image inspect "$PHP_IMAGE:previous" >/dev/null 2>&1; then
        docker tag "$PHP_IMAGE:previous" "$PHP_IMAGE:$PHP_TAG"
        if ! "${COMPOSE[@]}" up -d --remove-orphans --wait --wait-timeout 300; then
            dump_compose_logs
            die "up falhou também com a imagem anterior — stack precisa de intervenção (backup registrado no log)"
        fi
        warn "stack no ar com a imagem anterior; o código novo permanece no checkout"
    else
        dump_compose_logs
        die "up falhou e não existe imagem :previous — stack precisa de intervenção (backup registrado no log)"
    fi
fi

wait_stack 180
"${COMPOSE[@]}" ps

phase_end
