#!/usr/bin/env python3
# Runner migrasi minimal: menerapkan berkas *.up.sql yang belum tercatat
# di tabel schema_migrations, satu transaksi per migrasi.
import os
import re

import psycopg

BASE = os.path.dirname(os.path.abspath(__file__))
POLA = re.compile(r"^(\d+)_(.+)\.up\.sql$")

conn = psycopg.connect()
conn.execute("""
    CREATE TABLE IF NOT EXISTS schema_migrations (
        version    bigint PRIMARY KEY,
        name       text NOT NULL,
        applied_at timestamptz NOT NULL DEFAULT now()
    )
""")
conn.commit()

terpasang = {v for (v,) in conn.execute(
    "SELECT version FROM schema_migrations").fetchall()}
# Tutup transaksi yang dibuka pembacaan di atas, supaya blok
# conn.transaction() di bawah berjalan sebagai transaksi teratas.
conn.commit()

tertunda = []
for berkas in sorted(os.listdir(BASE)):
    m = POLA.match(berkas)
    if m and int(m.group(1)) not in terpasang:
        tertunda.append((int(m.group(1)), m.group(2), berkas))

if not tertunda:
    print("tidak ada migrasi tertunda")

for versi, nama, berkas in tertunda:
    sql = open(os.path.join(BASE, berkas)).read()
    # Satu transaksi per migrasi: DDL di PostgreSQL bersifat transaksional,
    # jadi kegagalan di tengah berkas tidak meninggalkan skema setengah jadi.
    with conn.transaction():
        conn.execute(sql)
        conn.execute(
            "INSERT INTO schema_migrations (version, name) VALUES (%s, %s)",
            (versi, nama),
        )
    print(f"menerapkan {versi:04d}_{nama}")

for versi, nama in conn.execute(
        "SELECT version, name FROM schema_migrations ORDER BY version").fetchall():
    print(f"terpasang: {versi:04d}_{nama}")

conn.close()
