#!/usr/bin/env bash
#
# Prisma migrációk alkalmazása psql-lel, PostgreSQL 10 alatt.
#
# Miért nem `prisma migrate deploy`?
#   A Rackforest tárhely PostgreSQL 10.23-at futtat. A Prisma 6 schema engine
#   (a migrációkat végző Rust bináris) ezen panikkal elszáll:
#     "Could not parse schema engine response ... thread 'mai..."
#   A query engine – amit az alkalmazás futás közben használ – viszont
#   hibátlanul működik, tehát csak a migrációs lépést kell megkerülni.
#
# Ez a szkript azt csinálja, amit a `migrate deploy`: sorrendben alkalmazza a
# még nem futott migrációkat, mindegyiket saját tranzakcióban, és vezeti a
# _prisma_migrations táblát ugyanabban a formátumban (SHA-256 checksummal).
# Így ha a tárhely egyszer újabb PostgreSQL-t kap, a Prisma pontosan látja,
# mi van már alkalmazva, és onnan folytatja.
#
# Használat (az alkalmazás gyökeréből, ahol a .env és a prisma/ van):
#   bash deploy/rackforest/migrate-psql.sh
#
set -euo pipefail

app_dir="${1:-$PWD}"
env_file="${app_dir}/.env"
migrations_dir="${app_dir}/prisma/migrations"

if [[ ! -f "${env_file}" ]]; then
  echo "Nem található: ${env_file}" >&2
  exit 10
fi

if [[ ! -d "${migrations_dir}" ]]; then
  echo "Nem található: ${migrations_dir}" >&2
  exit 11
fi

db_url="$(grep -E '^DATABASE_URL=' "${env_file}" | head -1 | cut -d= -f2- | sed 's/^"//; s/"$//')"
if [[ -z "${db_url}" ]]; then
  echo "A DATABASE_URL hiányzik a .env fájlból." >&2
  exit 12
fi

# A Prisma URL-je olyan paramétereket is tartalmaz, amiket a libpq nem ismer
# (schema, connection_limit, pool_timeout) – ezektől a psql hibára fut.
# A sémát kivesszük és search_path-ként adjuk át, a többi paramétert elhagyjuk.
db_schema="$(sed -n 's/.*[?&]schema=\([^&]*\).*/\1/p' <<< "${db_url}")"
db_schema="${db_schema:-public}"
psql_url="${db_url%%\?*}"

export PGOPTIONS="-c search_path=${db_schema}"

psql_run() { psql "${psql_url}" -v ON_ERROR_STOP=1 -q "$@"; }
psql_val() { psql "${psql_url}" -tA -c "$1"; }

# A Prisma saját előzménytáblája. Ugyanaz a séma, amit a migrate deploy hoz létre.
psql_run -c '
CREATE TABLE IF NOT EXISTS "_prisma_migrations" (
    "id"                    VARCHAR(36)  PRIMARY KEY NOT NULL,
    "checksum"              VARCHAR(64)  NOT NULL,
    "finished_at"           TIMESTAMPTZ,
    "migration_name"        VARCHAR(255) NOT NULL,
    "logs"                  TEXT,
    "rolled_back_at"        TIMESTAMPTZ,
    "started_at"            TIMESTAMPTZ  NOT NULL DEFAULT now(),
    "applied_steps_count"   INTEGER      NOT NULL DEFAULT 0
);'

applied=0
skipped=0

for dir in $(find "${migrations_dir}" -mindepth 1 -maxdepth 1 -type d | sort); do
  name="$(basename "${dir}")"
  sql="${dir}/migration.sql"
  [[ -f "${sql}" ]] || continue

  exists="$(psql_val "SELECT count(*) FROM \"_prisma_migrations\" WHERE migration_name = '${name}' AND rolled_back_at IS NULL;")"
  if [[ "${exists}" != "0" ]]; then
    skipped=$((skipped + 1))
    continue
  fi

  # A Prisma a migrációs fájl SHA-256 lenyomatát tárolja hexben.
  checksum="$(sha256sum "${sql}" | cut -d' ' -f1)"

  echo "  alkalmazás: ${name}"
  # Egy tranzakció: vagy a migráció ÉS a nyilvántartás is lefut, vagy egyik sem.
  {
    echo "BEGIN;"
    cat "${sql}"
    echo ";"
    echo "INSERT INTO \"_prisma_migrations\" (id, checksum, migration_name, started_at, finished_at, applied_steps_count)"
    echo "VALUES (gen_random_uuid()::text, '${checksum}', '${name}', now(), now(), 1);"
    echo "COMMIT;"
  } | psql_run -f -

  applied=$((applied + 1))
done

echo "  kész – alkalmazva: ${applied}, már megvolt: ${skipped}"
