#!/usr/bin/env bash
# Import zálohy EMS (pg_dump -Fc) do Postgresu v Dockeru na serveru.
#
# Předpoklad: čerstvý volume nebo vědomá obnova přes existující data.
# Spouštěj na serveru z /opt/ems-deploy (nebo nastav EMS_DEPLOY_ROOT).
#
# Postup (nová instance, ještě bez plného stacku):
#   1) /opt/ems-deploy/.env vyplněné (DB_USER, DB_PASSWORD stejné jako v cílové DB – po initu db)
#   2) docker compose -f /opt/ems-deploy/docker-compose.yml --env-file /opt/ems-deploy/.env up -d db
#   3) Počkej na healthy: docker compose ... ps
#   4) bash app/scripts/import_ems_db.sh /tmp/ems.dump
#   5) flyway migrate (doplní PK / FK po problematickém restore – V032–V034)
#   6) Celý stack: /opt/ems-deploy/deploy.sh   (nebo docker compose up -d)
#
# Volby prostředí:
#   EMS_DEPLOY_ROOT=/opt/ems-deploy  (výchozí)
#   COMPOSE_FILE, ENV_FILE – přepíšou cesty k souborům
#   EMS_SKIP_TIMESCALE_RESTORE_HOOKS=1 – přeskočí timescaledb_pre_restore / post_restore (jen výjimečně)
#
# TimescaleDB – doporučení z dokumentace (full restore):
#   - Cílová DB má mít rozšíření timescaledb před restore.
#   - Před pg_restore: SELECT timescaledb_pre_restore();
#   - Po pg_restore: ALTER EXTENSION timescaledb UPDATE; (srovná katalog zálohy s verzí v imagi –
#     jinak post_restore hlásí „catalog version mismatch expected … seen …“)
#   - Pak: SELECT timescaledb_post_restore();
#   - Ideálně stejná major verze Postgres + Timescale jako u zálohy; jinak pin imagí
#     (např. timescale/timescaledb:2.25.2-pg16 místo latest-pg16).
#   - Bez paralelního pg_restore (-j) – může rozbít pořadí objektů a chunky.
#
# pg_restore z běžného pg_dump i tak může u hypertable vygenerovat nevhodné DDL (např. ALTER TABLE ONLY
# u FK). Po importu proto spusťte flyway migrate (V034 doplní chybějící FK).
#
# Robustnější varianta (schema + data zvlášť) – viz oficiální návod Timescale / Tiger Data:
#   pg_dump -Fc --section=pre-data --exclude-schema='_timescaledb*' …
#   na cíli znovu create_hypertable(...) (např. přes Flyway), data COPY / parallel-copy.
#   Tento skript řeší klasický jednosouborový -Fc restore, ne oddělené sekce.

set -euo pipefail

ROOT="${EMS_DEPLOY_ROOT:-/opt/ems-deploy}"
COMPOSE_FILE="${COMPOSE_FILE:-$ROOT/docker-compose.yml}"
ENV_FILE="${ENV_FILE:-$ROOT/.env}"

if [[ $# -lt 1 ]]; then
  echo "Usage: $0 /cesta/k/ems.dump" >&2
  exit 1
fi

DUMP="$(readlink -f "$1")"
if [[ ! -f "$DUMP" ]]; then
  echo "ERROR: soubor neexistuje: $DUMP" >&2
  exit 1
fi

if [[ ! -f "$COMPOSE_FILE" ]]; then
  echo "ERROR: compose not found: $COMPOSE_FILE" >&2
  exit 1
fi

if [[ ! -f "$ENV_FILE" ]]; then
  echo "ERROR: .env not found: $ENV_FILE" >&2
  exit 1
fi

set -a
# shellcheck disable=SC1090
source "$ENV_FILE"
set +a

: "${DB_USER:?DB_USER missing in $ENV_FILE}"
: "${DB_PASSWORD:?DB_PASSWORD missing in $ENV_FILE}"

cd "$ROOT"

if ! docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" ps --status running -q db | grep -q .; then
  echo "ERROR: db neběží. Spusť jen databázi, např.:" >&2
  echo "  docker compose -f \"$COMPOSE_FILE\" --env-file \"$ENV_FILE\" up -d db" >&2
  exit 1
fi

compose_db() {
  docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" exec -T \
    -e "PGPASSWORD=${DB_PASSWORD}" \
    db \
    "$@"
}

CID="$(docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" ps -q db)"
echo "Kopíruji dump do kontejneru..."
docker cp "$DUMP" "${CID}:/tmp/ems_import.dump"

if [[ "${EMS_SKIP_TIMESCALE_RESTORE_HOOKS:-0}" != "1" ]]; then
  echo "Timescale: CREATE EXTENSION + timescaledb_pre_restore()…"
  compose_db psql -U "$DB_USER" -d ems -v ON_ERROR_STOP=1 \
    -c "CREATE EXTENSION IF NOT EXISTS timescaledb;"
  compose_db psql -U "$DB_USER" -d ems -v ON_ERROR_STOP=1 \
    -c "SELECT timescaledb_pre_restore();"
else
  echo "WARN: EMS_SKIP_TIMESCALE_RESTORE_HOOKS=1 – přeskakuji pre_restore"
fi

echo "Obnovuji databázi ems (--clean smaže existující objekty ve schématech ze zálohy)…"
set +e
compose_db pg_restore -U "$DB_USER" -d ems --clean --if-exists --no-owner --no-acl --verbose /tmp/ems_import.dump
RESTORE_EXIT=$?
set -e

if [[ "${EMS_SKIP_TIMESCALE_RESTORE_HOOKS:-0}" != "1" ]]; then
  echo "Timescale: ALTER EXTENSION timescaledb UPDATE (katalog ze zálohy → verze v imagi)…"
  if compose_db psql -U "$DB_USER" -d ems -v ON_ERROR_STOP=1 \
      -c "ALTER EXTENSION timescaledb UPDATE;"; then
    echo "Timescale: timescaledb_post_restore()…"
    if ! compose_db psql -U "$DB_USER" -d ems -v ON_ERROR_STOP=1 \
        -c "SELECT timescaledb_post_restore();"; then
      echo "ERROR: timescaledb_post_restore() selhal (zkontroluj verze PG/Timescale vs. záloha)." >&2
      RESTORE_EXIT=1
    fi
  else
    echo "ERROR: ALTER EXTENSION timescaledb UPDATE selhalo – nespouštím post_restore." >&2
    echo "       Zkus v compose stejný Timescale tag jako u zdroje dumpu (např. :2.25.2-pg16), nebo nový dump po upgrade zdroje." >&2
    RESTORE_EXIT=1
  fi
else
  echo "WARN: EMS_SKIP_TIMESCALE_RESTORE_HOOKS=1 – přeskakuji post_restore"
fi

docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" exec -T db rm -f /tmp/ems_import.dump

if [[ "$RESTORE_EXIT" -ne 0 ]]; then
  echo "WARN: pg_restore skončil s kódem $RESTORE_EXIT (časté u FK na hypertable). Spusť flyway migrate." >&2
fi

echo "Import dokončen (exit pg_restore=$RESTORE_EXIT). Doporučeno: flyway migrate, pak deploy.sh / docker compose up -d."
exit "$RESTORE_EXIT"
