import { strict as assert } from 'node:assert';
import { describe, it } from 'node:test';
import { runCli } from '../src/cli';

interface HarnessResult {
  code: number;
  stdout: string;
  stderr: string;
}

async function invoke(
  args: string[],
  fetchImpl: typeof fetch,
  env: NodeJS.ProcessEnv = {},
): Promise<HarnessResult> {
  let stdout = '';
  let stderr = '';
  const code = await runCli(args, {
    env,
    fetchImpl,
    stdout: (value) => {
      stdout += value;
    },
    stderr: (value) => {
      stderr += value;
    },
  });
  return { code, stdout, stderr };
}

describe('pig CLI JSON contract', () => {
  it('emits exactly one machine JSON value and authenticates with the API key', async () => {
    const requests: { url: string; authorization: string | null }[] = [];
    const payload = {
      id: '10000000-0000-4000-8000-000000000001',
      name: 'Ada',
      email: 'ada@example.com',
      teams: [],
    };
    const fetchImpl: typeof fetch = async (input, init) => {
      requests.push({
        url: String(input),
        authorization: new Headers(init?.headers).get('authorization'),
      });
      return new Response(JSON.stringify(payload), {
        status: 200,
        headers: { 'content-type': 'application/json' },
      });
    };

    const result = await invoke(['--json', 'me'], fetchImpl, {
      PIG_API_URL: 'https://pig.example/',
      PIG_API_KEY: 'pig_test_secret',
    });

    assert.equal(result.code, 0);
    assert.equal(result.stdout, `${JSON.stringify(payload)}\n`);
    assert.equal(result.stderr, '');
    assert.deepEqual(requests, [
      { url: 'https://pig.example/api/me', authorization: 'Bearer pig_test_secret' },
    ]);
  });

  it('writes structured API failures only to stderr and redacts echoed credentials', async () => {
    const key = 'pig_should_never_print';
    const fetchImpl: typeof fetch = async () =>
      new Response(
        JSON.stringify({
          code: 'insufficient_scope',
          error: `Credential ${key} cannot write.`,
        }),
        { status: 403, headers: { 'content-type': 'application/json' } },
      );

    const result = await invoke(['--json', 'commitments'], fetchImpl, {
      PIG_API_URL: 'https://pig.example',
      PIG_API_KEY: key,
    });

    assert.equal(result.code, 1);
    assert.equal(result.stdout, '');
    assert.equal(result.stderr.includes(key), false);
    assert.deepEqual(JSON.parse(result.stderr), {
      error: {
        code: 'insufficient_scope',
        message: 'Credential [REDACTED] cannot write.',
        status: 403,
        details: {
          code: 'insufficient_scope',
          error: 'Credential [REDACTED] cannot write.',
        },
      },
    });
  });

  it('returns JSON usage failures without making a request', async () => {
    let called = false;
    const fetchImpl: typeof fetch = async () => {
      called = true;
      return new Response('{}');
    };
    const result = await invoke(['--json', 'me'], fetchImpl);

    assert.equal(result.code, 2);
    assert.equal(result.stdout, '');
    assert.deepEqual(JSON.parse(result.stderr), {
      error: { code: 'invalid_usage', message: 'Set PIG_API_URL or pass --api-url.' },
    });
    assert.equal(called, false);
  });
});

describe('pig CLI route decisions', () => {
  it('uses the bounded release endpoint and sends an explicit JSON body', async () => {
    const calls: { url: string; method: string | undefined; body: string | null | undefined }[] = [];
    const fetchImpl: typeof fetch = async (input, init) => {
      calls.push({ url: String(input), method: init?.method, body: init?.body?.toString() });
      return new Response(JSON.stringify({ id: 'allocation-1', status: 'released' }), {
        status: 200,
        headers: { 'content-type': 'application/json' },
      });
    };

    const result = await invoke(
      ['--json', 'allocations', 'release', 'allocation-1', '--reason', 'Customer changed scope'],
      fetchImpl,
      { PIG_API_URL: 'https://pig.example', PIG_API_KEY: 'pig_writer' },
    );

    assert.equal(result.code, 0);
    assert.deepEqual(calls, [
      {
        url: 'https://pig.example/api/allocations/allocation-1/release',
        method: 'POST',
        body: JSON.stringify({ reason: 'Customer changed scope' }),
      },
    ]);
  });

  it('maps capacity search flags to the public inventory query', async () => {
    let requestedUrl = '';
    const fetchImpl: typeof fetch = async (input) => {
      requestedUrl = String(input);
      return new Response('[]', {
        status: 200,
        headers: { 'content-type': 'application/json' },
      });
    };

    const result = await invoke(
      [
        '--json',
        '--api-url',
        'https://pig.example',
        '--api-key',
        'pig_reader',
        'capacity',
        'search',
        '--gpu-type',
        'H100_80GB',
        '--min-gpu-count',
        '8',
        '--fast-fabric',
        '--limit',
        '25',
      ],
      fetchImpl,
    );

    assert.equal(result.code, 0);
    assert.equal(
      requestedUrl,
      'https://pig.example/api/inventory?gpuType=H100_80GB&minGpuCount=8&fastFabric=true&limit=25',
    );
  });
});
