import pg from 'pg';
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
import { getTestDbUrl, recreateDatabase, runMigrations, tableExists } from './db-test-support.js';

const hasDb = Boolean(process.env.TEST_DATABASE_URL);

describe.skipIf(!hasDb)('migrations', () => {
  const url = hasDb ? getTestDbUrl() : '';
  let pool: pg.Pool;

  beforeAll(async () => {
    await recreateDatabase(url);
    pool = new pg.Pool({ connectionString: url, max: 2 });
  });

  afterAll(async () => {
    await pool.end();
  });

  it('fresh up creates the full schema (baseline + identity + users)', async () => {
    await runMigrations(url, 'up');
    expect(await tableExists(pool, 'app_meta')).toBe(true);
    expect(await tableExists(pool, 'identity_users')).toBe(true);
    expect(await tableExists(pool, 'identity_sessions')).toBe(true);
    expect(await tableExists(pool, 'users_profiles')).toBe(true);
    expect(await tableExists(pool, 'users_addresses')).toBe(true);
  });

  it('second up is a no-op', async () => {
    const before = await pool.query('SELECT count(*)::int AS n FROM pgmigrations');
    await runMigrations(url, 'up');
    const after = await pool.query('SELECT count(*)::int AS n FROM pgmigrations');
    expect(after.rows[0]?.n).toBe(before.rows[0]?.n);
    expect(await tableExists(pool, 'app_meta')).toBe(true);
  });

  it('down rolls back the full schema cleanly', async () => {
    // count 0 reverts every applied migration in reverse order.
    await runMigrations(url, 'down', 0);
    expect(await tableExists(pool, 'users_addresses')).toBe(false);
    expect(await tableExists(pool, 'users_profiles')).toBe(false);
    expect(await tableExists(pool, 'identity_sessions')).toBe(false);
    expect(await tableExists(pool, 'identity_users')).toBe(false);
    expect(await tableExists(pool, 'app_meta')).toBe(false);
  });

  it('reapplies the full schema after a complete rollback', async () => {
    await runMigrations(url, 'up');
    expect(await tableExists(pool, 'app_meta')).toBe(true);
    expect(await tableExists(pool, 'backoffice_users')).toBe(true);
    expect(await tableExists(pool, 'categories_categories')).toBe(true);
  });
});
