#!/bin/sh
set -eu

ACTION="${1:-${FRONT_APACHE_ACTION:-}}"
SITE_NAME="${FRONT_APACHE_SITE_NAME:-stackpos-front}"
CONFIG_PATH="${FRONT_APACHE_CONFIG_PATH:-}"
DISABLED_CONFIG_PATH="${FRONT_APACHE_DISABLED_CONFIG_PATH:-${CONFIG_PATH}.disabled}"
CONFIG_FILE_NAME="${FRONT_APACHE_CONFIG_FILE_NAME:-$(basename "$CONFIG_PATH")}"
DOCUMENT_ROOT="${FRONT_APACHE_DOCUMENT_ROOT:-}"
PUBLIC_URL="${FRONT_APACHE_PUBLIC_URL:-}"
TOPOLOGY="${FRONT_APACHE_TOPOLOGY:-same-origin}"
API_TARGET="${FRONT_APACHE_API_TARGET:-}"
CONTAINER_NAME="${FRONT_APACHE_CONTAINER_NAME:-}"
CONTAINER_CONFIG_PATH="${FRONT_APACHE_CONTAINER_CONFIG_PATH:-}"
CONTAINER_HTTPD_CONF_PATH="${FRONT_APACHE_CONTAINER_HTTPD_CONF_PATH:-/usr/local/apache2/conf/httpd.conf}"
VHOST_SOURCE_PATH="${FRONT_APACHE_VHOST_SOURCE_PATH:-}"

replace_sites_path() {
  printf '%s' "$1" | sed 's@/sites-available/@/sites-enabled/@'
}

CONTAINER_ENABLED_CONFIG_PATH="$(replace_sites_path "$CONTAINER_CONFIG_PATH")"

require_var() {
  name="$1"
  value="$2"
  if [ -z "$value" ]; then
    echo "Variable requise manquante: $name" >&2
    exit 1
  fi
}

run_root() {
  if [ "$(id -u)" -eq 0 ]; then
    sh -lc "$1"
    return
  fi
  if command -v sudo >/dev/null 2>&1 && sudo -n true >/dev/null 2>&1; then
    sudo -n sh -lc "$1"
    return
  fi
  echo "Root ou sudo -n requis." >&2
  exit 1
}

proxy_expected() {
  [ "$TOPOLOGY" != "split-domain" ]
}

ensure_container_modules() {
  if ! proxy_expected; then
    return
  fi
  if docker exec "$CONTAINER_NAME" apachectl -M 2>/dev/null | grep -q proxy_http_module \
    && docker exec "$CONTAINER_NAME" apachectl -M 2>/dev/null | grep -q proxy_wstunnel_module; then
    return
  fi

  if docker exec "$CONTAINER_NAME" sh -lc 'command -v a2enmod >/dev/null 2>&1'; then
    docker exec -u 0 "$CONTAINER_NAME" sh -lc 'a2enmod rewrite proxy proxy_http proxy_wstunnel headers alias >/dev/null'
    return
  fi

  docker exec -u 0 "$CONTAINER_NAME" sh -lc "sed -i 's@^#LoadModule proxy_http_module modules/mod_proxy_http.so@LoadModule proxy_http_module modules/mod_proxy_http.so@' '$CONTAINER_HTTPD_CONF_PATH' && sed -i 's@^#LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so@LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so@' '$CONTAINER_HTTPD_CONF_PATH'"
}

enable_container_site() {
  if docker exec "$CONTAINER_NAME" sh -lc 'command -v a2ensite >/dev/null 2>&1'; then
    docker exec -u 0 "$CONTAINER_NAME" sh -lc "a2ensite '$CONFIG_FILE_NAME' >/dev/null"
    return
  fi

  if [ -n "$CONTAINER_CONFIG_PATH" ] && [ "$CONTAINER_ENABLED_CONFIG_PATH" != "$CONTAINER_CONFIG_PATH" ]; then
    docker exec -u 0 "$CONTAINER_NAME" sh -lc "mkdir -p '$(dirname "$CONTAINER_ENABLED_CONFIG_PATH")' && ln -sf '$CONTAINER_CONFIG_PATH' '$CONTAINER_ENABLED_CONFIG_PATH'"
  fi
}

disable_container_site() {
  if docker exec "$CONTAINER_NAME" sh -lc 'command -v a2dissite >/dev/null 2>&1'; then
    docker exec -u 0 "$CONTAINER_NAME" sh -lc "a2dissite '$CONFIG_FILE_NAME' >/dev/null || true"
    return
  fi

  if [ -n "$CONTAINER_ENABLED_CONFIG_PATH" ] && [ "$CONTAINER_ENABLED_CONFIG_PATH" != "$CONTAINER_CONFIG_PATH" ]; then
    docker exec -u 0 "$CONTAINER_NAME" sh -lc "rm -f '$CONTAINER_ENABLED_CONFIG_PATH'"
  fi
}

container_config_test() {
  docker exec "$CONTAINER_NAME" apachectl -t
}

container_reload() {
  docker exec "$CONTAINER_NAME" apachectl -k graceful
}

