import { execFileSync } from 'node:child_process';
import path from 'node:path';
import { describe, expect, it } from 'vitest';

const nxBin = path.resolve(process.cwd(), 'node_modules/.bin/nx');

function runNx(args: string[]) {
  return execFileSync(nxBin, args, {
    cwd: process.cwd(),
    env: {
      ...process.env,
      NX_DAEMON: 'false',
      NX_ISOLATE_PLUGINS: 'false',
      CI: 'true',
      PLAYWRIGHT_APP_PORT: process.env.PLAYWRIGHT_APP_PORT || '3300',
      PLAYWRIGHT_APP_PORT_LOCKED: 'true',
    },
    encoding: 'utf8',
    stdio: ['ignore', 'pipe', 'pipe'],
  });
}

function parseTrailingJsonArray(output: string): string[] {
  const start = output.lastIndexOf('[');
  const end = output.lastIndexOf(']');
  if (start === -1 || end === -1 || end <= start) {
    throw new Error(`Expected JSON array in output. Output:\n${output}`);
  }
  const json = output.slice(start, end + 1);
  const parsed = JSON.parse(json);
  if (!Array.isArray(parsed)) throw new Error(`Expected JSON array, got: ${typeof parsed}`);
  return parsed as string[];
}

describe('nx affected', () => {
  it('identifies affected projects from a file list', { timeout: 180_000 }, () => {
    const output = runNx(['show', 'projects', '--affected', '--files=packages/types/src/index.ts', '--json']);
    const projects = parseTrailingJsonArray(output);

    expect(projects).toContain('@alga-psa/types');
    // Types changes should affect the main app as a downstream consumer.
    expect(projects).toContain('server');
  });

  it('includes @alga-psa/clients when client code changes', { timeout: 180_000 }, () => {
    const output = runNx(['show', 'projects', '--affected', '--files=packages/clients/src/schemas/client.schema.ts', '--json']);
    const projects = parseTrailingJsonArray(output);
    expect(projects).toContain('@alga-psa/clients');
  });
});
