import { afterEach, 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 { runMxCli, parseLastJson, assertExitCode } from '../helpers/cli-harness.js';
import { createMatrixPackage } from '../helpers/package-fixtures.js';

describe('FP-30 mx fork lifecycle', () => {
  const tempDirs: string[] = [];

  afterEach(() => {
    while (tempDirs.length > 0) {
      const dir = tempDirs.pop();
      if (dir) {
        fs.rmSync(dir, { recursive: true, force: true });
      }
    }
  });

  it('creates a fork with provenance metadata and renamed manifest surface', async () => {
    const root = fs.mkdtempSync(path.join(os.tmpdir(), 'mx-fp30-fork-'));
    tempDirs.push(root);
    const cwd = path.join(root, 'workspace');
    const packagesDir = path.join(root, '.matrix', 'packages');
    fs.mkdirSync(cwd, { recursive: true });

    const source = createMatrixPackage(root, {
      packageName: '@matrix/filesystem',
      version: '1.0.0',
      componentType: 'FolderProjection',
      mount: 'fs',
    });

    const installResult = await runMxCli([
      'node',
      'mx',
      'install',
      source.packageDir,
      '--packages-dir',
      packagesDir,
      '--json',
    ], { cwd });
    assertExitCode(installResult, 0);

    const forkResult = await runMxCli([
      'node',
      'mx',
      'fork',
      '@matrix/filesystem',
      '--name',
      '@alice/filesystem',
      '--packages-dir',
      packagesDir,
      '--forked-by',
      'alice',
      '--json',
    ], { cwd });
    assertExitCode(forkResult, 0);
    const forkPayload = parseLastJson(forkResult.logs) as { targetDir: string };
    assert.equal(fs.existsSync(forkPayload.targetDir), true);
    assert.equal(fs.existsSync(path.join(forkPayload.targetDir, '.forked-from')), true);

    const manifest = JSON.parse(fs.readFileSync(path.join(forkPayload.targetDir, 'matrix.json'), 'utf8')) as {
      name: string;
      components: Array<{ type?: string; export?: string; mount?: string }>;
    };
    assert.equal(manifest.name, '@alice/filesystem');
    assert.equal(manifest.components[0]?.type, 'AliceFolderProjection');
    assert.equal(manifest.components[0]?.export, 'AliceFolderProjection');
    assert.equal(manifest.components[0]?.mount, 'alice.fs');
  });
});
