#!/usr/bin/env node
/**
 * Lightweight migration runner for Supabase.
 * Reads SQL files in supabase/migrations (sorted) and applies any that have not been recorded.
 *
 * Env:
 *  - SUPABASE_DB_URL or DATABASE_URL: postgres connection string (service role / connection string)
 */
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
import { Pool } from 'pg';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const migrationsDir = path.resolve(__dirname, '..', 'supabase', 'migrations');
const connectionString = process.env.SUPABASE_DB_URL || process.env.DATABASE_URL;

if (!connectionString) {
  console.error('Missing SUPABASE_DB_URL (or DATABASE_URL) environment variable. Aborting migrations.');
  process.exit(1);
}

if (!fs.existsSync(migrationsDir)) {
  console.error(`Migrations directory not found: ${migrationsDir}`);
  process.exit(1);
}

const pool = new Pool({ connectionString });

async function ensureMigrationsTable(client) {
  await client.query(`
    create table if not exists public.schema_migrations (
      id serial primary key,
      filename text not null unique,
      applied_at timestamptz not null default now()
    );
  `);
}

async function getApplied(client) {
  const { rows } = await client.query('select filename from public.schema_migrations');
  return new Set(rows.map((r) => r.filename));
}

function listMigrations() {
  return fs
    .readdirSync(migrationsDir)
    .filter((file) => file.endsWith('.sql'))
    .sort();
}

async function applyMigration(client, filename) {
  const filePath = path.join(migrationsDir, filename);
  const sql = fs.readFileSync(filePath, 'utf8');
  console.log(`Applying migration: ${filename}`);
  await client.query('begin');
  try {
    await client.query(sql);
    await client.query('insert into public.schema_migrations (filename) values ($1)', [filename]);
    await client.query('commit');
    console.log(`✓ Applied ${filename}`);
  } catch (err) {
    await client.query('rollback');
    console.error(`✗ Failed ${filename}:`, err.message);
    throw err;
  }
}

async function run() {
  const client = await pool.connect();
  try {
    await ensureMigrationsTable(client);
    const applied = await getApplied(client);
    const migrations = listMigrations();

    const pending = migrations.filter((m) => !applied.has(m));
    if (pending.length === 0) {
      console.log('No pending migrations.');
      return;
    }

    for (const migration of pending) {
      await applyMigration(client, migration);
    }
    console.log('All pending migrations applied.');
  } finally {
    client.release();
    await pool.end();
  }
}

run().catch((err) => {
  console.error('Migration run failed:', err);
  process.exit(1);
});
