import { Command } from 'commander';

import { PrdService } from './service.js';
import { runPrdWizard } from './wizard.js';

interface InitCommandOptions {
  readonly name: string;
  readonly project: string;
  readonly template?: 'software' | 'feature' | 'spike';
}

interface ListCommandOptions {
  readonly project: string;
}

interface ShowCommandOptions {
  readonly project: string;
  readonly id?: string;
}

interface ImportCommandOptions {
  readonly project: string;
  readonly file: string;
  readonly acceptSuccessor?: boolean;
}

interface ExportCommandOptions {
  readonly project: string;
  readonly id?: string;
  readonly out?: string;
}

function serviceFor(project: string): PrdService {
  return new PrdService({ projectPath: project });
}

export function buildPrdyCli(): Command {
  const program = new Command();
  program.name('mosaic').description('Mosaic CLI').exitOverride();

  const prdy = program.command('prdy').description('PRD wizard commands');

  prdy
    .command('init')
    .description('Create a PRD document')
    .requiredOption('--name <name>', 'PRD name')
    .requiredOption('--project <path>', 'Project path')
    .option('--template <template>', 'Template (software|feature|spike)')
    .action(async (options: InitCommandOptions) => {
      const doc = process.stdout.isTTY
        ? await runPrdWizard({
            name: options.name,
            projectPath: options.project,
            template: options.template,
            interactive: true,
          })
        : await serviceFor(options.project).create({
            name: options.name,
            template: options.template,
          });

      console.log(
        JSON.stringify(
          {
            ok: true,
            id: doc.id,
            title: doc.title,
            status: doc.status,
            version: doc.version,
            projectPath: doc.projectPath,
          },
          null,
          2,
        ),
      );
    });

  prdy
    .command('list')
    .description('List PRD documents for a project')
    .requiredOption('--project <path>', 'Project path')
    .action(async (options: ListCommandOptions) => {
      const docs = await serviceFor(options.project).list();
      console.log(JSON.stringify(docs, null, 2));
    });

  prdy
    .command('show')
    .description('Show a PRD document')
    .requiredOption('--project <path>', 'Project path')
    .option('--id <id>', 'PRD document id')
    .action(async (options: ShowCommandOptions) => {
      const doc = await serviceFor(options.project).get(options.id);
      console.log(JSON.stringify(doc, null, 2));
    });

  prdy
    .command('import')
    .description('Import a YAML PRD document (validated; conflicts propose a successor)')
    .requiredOption('--project <path>', 'Project path')
    .requiredOption('--file <file>', 'Path to YAML PRD document')
    .option('--accept-successor', 'Accept a conflicted import as the next version')
    .action(async (options: ImportCommandOptions) => {
      const service = serviceFor(options.project);
      const input = { filePath: options.file };

      if (options.acceptSuccessor) {
        const successor = await service.acceptSuccessor(input);
        console.log(
          JSON.stringify(
            {
              ok: true,
              outcome: 'successor-accepted',
              id: successor.id,
              version: successor.version,
            },
            null,
            2,
          ),
        );
        return;
      }

      const result = await service.importDocument(input);
      console.log(
        JSON.stringify(
          {
            ok: true,
            outcome: result.kind,
            id: result.document.id,
            version: result.document.version,
            status: result.document.status,
          },
          null,
          2,
        ),
      );
    });

  prdy
    .command('export')
    .description('Render a PRD to a labeled generated-view Markdown file')
    .requiredOption('--project <path>', 'Project path')
    .option('--id <id>', 'PRD document id')
    .option('--out <path>', 'Output path (default docs/prdy/<id>.md)')
    .action(async (options: ExportCommandOptions) => {
      const result = await serviceFor(options.project).exportMarkdown({
        id: options.id,
        outPath: options.out,
      });
      console.log(JSON.stringify({ ok: true, filePath: result.filePath }, null, 2));
    });

  return program;
}

export async function runPrdyCli(argv: readonly string[] = process.argv): Promise<void> {
  const program = buildPrdyCli();
  await program.parseAsync(argv);
}
