import { afterEach, describe, expect, test, vi } from 'vitest';

const loadVolumeSpec = async () => {
  vi.resetModules();
  process.env.SPOON_WORKER_TOKEN = 'test-worker-token';
  process.env.GITHUB_APP_ID = '123';
  process.env.GITHUB_APP_PRIVATE_KEY =
    '-----BEGIN PRIVATE KEY-----\\ntest\\n-----END PRIVATE KEY-----';
  return await import('../../src/runtime/docker');
};

describe('Docker runtime', () => {
  afterEach(() => {
    delete process.env.SPOON_AGENT_CONTAINER_RUNTIME;
    delete process.env.SPOON_AGENT_CONTAINER_VOLUME_OPTIONS;
    vi.resetModules();
  });

  test('adds SELinux relabel option for Podman workspace mounts by default', async () => {
    process.env.SPOON_AGENT_CONTAINER_RUNTIME = 'podman';
    const { jobWorkspaceVolumeSpec } = await loadVolumeSpec();

    expect(jobWorkspaceVolumeSpec('/tmp/spoon-job')).toBe(
      '/tmp/spoon-job:/workspace:Z',
    );
  });

  test('does not add Podman volume options for Docker by default', async () => {
    process.env.SPOON_AGENT_CONTAINER_RUNTIME = 'docker';
    const { jobWorkspaceVolumeSpec } = await loadVolumeSpec();

    expect(jobWorkspaceVolumeSpec('/tmp/spoon-job')).toBe(
      '/tmp/spoon-job:/workspace',
    );
  });

  test('allows explicit workspace mount options', async () => {
    process.env.SPOON_AGENT_CONTAINER_RUNTIME = 'podman';
    process.env.SPOON_AGENT_CONTAINER_VOLUME_OPTIONS = 'z';
    const { jobWorkspaceVolumeSpec } = await loadVolumeSpec();

    expect(jobWorkspaceVolumeSpec('/tmp/spoon-job')).toBe(
      '/tmp/spoon-job:/workspace:z',
    );
  });

  test('treats a spawn failure (no exitCode) as a non-zero exit, not empty success', async () => {
    const { normalizeRunResult } = await loadVolumeSpec();
    // This is what execa returns with `reject: false` when the runtime binary is
    // missing (e.g. no `docker` CLI in the worker image): exitCode is undefined.
    const result = normalizeRunResult(
      { exitCode: undefined, shortMessage: 'spawn docker ENOENT' },
      undefined,
      (value) => value,
    );
    expect(result.exitCode).toBe(1);
    expect(result.output).toContain('spawn docker ENOENT');
  });

  test('passes through a normal command result unchanged', async () => {
    const { normalizeRunResult } = await loadVolumeSpec();
    const result = normalizeRunResult(
      { exitCode: 0, shortMessage: undefined },
      'hello',
      (value) => value,
    );
    expect(result).toEqual({ exitCode: 0, output: 'hello' });
  });
});
