#!/usr/bin/env bash
# =====================================================================
# 空のDBから `php artisan migrate` が最後まで通るかを確かめる
# （`docs/degradation-policy.md` の「形5: 本番で migrate が止まる」の検査）
# ---------------------------------------------------------------------
# なぜ要るか:
#   マイグレーションは**追加した順**ではなく**ファイル名の順**で流れる。
#   開発中は後から前の日付のファイルを足すことがあるため、
#   「今の本番では通るが、空のDBに順番どおり流すと止まる」形が作れてしまう。
#   新しいサーバを立てる・DBを作り直すときに初めて分かるので、ここで先に止める。
#
# 使い方（接続先は環境変数で渡す。`.env` は読まない）:
#   DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 \
#   DB_DATABASE=monaka_fresh_check DB_USERNAME=... DB_PASSWORD=... \
#   bash bin/check-fresh-migrate.sh
#
# 安全装置:
#   **テーブルが1つでもあるDBには実行しない。** 本番を指してしまっても
#   何も書き換えずに終わる（本番が空であることは無い）。
# =====================================================================
set -euo pipefail

cd "$(dirname "$0")/.."

for name in DB_CONNECTION DB_HOST DB_PORT DB_DATABASE DB_USERNAME; do
  if [ -z "${!name:-}" ]; then
    echo "ERROR: 環境変数 ${name} が未設定です。接続先を明示してください。" >&2
    exit 2
  fi
done

if [ "${DB_CONNECTION}" != "mysql" ]; then
  echo "ERROR: 本番は MySQL です。DB_CONNECTION=mysql で確かめてください（現在: ${DB_CONNECTION}）。" >&2
  echo "       SQLite で通しても、MySQL 専用の構文・外部キーの型不整合は見つかりません。" >&2
  exit 2
fi

echo "==> 接続先: ${DB_HOST}:${DB_PORT} / ${DB_DATABASE}"

# --- 安全装置: 空のDBでなければ何もしない ---
tables="$(php -r '
$dsn = sprintf("mysql:host=%s;port=%s;dbname=%s", getenv("DB_HOST"), getenv("DB_PORT"), getenv("DB_DATABASE"));
try {
    $pdo = new PDO($dsn, getenv("DB_USERNAME"), getenv("DB_PASSWORD") ?: "");
} catch (Throwable $e) {
    fwrite(STDERR, "ERROR: DB に接続できません: ".$e->getMessage()."\n");
    exit(3);
}
$stmt = $pdo->prepare("SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = ?");
$stmt->execute([getenv("DB_DATABASE")]);
echo (int) $stmt->fetchColumn();
')"

if [ "${tables}" != "0" ]; then
  echo "ERROR: このDBには既に ${tables} 個のテーブルがあります。**空のDBを指してください**。" >&2
  echo "       （本番を指した場合の事故を防ぐため、空でなければ何もせず終了します）" >&2
  exit 2
fi

echo "==> 空であることを確認。migrate を実行します"
php artisan migrate --force --no-interaction

# --- 素通り防止: 本当に全部流れたかを数で確かめる ---
#     `database/migrations` が配置されていない等で「0件流して成功」になると、
#     検査は緑なのに何も見ていないことになる（ゲートとしては最悪の壊れ方）。
files="$(find database/migrations -maxdepth 1 -name '*.php' | wc -l | tr -d ' ')"
applied="$(php -r '
$dsn = sprintf("mysql:host=%s;port=%s;dbname=%s", getenv("DB_HOST"), getenv("DB_PORT"), getenv("DB_DATABASE"));
$pdo = new PDO($dsn, getenv("DB_USERNAME"), getenv("DB_PASSWORD") ?: "");
echo (int) $pdo->query("SELECT COUNT(*) FROM migrations")->fetchColumn();
')"

#     判定は `applied < files` と「ファイルが0件」のみにする。
#     完全一致にすると、将来パッケージが自前のマイグレーションを持ち込んだだけで
#     **本物の異常が無いのにデプロイが止まる**（ゲートは誤検知でも信用を失う）。
if [ "${files}" = "0" ]; then
  echo "ERROR: database/migrations にファイルがありません。検査が素通りしています。" >&2
  exit 1
fi

if [ "${applied}" -lt "${files}" ]; then
  echo "ERROR: 流れた件数がファイル数に足りません（ファイル ${files} 件 / 適用 ${applied} 件）。" >&2
  echo "       検査が素通りしている可能性があります。" >&2
  exit 1
fi

echo "==> 空のDBから migrate が最後まで通りました（${applied} 件）"
