/**
 * mx init command implementation.
 *
 * Creates matrix.json and scaffolds directory structure.
 * Implementation: B013
 */

import * as fs from 'node:fs';
import * as path from 'node:path';
import * as readline from 'node:readline/promises';
import { stdin as input, stdout as output } from 'node:process';
import { validateMatrixManifest, writeJsonFile } from '../utils/scaffold.js';

export interface IInitCommandOptions {
  readonly cwd?: string;
  readonly name?: string;
  readonly version?: string;
  readonly description?: string;
  readonly yes?: boolean;
}

export interface IInitCommandResult {
  readonly rootDir: string;
  readonly manifestPath: string;
}

function defaultPackageName(cwd: string): string {
  return path.basename(cwd) || 'matrix-package';
}

async function promptIfNeeded(
  question: string,
  fallback: string,
  enabled: boolean,
  rl: readline.Interface
): Promise<string> {
  if (!enabled) {
    return fallback;
  }

  const suffix = fallback.length > 0 ? ` (${fallback})` : '';
  const answer = (await rl.question(`${question}${suffix}: `)).trim();
  return answer.length > 0 ? answer : fallback;
}

export async function initCommand(options: IInitCommandOptions = {}): Promise<IInitCommandResult> {
  const cwd = path.resolve(options.cwd ?? process.cwd());
  const shouldPrompt = options.yes !== true;

  const rl = readline.createInterface({ input, output });
  try {
    const name = await promptIfNeeded(
      'Package name',
      options.name ?? defaultPackageName(cwd),
      shouldPrompt,
      rl
    );
    const version = await promptIfNeeded(
      'Version',
      options.version ?? '0.1.0',
      shouldPrompt,
      rl
    );
    const description = await promptIfNeeded(
      'Description',
      options.description ?? '',
      shouldPrompt,
      rl
    );

    const manifest = {
      name,
      version,
      description,
      runtime: { language: 'typescript', entry: 'dist/index.js' },
      components: [],
      permissions: { fsPolicy: 'none' },
    };

    const validation = validateMatrixManifest(manifest);
    if (!validation.valid) {
      throw new Error(`Generated matrix.json failed validation: ${validation.errors.join('; ')}`);
    }

    fs.mkdirSync(path.join(cwd, 'src'), { recursive: true });
    fs.mkdirSync(path.join(cwd, 'examples'), { recursive: true });
    fs.mkdirSync(path.join(cwd, 'skills'), { recursive: true });
    fs.mkdirSync(path.join(cwd, 'tests'), { recursive: true });

    const manifestPath = path.join(cwd, 'matrix.json');
    writeJsonFile(manifestPath, manifest);

    const srcIndex = path.join(cwd, 'src', 'index.ts');
    if (!fs.existsSync(srcIndex)) {
      fs.writeFileSync(
        srcIndex,
        [
          '// Entry point for your Matrix package.',
          '// Add exports for your actors/services here.',
          'export {};',
          '',
        ].join('\n'),
        'utf8'
      );
    }

    const testScaffold = path.join(cwd, 'tests', 'package.spec.ts');
    if (!fs.existsSync(testScaffold)) {
      fs.writeFileSync(
        testScaffold,
        [
          "import { describe, it } from 'node:test';",
          "import { strict as assert } from 'node:assert';",
          '',
          "describe('package scaffold', () => {",
          "  it('has a valid matrix manifest placeholder', () => {",
          "    assert.equal(true, true);",
          '  });',
          '});',
          '',
        ].join('\n'),
        'utf8'
      );
    }

    console.log('Created matrix.json');
    console.log('Created src/, examples/, skills/, and tests/');

    return { rootDir: cwd, manifestPath };
  } finally {
    rl.close();
  }
}
