/**
 * Feature New Command
 *
 * Creates a new feature with a git branch and worktree.
 *
 * Usage: shep feat new <description> [options]
 *
 * @example
 * $ shep feat new "Add user authentication"
 * $ shep feat new "Add login page" --repo /path/to/project
 */
import { Command } from 'commander';
import { createHash } from 'node:crypto';
import { existsSync } from 'node:fs';
import { join, resolve } from 'node:path';
import { container } from '../../../../../packages/core/src/infrastructure/di/container.js';
import { CreateFeatureUseCase } from '../../../../../packages/core/src/application/use-cases/features/create/create-feature.use-case.js';
import { CreateFeatureFromRemoteUseCase } from '../../../../../packages/core/src/application/use-cases/features/create/create-feature-from-remote.use-case.js';
import { SdlcLifecycle } from '../../../../../packages/core/src/domain/generated/output.js';
import { colors, messages, spinner } from '../../ui/index.js';
import { getCliI18n } from '../../i18n.js';
import { getShepHomeDir } from '../../../../../packages/core/src/infrastructure/services/filesystem/shep-directory.service.js';
import { getSettings, hasSettings } from '../../../../../packages/core/src/infrastructure/services/settings.service.js';
import { CheckOnboardingStatusUseCase } from '../../../../../packages/core/src/application/use-cases/settings/check-onboarding-status.use-case.js';
import { onboardingWizard } from '../../../tui/wizards/onboarding/onboarding.wizard.js';
/** Commander collect pattern for repeatable options. */
function collect(value, previous) {
    return [...previous, value];
}
function getWorkflowDefaults() {
    if (!hasSettings()) {
        return {
            openPr: false,
            allowPrd: false,
            allowPlan: false,
            allowMerge: false,
            push: false,
            fast: true,
        };
    }
    const settings = getSettings();
    const gates = settings.workflow.approvalGateDefaults;
    return {
        openPr: settings.workflow.openPrOnImplementationComplete,
        allowPrd: gates.allowPrd,
        allowPlan: gates.allowPlan,
        allowMerge: gates.allowMerge,
        push: gates.pushOnImplementationComplete,
        fast: settings.workflow.defaultFastMode,
    };
}
/**
 * Create the feat new command
 */
