#!/bin/bash

set -Eeuo pipefail

BRANCH=${1:-main}
SERVICE_NAME=${2:-fpm}
APP_PATH=${APP_PATH:-/var/www/html/farmacia}
COMPOSE_DIR=${COMPOSE_DIR:-/var/www/farmacia}
COMPOSE_FILE=${COMPOSE_FILE:-$COMPOSE_DIR/docker-compose.yml}
HEALTHCHECK_URL=${HEALTHCHECK_URL:-https://demo.sysfarma.pe/login}
LOCK_FILE=${LOCK_FILE:-/var/lock/enterfarmaplus-deploy.lock}
STATE_DIR=${STATE_DIR:-/var/lib/enterfarmaplus-deploy}
LOG_FILE=${LOG_FILE:-/var/log/enterfarmaplus-deploy.log}
DOCKER_APP_SCRIPT=${DOCKER_APP_SCRIPT:-$APP_PATH/script-docker-app.sh}

if [ "$(id -u)" -ne 0 ]; then
  echo "Este deploy debe ejecutarse como root en el host Docker."
  exit 1
fi

for command_name in git docker flock curl; do
  if ! command -v "$command_name" >/dev/null 2>&1; then
    echo "Falta el comando requerido: $command_name"
    exit 1
  fi
done

if [ ! -d "$APP_PATH/.git" ]; then
  echo "No existe un repositorio git en $APP_PATH"
  exit 1
fi

if [ ! -x "$DOCKER_APP_SCRIPT" ]; then
  echo "No existe o no es ejecutable el helper Docker: $DOCKER_APP_SCRIPT"
  exit 1
fi

mkdir -p "$STATE_DIR"
touch "$LOG_FILE"
chmod 750 "$STATE_DIR"
chmod 640 "$LOG_FILE"

exec 9>"$LOCK_FILE"
if ! flock -n 9; then
  echo "Ya hay otro deploy de EnterFarmaPlus en ejecucion."
  exit 1
fi

exec > >(tee -a "$LOG_FILE") 2>&1

started_at=$(date -u +%Y-%m-%dT%H:%M:%SZ)
previous_commit=""
target_commit=""

on_error() {
  exit_code=$?
  echo "DEPLOY_ERROR timestamp=$(date -u +%Y-%m-%dT%H:%M:%SZ) previous=${previous_commit:-unknown} target=${target_commit:-unknown} exit=$exit_code"
  echo "No se hace rollback automatico: las migraciones pueden no ser reversibles."
  exit "$exit_code"
}
trap on_error ERR

docker_app() {
  SERVICE_NAME="$SERVICE_NAME" \
  APP_PATH="$APP_PATH" \
  COMPOSE_DIR="$COMPOSE_DIR" \
  COMPOSE_FILE="$COMPOSE_FILE" \
  "$DOCKER_APP_SCRIPT" "$@"
}

echo "DEPLOY_START timestamp=$started_at branch=$BRANCH"
cd "$APP_PATH"

current_branch=$(git branch --show-current)
if [ "$current_branch" != "$BRANCH" ]; then
  echo "Rama inesperada: actual=$current_branch esperada=$BRANCH"
  exit 1
fi

if [ -n "$(git status --porcelain)" ]; then
  echo "El arbol de produccion no esta limpio; deploy cancelado."
  git status --short
  exit 1
fi

previous_commit=$(git rev-parse HEAD)
git fetch --prune origin "$BRANCH"
target_commit=$(git rev-parse FETCH_HEAD)

if ! git merge-base --is-ancestor "$previous_commit" "$target_commit"; then
  echo "origin/$BRANCH no es avance fast-forward desde el HEAD actual."
  exit 1
fi

if [ "$previous_commit" != "$target_commit" ]; then
  git merge --ff-only "$target_commit"
else
  echo "Codigo ya alineado en $(git rev-parse --short HEAD)."
fi

# Los assets se compilan y versionan antes del push. Nunca se ejecuta npm aqui.
docker_app composer install --no-interaction --prefer-dist --optimize-autoloader --no-dev
docker_app artisan storage:link --force
docker_app artisan migrate --force --no-interaction
docker_app artisan tenancy:migrate --no-interaction
docker_app artisan optimize:clear
docker_app artisan config:cache || {
  echo "config:cache fallo; se deja la configuracion sin cachear."
  docker_app artisan config:clear
}
docker_app artisan route:clear
docker_app artisan view:clear
docker_app artisan queue:restart

# PHP solo necesita escritura en los directorios de runtime.
RUN_USER=root docker_app shell \
  "chown -R www-data:www-data storage bootstrap/cache && find storage bootstrap/cache -type d -exec chmod 775 {} + && find storage bootstrap/cache -type f -exec chmod 664 {} +"

if [ -n "$(git status --porcelain)" ]; then
  echo "El deploy dejo cambios en el arbol Git; se considera fallido."
  git status --short
  exit 1
fi

curl --fail --silent --show-error --location --max-time 20 \
  --output /dev/null "$HEALTHCHECK_URL"

deployed_commit=$(git rev-parse HEAD)
printf '%s\n' "$previous_commit" > "$STATE_DIR/previous-commit"
printf '%s\n' "$deployed_commit" > "$STATE_DIR/current-commit"
printf '%s\t%s\t%s\t%s\n' "$started_at" "$BRANCH" "$previous_commit" "$deployed_commit" \
  >> "$STATE_DIR/history.tsv"

echo "DEPLOY_OK timestamp=$(date -u +%Y-%m-%dT%H:%M:%SZ) head=$(git rev-parse --short HEAD) healthcheck=$HEALTHCHECK_URL"
