// cli/commands/spec.ts — planu spec <subcommand> (SPEC-609)
//
// Subcommands:
//   planu spec create "title"         → calls handleCreateSpec
//   planu spec list [--status X]      → calls handleListSpecs
//   planu spec show SPEC-NNN          → reads spec from storage
//   planu spec status SPEC-NNN done   → calls handleUpdateStatus
//   planu spec validate SPEC-NNN      → calls handleValidate
import { parseArgs } from 'node:util';
import { resolve } from 'node:path';
import { handleCreateSpec } from '../../tools/create-spec.js';
import { handleListSpecs } from '../../tools/list-specs.js';
import { handleUpdateStatus } from '../../tools/update-status.js';
import { handleUpdateStatusBatch } from '../../tools/update-status/batch.js';
import { handleValidate } from '../../tools/validate.js';
import { formatToolResult } from '../formatter.js';
import { detectProjectId } from '../project-detector.js';
import { bold, cyan, green, red, dim } from '../colors.js';
// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------
function printSpecSubcommandHelp() {
    const lines = [
        `${bold('planu spec')} — Manage specs`,
        '',
        `${cyan('Usage:')} planu spec <subcommand> [args]`,
        '',
        cyan('Subcommands:'),
        `  ${'create'.padEnd(10)} ${dim('Create a new spec')}`,
        `  ${'list'.padEnd(10)} ${dim('List specs [--status draft|approved|done...]')}`,
        `  ${'show'.padEnd(10)} ${dim('Show spec details (SPEC-NNN)')}`,
        `  ${'status'.padEnd(10)} ${dim('Update spec status (SPEC-NNN <status>)')}`,
        `  ${'validate'.padEnd(10)} ${dim('Validate a spec against its codebase')}`,
        '',
        cyan('Examples:'),
        `  planu spec create "Add login flow"`,
        `  planu spec list --status approved`,
        `  planu spec show SPEC-001`,
        `  planu spec status SPEC-001 done`,
        `  planu spec validate SPEC-001`,
    ];
    process.stdout.write(lines.join('\n') + '\n');
}
// ---------------------------------------------------------------------------
// Subcommand: spec validate
// ---------------------------------------------------------------------------
async function runValidate(args, flags) {
    const { positionals, values } = parseArgs({
        args,
        options: {
            'project-id': { type: 'string' },
        },
        strict: false,
        allowPositionals: true,
    });
    const specId = positionals[0];
    if (!specId) {
        process.stderr.write(`${red('Error:')} Spec ID is required.\nUsage: planu spec validate SPEC-NNN\n`);
        process.exitCode = 1;
        return;
    }
    const projectId = values['project-id'] ?? detectProjectId();
    const result = await handleValidate({ specId, projectId });
    if (result.isError) {
        process.stderr.write(`${red(formatToolResult(result, flags))}\n`);
        process.exitCode = 1;
        return;
    }
    const output = formatToolResult(result, flags);
    if (output) {
        process.stdout.write(output + '\n');
    }
}
// ---------------------------------------------------------------------------
// Subcommand: spec create
// ---------------------------------------------------------------------------
async function runCreate(args, flags) {
    const { values, positionals } = parseArgs({
        args,
        options: {
            type: { type: 'string', short: 't' },
            description: { type: 'string', short: 'd' },
            path: { type: 'string', short: 'p' },
            scope: { type: 'string' },
            target: { type: 'string' },
            feature: { type: 'string' },
        },
        strict: false,
        allowPositionals: true,
    });
    const title = positionals.join(' ');
    if (!title) {
        process.stderr.write(`${red('Error:')} Title is required.\nUsage: planu spec create "title"\n`);
        process.exitCode = 1;
        return;
    }
    const projectPath = resolve(values.path ?? process.cwd());
    const description = values.description ?? title;
    const result = await handleCreateSpec({
        title,
        description,
        projectPath,
        type: values.type,
        scope: values.scope,
        target: values.target,
        feature: values.feature ?? undefined,
    });
    if (result.isError) {
        process.stderr.write(`${red(formatToolResult(result, flags))}\n`);
        process.exitCode = 1;
        return;
    }
    const output = formatToolResult(result, flags);
    if (flags?.quiet) {
        if (output) {
            process.stdout.write(output + '\n');
        }
    }
    else {
        process.stdout.write(`${green('Spec created!')} ${output}\n`);
    }
}
// ---------------------------------------------------------------------------
// Subcommand: spec list
// ---------------------------------------------------------------------------
async function runList(args, flags) {
    const { values } = parseArgs({
        args,
        options: {
            status: { type: 'string', short: 's' },
            type: { type: 'string', short: 't' },
            'project-id': { type: 'string' },
        },
        strict: false,
        allowPositionals: true,
    });
    const projectId = values['project-id'] ?? detectProjectId();
    const result = await handleListSpecs({
        projectId,
        status: values.status,
        type: values.type,
    });
    if (result.isError) {
        process.stderr.write(`${red(formatToolResult(result, flags))}\n`);
        process.exitCode = 1;
        return;
    }
    const output = formatToolResult(result, flags);
    if (output) {
        process.stdout.write(output + '\n');
    }
}
// ---------------------------------------------------------------------------
// Subcommand: spec show
// ---------------------------------------------------------------------------
async function runShow(args, flags) {
    const { positionals, values } = parseArgs({
        args,
        options: {
            'project-id': { type: 'string' },
        },
        strict: false,
        allowPositionals: true,
    });
    const specId = positionals[0];
    if (!specId) {
        process.stderr.write(`${red('Error:')} Spec ID is required.\nUsage: planu spec show SPEC-NNN\n`);
        process.exitCode = 1;
        return;
    }
    const projectId = values['project-id'] ?? detectProjectId();
    // Import storage lazily to avoid pulling it in when not needed
    const { getSpec } = await import('../../storage/spec-store.js');
    const spec = await getSpec(projectId, specId);
    if (!spec) {
        process.stderr.write(`${red('Error:')} Spec "${specId}" not found in project "${projectId}".\n`);
        process.exitCode = 1;
        return;
    }
    if (flags?.json) {
        process.stdout.write(JSON.stringify(spec, null, 2) + '\n');
        return;
    }
    const lines = [
        '',
        `${bold(spec.id)} — ${spec.title}`,
        `${dim('Status:')}    ${spec.status}`,
        `${dim('Type:')}      ${spec.type}`,
        `${dim('Scope:')}     ${spec.scope}`,
        `${dim('Difficulty:')} ${spec.difficulty}`,
        `${dim('Created:')}   ${spec.createdAt}`,
        `${dim('Updated:')}   ${spec.updatedAt}`,
    ];
    if (spec.tags.length > 0) {
        lines.push(`${dim('Tags:')}      ${spec.tags.join(', ')}`);
    }
    if (spec.dependencies.length > 0) {
        lines.push(`${dim('Depends on:')} ${spec.dependencies.join(', ')}`);
    }
    if (spec.healthScore !== undefined) {
        lines.push(`${dim('Health:')}    ${String(spec.healthScore)}/100`);
    }
    lines.push(`${dim('Spec path:')} ${spec.specPath}`);
    lines.push('');
    process.stdout.write(lines.join('\n') + '\n');
}
// ---------------------------------------------------------------------------
// Subcommand: spec status
// ---------------------------------------------------------------------------
async function runStatus(args, flags) {
    const { positionals, values } = parseArgs({
        args,
        options: {
            'project-id': { type: 'string' },
            notes: { type: 'string', short: 'n' },
            batch: { type: 'boolean' },
            set: { type: 'string', short: 's' },
        },
        strict: false,
        allowPositionals: true,
    });
    const batch = values.batch === true;
    const specId = positionals[0];
    const status = batch ? values.set : positionals[1];
    if (!specId) {
        process.stderr.write(`${red('Error:')} Spec ID is required.\nUsage: planu spec status SPEC-NNN <status>\n`);
        process.exitCode = 1;
        return;
    }
    if (!status) {
        process.stderr.write(`${red('Error:')} Status is required.\nUsage: planu spec status SPEC-NNN <status>\n`);
        process.exitCode = 1;
        return;
    }
    const projectId = values['project-id'] ?? detectProjectId();
    if (batch) {
        const result = await handleUpdateStatusBatch({
            specIds: positionals,
            projectId,
            status: status,
            reviewNotes: values.notes ?? undefined,
        });
        if (result.isError) {
            process.stderr.write(`${red(formatToolResult(result, flags))}\n`);
            process.exitCode = 1;
            return;
        }
        process.stdout.write(formatToolResult(result, flags) + '\n');
        return;
    }
    const result = await handleUpdateStatus({
        specId,
        projectId,
        status: status,
        reviewNotes: values.notes ?? undefined,
    });
    if (result.isError) {
        process.stderr.write(`${red(formatToolResult(result, flags))}\n`);
        process.exitCode = 1;
        return;
    }
    const output = formatToolResult(result, flags);
    if (flags?.quiet) {
        if (output) {
            process.stdout.write(output + '\n');
        }
    }
    else {
        process.stdout.write(`${green('Status updated!')} ${output}\n`);
    }
}
// ---------------------------------------------------------------------------
// Exported command
// ---------------------------------------------------------------------------
export const specCommand = {
    name: 'spec',
    description: 'Manage specs (create, list, show, status)',
    usage: 'planu spec <subcommand> [args]',
    async run(args, flags) {
        const subcommand = args[0];
        const rest = args.slice(1);
        switch (subcommand) {
            case 'create':
                await runCreate(rest, flags);
                break;
            case 'list':
                await runList(rest, flags);
                break;
            case 'show':
                await runShow(rest, flags);
                break;
            case 'status':
                await runStatus(rest, flags);
                break;
            case 'validate':
                await runValidate(rest, flags);
                break;
            case undefined:
            case 'help':
                printSpecSubcommandHelp();
                break;
            default:
                process.stderr.write(`${red('Error:')} Unknown subcommand "${subcommand}"\n`);
                process.stderr.write(`Run ${cyan('planu spec help')} to see available subcommands.\n`);
                process.exitCode = 1;
        }
    },
};
//# sourceMappingURL=spec.js.map