export function createNewCommand() {
    const t = getCliI18n().t;
    return new Command('new')
        .description(t('cli:commands.feat.new.description'))
        .argument('<description>', t('cli:commands.feat.new.descriptionArgument'))
        .option('-r, --repo <path>', t('cli:commands.feat.new.repoOption'))
        .option('--remote <url>', t('cli:commands.feat.new.remoteOption'))
        .option('--push', t('cli:commands.feat.new.pushOption'))
        .option('--pr', t('cli:commands.feat.new.prOption'))
        .option('--no-pr', t('cli:commands.feat.new.noPrOption'))
        .option('--allow-prd', t('cli:commands.feat.new.allowPrdOption'))
        .option('--allow-plan', t('cli:commands.feat.new.allowPlanOption'))
        .option('--allow-merge', t('cli:commands.feat.new.allowMergeOption'))
        .option('--allow-all', t('cli:commands.feat.new.allowAllOption'))
        .option('--parent <fid>', t('cli:commands.feat.new.parentOption'))
        .option('--pending', t('cli:commands.feat.new.pendingOption'))
        .option('--fast', t('cli:commands.feat.new.fastOption'))
        .option('--no-fast', t('cli:commands.feat.new.noFastOption'))
        .option('--model <model>', t('cli:commands.feat.new.modelOption'))
        .option('--no-rebase', t('cli:commands.feat.new.noRebaseOption'))
        .option('--inject-skills', t('cli:commands.feat.new.injectSkillsOption'))
        .option('--no-inject-skills', t('cli:commands.feat.new.noInjectSkillsOption'))
        .option('--attach <path>', t('cli:commands.feat.new.attachOption'), collect, [])
        .action(async (description, options) => {
        try {
            // Conflict check: --remote and --repo are mutually exclusive
            if (options.remote && options.repo) {
                messages.error(t('cli:commands.feat.new.remoteConflict'));
                process.exitCode = 1;
                return;
            }
            // First-run onboarding gate — only for interactive terminals
            if (process.stdin.isTTY) {
                const checkOnboarding = container.resolve(CheckOnboardingStatusUseCase);
                const { isComplete } = await checkOnboarding.execute();
                if (!isComplete) {
                    await onboardingWizard();
                }
            }
            const repoPath = options.repo ?? process.cwd();
            // Resolve openPr from CLI flags or settings defaults
            const defaults = getWorkflowDefaults();
            const openPr = options.pr ?? defaults.openPr;
            // Build approval gates from flags, falling back to settings defaults
            const approvalGates = options.allowAll
                ? { allowPrd: true, allowPlan: true, allowMerge: true }
                : {
                    allowPrd: options.allowPrd ?? defaults.allowPrd,
                    allowPlan: options.allowPlan ?? defaults.allowPlan,
                    allowMerge: options.allowMerge ?? defaults.allowMerge,
                };
            const push = options.push ?? defaults.push;
            // Resolve parent feature ID if --parent flag is provided
            let parentId;
            if (options.parent) {
                const featureRepo = container.resolve('IFeatureRepository');
                const parentFeature = await featureRepo.findByIdPrefix(options.parent);
                if (!parentFeature) {
                    messages.error(t('cli:commands.feat.new.parentNotFound', { id: options.parent }));
                    process.exitCode = 1;
                    return;
                }
                parentId = parentFeature.id;
            }
            // Validate --attach paths
            const attachmentPaths = [];
            if (options.attach && options.attach.length > 0) {
                for (const raw of options.attach) {
                    const resolved = resolve(raw);
                    if (!existsSync(resolved)) {
                        messages.error(t('cli:commands.feat.new.attachmentNotFound', { path: resolved }));
                        process.exitCode = 1;
                        return;
                    }
                    attachmentPaths.push(resolved);
                }
            }
            const fast = options.fast ?? defaults.fast;
            const commonInput = {
                userInput: description,
                approvalGates,
                push,
                openPr,
                ...(parentId !== undefined && { parentId }),
                ...(options.pending && { pending: true }),
                ...(fast && { fast: true }),
                ...(options.model !== undefined && { model: options.model }),
                ...(attachmentPaths.length > 0 && { attachmentPaths }),
            };
            let result;
            if (options.remote) {
                // Remote path: clone (or fork) then create feature
                const settings = getSettings();
                const defaultCloneDir = settings.environment?.defaultCloneDirectory;
                const remoteUseCase = container.resolve(CreateFeatureFromRemoteUseCase);
                result = await spinner(t('cli:commands.feat.new.spinnerText'), () => remoteUseCase.execute({
                    ...commonInput,
                    remoteUrl: options.remote,
                    defaultCloneDir,
                }));
            }
            else {
                // Local path: create feature on existing repo
                const useCase = container.resolve(CreateFeatureUseCase);
                result = await spinner(t('cli:commands.feat.new.spinnerText'), () => useCase.execute({
                    ...commonInput,
                    repositoryPath: repoPath,
                    ...(options.injectSkills !== undefined && { injectSkills: options.injectSkills }),
                    rebaseBeforeBranch: options.rebase,
                }));
            }
            const { feature, warning } = result;
            const repoHash = createHash('sha256').update(repoPath).digest('hex').slice(0, 16);
            const wtSlug = feature.branch.replace(/\//g, '-');
            const worktreePath = join(getShepHomeDir(), 'repos', repoHash, 'wt', wtSlug);
            messages.newline();
            if (warning) {
                messages.warning(warning);
            }
            messages.success(t('cli:commands.feat.new.featureCreated'));
            if (feature.lifecycle === SdlcLifecycle.Blocked) {
                messages.info(t('cli:commands.feat.new.blockedInfo'));
            }
            if (feature.lifecycle === SdlcLifecycle.Pending) {
                messages.info(t('cli:commands.feat.new.pendingInfo', {
                    command: colors.accent(`shep feat start ${feature.id.slice(0, 8)}`),
                }));
            }
            console.log(`  ${colors.muted(t('cli:commands.feat.new.idLabel'))}       ${colors.accent(feature.id)}`);
            console.log(`  ${colors.muted(t('cli:commands.feat.new.nameLabel'))}     ${feature.name}`);
            console.log(`  ${colors.muted(t('cli:commands.feat.new.branchLabel'))}   ${colors.accent(feature.branch)}`);
            console.log(`  ${colors.muted(t('cli:commands.feat.new.statusLabel'))}   ${feature.lifecycle}`);
            console.log(`  ${colors.muted(t('cli:commands.feat.new.worktreeLabel'))} ${worktreePath}`);
            if (feature.specPath) {
                console.log(`  ${colors.muted(t('cli:commands.feat.new.specLabel'))}     ${feature.specPath}`);
            }
            if (feature.agentRunId) {
                const agentStatus = feature.lifecycle === SdlcLifecycle.Pending
                    ? colors.muted(t('cli:commands.feat.new.pendingStatus'))
                    : colors.success(t('cli:commands.feat.new.spawnedStatus'));
                console.log(`  ${colors.muted(t('cli:commands.feat.new.agentLabel'))}    ${agentStatus} (run ${feature.agentRunId.slice(0, 8)})`);
            }
            if (push || openPr) {
                const pushHint = openPr
                    ? t('cli:commands.feat.new.pushPr')
                    : t('cli:commands.feat.new.pushOnly');
                console.log(`  ${colors.muted(t('cli:commands.feat.new.pushLabel'))}     ${pushHint}`);
            }
            const approved = [
                approvalGates.allowPrd && 'PRD',
                approvalGates.allowPlan && 'Plan',
                approvalGates.allowMerge && 'Merge',
            ].filter(Boolean);
            const hint = approved.length === 3
                ? t('cli:commands.feat.new.fullyAutonomous')
                : approved.length === 0
                    ? t('cli:commands.feat.new.pauseAfterEvery')
                    : t('cli:commands.feat.new.autoApprove', { approved: approved.join(', ') });
            console.log(`  ${colors.muted(t('cli:commands.feat.new.reviewLabel'))}   ${hint}`);
            messages.newline();
        }
        catch (error) {
            const err = error instanceof Error ? error : new Error(String(error));
            messages.error(t('cli:commands.feat.new.failedToCreate'), err);
            process.exitCode = 1;
        }
    });
}
