/**
 * A1 — migration runner. Reads every `db/migrations/*.sql` in filename order and executes it
 * over the parameterized `query` wrapper (db/pool.ts). All migrations are `IF NOT EXISTS`, so
 * `runMigrations` is idempotent and safe to run at every boot / test setup.
 *
 * `createQuery` ALWAYS routes through the extended (parameterized) protocol — even with `[]`
 * params — which rejects multi-statement command strings. So each file is split into its
 * top-level statements (on `;`, after stripping `-- line comments`) and each statement is run
 * as its own single-command `query(stmt, [])`. Our migrations are plain IF-NOT-EXISTS DDL with
 * no `;` inside string literals and no dollar-quoted bodies, so this split is safe.
 */
import { readdir, readFile } from 'node:fs/promises'
import { dirname, join } from 'node:path'
import { fileURLToPath } from 'node:url'
import type { QueryFn } from './pool.js'

/** Absolute path to `control-plane/db/migrations`, resolved relative to this source file. */
function migrationsDir(): string {
  const here = dirname(fileURLToPath(import.meta.url)) // .../control-plane/src/db
  return join(here, '..', '..', 'db', 'migrations') // .../control-plane/db/migrations
}

/** Strip `-- line comments`, then split into non-empty top-level statements on `;`. */
export function splitStatements(sql: string): readonly string[] {
  const withoutComments = sql
    .split('\n')
    .map((line) => {
      const idx = line.indexOf('--')
      return idx >= 0 ? line.slice(0, idx) : line
    })
    .join('\n')
  return withoutComments
    .split(';')
    .map((stmt) => stmt.trim())
    .filter((stmt) => stmt.length > 0)
}

/** Apply all `*.sql` migrations in filename order. Idempotent (every migration is IF NOT EXISTS). */
export async function runMigrations(query: QueryFn): Promise<void> {
  const dir = migrationsDir()
  const files = (await readdir(dir)).filter((f) => f.endsWith('.sql')).sort()
  for (const file of files) {
    const sql = await readFile(join(dir, file), 'utf8')
    for (const stmt of splitStatements(sql)) {
      await query(stmt, [])
    }
  }
}
