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 { spawnSync } from 'node:child_process';
import { fileURLToPath } from 'node:url';
import { elementCommand } from '../../src/commands/element.js';
import { installOpenMatrixCoreStub } from '../support/installCoreStub.ts';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const repoRoot = path.resolve(__dirname, '../../../../');

describe('FP-30 mx element scaffold', () => {
  it('creates a compilable element package archetype', async () => {
    const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'mx-element-'));
    const outputDir = path.join(tmpRoot, 'status-element');

    try {
      const result = await elementCommand('status-element', {
        cwd: repoRoot,
        outputDir,
      });

      assert.equal(fs.existsSync(path.join(outputDir, 'matrix.json')), true);
      assert.equal(fs.existsSync(path.join(outputDir, 'src', `${result.className}.ts`)), true);
      assert.equal(fs.existsSync(path.join(outputDir, 'examples', 'render.mxq')), true);
      assert.equal(fs.existsSync(path.join(outputDir, 'skills', 'status-element.skill.md')), true);

      const manifest = JSON.parse(fs.readFileSync(path.join(outputDir, 'matrix.json'), 'utf8')) as {
        name: string;
        components: Array<{ mount?: string; type?: string }>;
      };
      assert.equal(manifest.name, 'status-element');
      assert.equal(manifest.components[0]?.mount, 'status-element');
      assert.equal(manifest.components[0]?.type, result.className);

      installOpenMatrixCoreStub(outputDir);

      const compile = spawnSync(
        process.execPath,
        [
          path.resolve(repoRoot, 'node_modules/tsx/dist/cli.mjs'),
          path.join(outputDir, 'src', `${result.className}.ts`),
        ],
        { cwd: outputDir, encoding: 'utf8' }
      );
      assert.equal(compile.status, 0, compile.stderr || '(no stderr)');
    } finally {
      fs.rmSync(tmpRoot, { recursive: true, force: true });
    }
  });
});
