/**
 * Test B — Gateway boot refuses (fail-fast) when PG is unreachable.
 *
 * Prereq: docker compose -f docker-compose.federated.yml --profile federated up -d
 *         (Valkey must be running; only PG is intentionally misconfigured.)
 * Run:    FEDERATED_INTEGRATION=1 pnpm --filter @mosaicstack/gateway test src/__tests__/integration/federated-boot.pg-unreachable.integration.test.ts
 *
 * Skipped when FEDERATED_INTEGRATION !== '1'.
 */

import net from 'node:net';
import { beforeAll, describe, expect, it } from 'vitest';
import { TierDetectionError, detectAndAssertTier } from '@mosaicstack/storage';

const run = process.env['FEDERATED_INTEGRATION'] === '1';

const VALKEY_URL = 'redis://localhost:6380';

/**
 * Reserves a guaranteed-closed port at runtime by binding to an ephemeral OS
 * port (port 0) and immediately releasing it. The OS will not reassign the
 * port during the TIME_WAIT window, so it remains closed for the duration of
 * this test.
 */
async function reserveClosedPort(): Promise<number> {
  return new Promise((resolve, reject) => {
    const server = net.createServer();
    server.listen(0, '127.0.0.1', () => {
      const addr = server.address();
      if (typeof addr !== 'object' || !addr) return reject(new Error('no addr'));
      const port = addr.port;
      server.close(() => resolve(port));
    });
    server.on('error', reject);
  });
}

describe.skipIf(!run)('federated boot — PG unreachable', () => {
  let badPgUrl: string;

  beforeAll(async () => {
    const closedPort = await reserveClosedPort();
    badPgUrl = `postgresql://mosaic:mosaic@localhost:${closedPort}/mosaic`;
  });

  it('detectAndAssertTier throws TierDetectionError with service: postgres when PG is down', async () => {
    const brokenConfig = {
      tier: 'federated' as const,
      storage: {
        type: 'postgres' as const,
        url: badPgUrl,
        enableVector: true,
      },
      queue: {
        type: 'bullmq',
        url: VALKEY_URL,
      },
    };

    await expect(detectAndAssertTier(brokenConfig)).rejects.toSatisfy(
      (err: unknown) => err instanceof TierDetectionError && err.service === 'postgres',
    );
  }, 10_000);
});
