import { describe, it } from 'node:test';
import { strict as assert } from 'node:assert';
import * as fs from 'node:fs';
import * as os from 'node:os';
import * as path from 'node:path';

import {
  resolveNatsBinary,
  resolveRunnerTransportPlan,
} from '../../src/utils/runner-transport.js';
import type { ILoadedMatrixPackageEnvironment } from '../../src/utils/package-environment.js';

function createLoadedEnvironment(
  packageDir: string,
  envName: string,
  environment: ILoadedMatrixPackageEnvironment['environment'],
): ILoadedMatrixPackageEnvironment {
  return {
    packageDir,
    envName,
    environmentPath: path.join(packageDir, '.matrix', `${envName}.environment.json`),
    environment,
  };
}

describe('runner transport resolution', () => {
  it('prefers environment-owned embedded NATS paths over shared defaults', () => {
    const packageDir = fs.mkdtempSync(path.join(os.tmpdir(), 'mx-runner-embedded-'));
    const loaded = createLoadedEnvironment(packageDir, 'dev', {
      name: 'dev',
      runtime: { root: 'COM.TEST.EMBEDDED' },
      nats: {
        mode: 'embedded',
        port: 5111,
        wsPort: 5112,
        binaryPath: './tools/nats-server-custom',
        dataDir: './runtime-state/nats-data',
        pidFile: './runtime-state/nats.pid',
      },
    });

    const plan = resolveRunnerTransportPlan(packageDir, loaded);

    assert.equal(plan.mode, 'embedded');
    assert.equal(plan.root, 'COM.TEST.EMBEDDED');
    assert.equal(plan.url, 'nats://127.0.0.1:5111');
    assert.equal(plan.wsUrl, 'ws://127.0.0.1:5112');
    assert.equal(plan.binaryPath, path.join(packageDir, 'tools', 'nats-server-custom'));
    assert.equal(plan.dataDir, path.join(packageDir, 'runtime-state', 'nats-data'));
    assert.equal(plan.pidFile, path.join(packageDir, 'runtime-state', 'nats.pid'));
  });

  it('uses MATRIX_NATS_SERVER_BINARY before shared repo fallbacks', () => {
    const packageDir = fs.mkdtempSync(path.join(os.tmpdir(), 'mx-runner-envbinary-'));
    const fakeBinary = path.join(packageDir, 'custom-bin', 'nats-server');
    fs.mkdirSync(path.dirname(fakeBinary), { recursive: true });
    fs.writeFileSync(fakeBinary, '', 'utf8');

    const original = process.env.MATRIX_NATS_SERVER_BINARY;
    process.env.MATRIX_NATS_SERVER_BINARY = fakeBinary;
    try {
      const resolved = resolveNatsBinary(packageDir);
      assert.equal(resolved, fakeBinary);
    } finally {
      if (original === undefined) {
        delete process.env.MATRIX_NATS_SERVER_BINARY;
      } else {
        process.env.MATRIX_NATS_SERVER_BINARY = original;
      }
    }
  });

  it('resolves external NATS environments without inventing embedded state', () => {
    const packageDir = fs.mkdtempSync(path.join(os.tmpdir(), 'mx-runner-external-'));
    const loaded = createLoadedEnvironment(packageDir, 'integration', {
      name: 'integration',
      runtime: { root: 'COM.TEST.EXTERNAL' },
      nats: {
        mode: 'external',
        url: 'nats://example.net:4229',
        wsUrl: 'wss://example.net/nats-ws',
        credentialsRef: 'file:~/.matrix/credentials.json',
      },
    });

    const plan = resolveRunnerTransportPlan(packageDir, loaded, 'COM.TEST.EXTERNAL.OVERRIDE');

    assert.equal(plan.mode, 'external');
    assert.equal(plan.root, 'COM.TEST.EXTERNAL.OVERRIDE');
    assert.equal(plan.url, 'nats://example.net:4229');
    assert.equal(plan.wsUrl, 'wss://example.net/nats-ws');
    assert.equal(plan.credentialsRef, 'file:~/.matrix/credentials.json');
    assert.equal('binaryPath' in plan, false);
    assert.equal('dataDir' in plan, false);
    assert.equal('pidFile' in plan, false);
  });
});