host_config_test() {
  if ! command -v apache2ctl >/dev/null 2>&1; then
    echo "apache2ctl introuvable" >&2
    return 1
  fi
  apache2ctl -t
}

status_container() {
  DOCKER_AVAILABLE="$(if command -v docker >/dev/null 2>&1; then echo 1; else echo 0; fi)"
  CONTAINER_EXISTS=0
  CONTAINER_RUNNING=0

  printf 'apacheContainer=%s\n' "$CONTAINER_NAME"
  printf 'dockerAvailable=%s\n' "$DOCKER_AVAILABLE"
  printf 'configExists=%s\n' "$(if [ -f "$CONFIG_PATH" ]; then echo 1; else echo 0; fi)"
  printf 'disabledConfigExists=%s\n' "$(if [ -f "$DISABLED_CONFIG_PATH" ]; then echo 1; else echo 0; fi)"
  printf 'configPath=%s\n' "$CONFIG_PATH"
  printf 'disabledConfigPath=%s\n' "$DISABLED_CONFIG_PATH"
  printf 'containerConfigPath=%s\n' "$CONTAINER_CONFIG_PATH"
  printf 'documentRoot=%s\n' "$DOCUMENT_ROOT"
  printf 'publicUrl=%s\n' "$PUBLIC_URL"
  printf 'topology=%s\n' "$TOPOLOGY"
  printf 'proxyExpected=%s\n' "$(if proxy_expected; then echo 1; else echo 0; fi)"
  printf 'apiTarget=%s\n' "$API_TARGET"

  if [ "$DOCKER_AVAILABLE" = "1" ] && docker inspect "$CONTAINER_NAME" >/dev/null 2>&1; then
    CONTAINER_EXISTS=1
    if [ "$(docker inspect -f '{{.State.Running}}' "$CONTAINER_NAME" 2>/dev/null)" = "true" ]; then
      CONTAINER_RUNNING=1
    fi
  fi

  printf 'apacheContainerExists=%s\n' "$CONTAINER_EXISTS"
  printf 'apacheContainerRunning=%s\n' "$CONTAINER_RUNNING"
  printf 'siteEnabled=%s\n' "$(if [ "$CONTAINER_RUNNING" = "1" ] && docker exec "$CONTAINER_NAME" test -e "$CONTAINER_ENABLED_CONFIG_PATH"; then echo 1; else echo 0; fi)"
  printf 'documentRootExists=%s\n' "$(if [ "$CONTAINER_RUNNING" = "1" ] && docker exec "$CONTAINER_NAME" test -d "$DOCUMENT_ROOT"; then echo 1; else echo 0; fi)"
  if proxy_expected; then
    printf 'proxyHttpLoaded=%s\n' "$(if [ "$CONTAINER_RUNNING" = "1" ] && docker exec "$CONTAINER_NAME" apachectl -M | grep -q proxy_http_module; then echo 1; else echo 0; fi)"
    printf 'proxyWstunnelLoaded=%s\n' "$(if [ "$CONTAINER_RUNNING" = "1" ] && docker exec "$CONTAINER_NAME" apachectl -M | grep -q proxy_wstunnel_module; then echo 1; else echo 0; fi)"
  else
    printf 'proxyHttpLoaded=not-required\n'
    printf 'proxyWstunnelLoaded=not-required\n'
  fi

  if [ "$DOCKER_AVAILABLE" != "1" ]; then
    printf 'configTest=docker-unavailable\n'
  elif [ "$CONTAINER_EXISTS" != "1" ]; then
    printf 'configTest=container-missing\n'
  elif [ "$CONTAINER_RUNNING" != "1" ]; then
    printf 'configTest=container-stopped\n'
  elif container_config_test >/tmp/ttm-front-apache-configtest.out 2>&1; then
    printf 'configTest=ok\n'
  else
    printf 'configTest=error\n'
  fi

  cat /tmp/ttm-front-apache-configtest.out 2>/dev/null || true
}

status_host() {
  ENABLED_PATH="/etc/apache2/sites-enabled/$CONFIG_FILE_NAME"
  printf 'apacheContainer=\n'
  printf 'documentRootExists=%s\n' "$(if [ -d "$DOCUMENT_ROOT" ]; then echo 1; else echo 0; fi)"
  printf 'configExists=%s\n' "$(if [ -f "$CONFIG_PATH" ]; then echo 1; else echo 0; fi)"
  printf 'disabledConfigExists=%s\n' "$(if [ -f "$DISABLED_CONFIG_PATH" ]; then echo 1; else echo 0; fi)"
  printf 'siteEnabled=%s\n' "$(if [ -e "$ENABLED_PATH" ]; then echo 1; else echo 0; fi)"
  printf 'configPath=%s\n' "$CONFIG_PATH"
  printf 'disabledConfigPath=%s\n' "$DISABLED_CONFIG_PATH"
  printf 'enabledPath=%s\n' "$ENABLED_PATH"
  printf 'documentRoot=%s\n' "$DOCUMENT_ROOT"
  printf 'publicUrl=%s\n' "$PUBLIC_URL"
  printf 'topology=%s\n' "$TOPOLOGY"
  printf 'proxyExpected=%s\n' "$(if proxy_expected; then echo 1; else echo 0; fi)"
  printf 'apiTarget=%s\n' "$API_TARGET"
  if proxy_expected; then
    printf 'proxyHttpLoaded=unknown\n'
    printf 'proxyWstunnelLoaded=unknown\n'
  else
    printf 'proxyHttpLoaded=not-required\n'
    printf 'proxyWstunnelLoaded=not-required\n'
  fi
  if host_config_test >/tmp/ttm-front-apache-configtest.out 2>&1; then
    printf 'configTest=ok\n'
  elif grep -q 'apache2ctl introuvable' /tmp/ttm-front-apache-configtest.out 2>/dev/null; then
    printf 'configTest=missing-apache2ctl\n'
  else
    printf 'configTest=error\n'
  fi

  cat /tmp/ttm-front-apache-configtest.out 2>/dev/null || true
}

