// SC #16 — skip-if-no-docker compose-config validation.
// First test in tests/integration/ — establishes the skip-on-missing-tool
// pattern voyage uses for environment-dependent integration tests.

import { test } from 'node:test';
import { strict as assert } from 'node:assert';
import { execFileSync, spawnSync } from 'node:child_process';
import { fileURLToPath } from 'node:url';
import { dirname, resolve } from 'node:path';

const __dirname = dirname(fileURLToPath(import.meta.url));
const REPO_ROOT = resolve(__dirname, '../..');
const COMPOSE_FILE = resolve(REPO_ROOT, 'examples/observability/docker-compose.yml');

const dockerAvailable = (() => {
  try {
    execFileSync('docker', ['info'], { stdio: 'ignore' });
    return true;
  } catch {
    return false;
  }
})();

test(
  'compose config parses and contains expected services',
  { skip: !dockerAvailable && 'Docker not installed' },
  () => {
    const r = spawnSync(
      'docker',
      ['compose', '-f', COMPOSE_FILE, 'config'],
      { encoding: 'utf8' },
    );
    assert.equal(r.status, 0, `docker compose config exited ${r.status}: ${r.stderr}`);
    assert.match(r.stdout, /otel-collector/, 'otel-collector service missing');
    assert.match(r.stdout, /prometheus/, 'prometheus service missing');
    assert.match(r.stdout, /grafana/, 'grafana service missing');
    assert.match(r.stdout, /node-exporter/, 'node-exporter service missing');
  },
);

test(
  'compose config pins required image versions',
  { skip: !dockerAvailable && 'Docker not installed' },
  () => {
    const r = spawnSync(
      'docker',
      ['compose', '-f', COMPOSE_FILE, 'config'],
      { encoding: 'utf8' },
    );
    assert.equal(r.status, 0);
    assert.match(r.stdout, /prom\/prometheus:v3\.0\.1/, 'prometheus pin missing');
    assert.match(r.stdout, /grafana\/grafana:11\.4\.0/, 'grafana pin missing');
    assert.match(
      r.stdout,
      /otel\/opentelemetry-collector-contrib:0\.115\.0/,
      'otel-collector pin missing',
    );
  },
);