install_container() {
  docker exec "$CONTAINER_NAME" test -d "$DOCUMENT_ROOT"
  mkdir -p "$(dirname "$CONFIG_PATH")"
  install -m 0644 "$VHOST_SOURCE_PATH" "$CONFIG_PATH"
  rm -f "$DISABLED_CONFIG_PATH"
  rm -f "$VHOST_SOURCE_PATH"
  ensure_container_modules
  enable_container_site
  container_config_test
  container_reload
  echo "[front-apache] vhost installé et Apache rechargé ($SITE_NAME)"
}

install_host() {
  [ -d "$DOCUMENT_ROOT" ]
  run_root "mkdir -p '$(dirname "$CONFIG_PATH")'"
  run_root "install -m 0644 '$VHOST_SOURCE_PATH' '$CONFIG_PATH'"
  rm -f "$VHOST_SOURCE_PATH"
  if proxy_expected; then
    run_root "a2enmod rewrite proxy proxy_http proxy_wstunnel headers alias"
  else
    run_root "a2enmod rewrite alias"
  fi
  run_root "a2ensite '$CONFIG_FILE_NAME'"
  run_root "apache2ctl configtest"
  run_root "systemctl reload apache2"
  echo "[front-apache] vhost installé et Apache rechargé ($SITE_NAME)"
}

enable_container() {
  if [ ! -f "$CONFIG_PATH" ] && [ ! -f "$DISABLED_CONFIG_PATH" ]; then
    echo "VHost introuvable: $CONFIG_PATH" >&2
    exit 1
  fi
  if [ -f "$DISABLED_CONFIG_PATH" ] && [ ! -f "$CONFIG_PATH" ]; then
    mv "$DISABLED_CONFIG_PATH" "$CONFIG_PATH"
  fi
  ensure_container_modules
  enable_container_site
  container_config_test
  container_reload
  echo "[front-apache] vhost activé ($SITE_NAME)"
}

enable_host() {
  [ -f "$CONFIG_PATH" ] || { echo "VHost introuvable: $CONFIG_PATH" >&2; exit 1; }
  if proxy_expected; then
    run_root "a2enmod rewrite proxy proxy_http proxy_wstunnel headers alias"
  else
    run_root "a2enmod rewrite alias"
  fi
  run_root "a2ensite '$CONFIG_FILE_NAME'"
  run_root "apache2ctl configtest"
  run_root "systemctl reload apache2"
  echo "[front-apache] vhost activé ($SITE_NAME)"
}

disable_container() {
  disable_container_site
  if [ -f "$CONFIG_PATH" ]; then
    mv "$CONFIG_PATH" "$DISABLED_CONFIG_PATH"
  fi
  container_config_test
  container_reload
  echo "[front-apache] vhost désactivé ($SITE_NAME)"
}

disable_host() {
  run_root "a2dissite '$CONFIG_FILE_NAME'"
  run_root "apache2ctl configtest"
  run_root "systemctl reload apache2"
  echo "[front-apache] vhost désactivé ($SITE_NAME)"
}

require_var FRONT_APACHE_CONFIG_PATH "$CONFIG_PATH"
require_var FRONT_APACHE_DOCUMENT_ROOT "$DOCUMENT_ROOT"

case "$ACTION" in
  status)
    if [ -n "$CONTAINER_NAME" ]; then
      status_container
    else
      status_host
    fi
    ;;
  install)
    require_var FRONT_APACHE_VHOST_SOURCE_PATH "$VHOST_SOURCE_PATH"
    if [ -n "$CONTAINER_NAME" ]; then
      install_container
    else
      install_host
    fi
    ;;
  enable)
    if [ -n "$CONTAINER_NAME" ]; then
      enable_container
    else
      enable_host
    fi
    ;;
  disable)
    if [ -n "$CONTAINER_NAME" ]; then
      disable_container
    else
      disable_host
    fi
    ;;
  *)
    echo "Action front-apache inconnue: $ACTION" >&2
    exit 1
    ;;
esac

