import { buildCommandContext, } from '../../../app/command-context.js';
import { upsertAgentsMdSection, } from '../../shared/agents-md.js';
import { confirmAction, inputWithDefault, selectWithAbort, } from '../../shared/shared.prompts.js';
import { readGlobalOptions } from '../../shared/shared.utils.js';
import { readOatConfig, writeOatConfig, } from '../../../config/oat-config.js';
import { resolveAssetsRoot } from '../../../fs/assets.js';
import { Command, Option } from 'commander';
import { buildDocsCommands } from './docs-commands.js';
import { DEFAULT_DOCS_REPO_SHAPE_DEPENDENCIES, detectDocsRepoShape, getDefaultDocsAppName, resolveDocsInitOptions, } from './resolve-options.js';
import { patchRootPackageJson, } from './root-package.js';
import { scaffoldDocsApp } from './scaffold.js';
function logRootPackagePatch(context, result) {
    if (result.status === 'disabled') {
        context.logger.info('Skipped root package.json patch (--no-root-patch).');
        return;
    }
    if (result.diff) {
        context.logger.info('');
        context.logger.info('Root package.json diff:');
        context.logger.info(result.diff);
    }
    if (result.status === 'applied') {
        context.logger.info('Updated the root Turbo build scripts to exclude the docs app from the default build and added `build:docs`.');
    }
    else if (result.status === 'dry-run') {
        context.logger.info('Dry run: the root Turbo build script patch was previewed but not written.');
        context.logger.info('Run without --dry-run to apply these changes.');
    }
    else if (result.status === 'already-configured') {
        context.logger.info('Root package.json already excludes the docs app from the default Turbo build and exposes `build:docs`.');
    }
    else if (result.status === 'skipped') {
        for (const warning of result.warnings) {
            context.logger.warn(warning);
        }
        if (result.manualSnippet) {
            context.logger.info('');
            context.logger.info('Recommended manual Turbo script snippet for the repo root:');
            context.logger.info(result.manualSnippet);
        }
        return;
    }
    for (const warning of result.warnings) {
        context.logger.warn(warning);
    }
}
const DEFAULT_DEPENDENCIES = {
    buildCommandContext,
    resolveAssetsRoot,
    detectRepoShape: (repoRoot) => detectDocsRepoShape(repoRoot, DEFAULT_DOCS_REPO_SHAPE_DEPENDENCIES),
    inputWithDefault,
    selectWithAbort,
    runDocsInit: async (context, options, assetsRoot) => {
        const result = await scaffoldDocsApp({
            assetsRoot,
            ...options,
        });
        const rootPackagePatch = await patchRootPackageJson({
            repoRoot: context.cwd,
            appName: options.appName,
            dryRun: context.dryRun,
            enabled: options.rootPatch,
        });
        const config = await readOatConfig(context.cwd);
        config.documentation = {
            ...config.documentation,
            ...result.documentationConfig,
        };
        await writeOatConfig(context.cwd, config);
        if (context.json) {
            context.logger.json({
                status: 'ok',
                ...options,
                createdFiles: result.createdFiles,
                appRoot: result.appRoot,
                rootPackagePatch,
            });
            return;
        }
        context.logger.info(`Scaffolded docs app at ${options.targetDir}`);
        context.logger.info(`  Framework: ${options.framework}`);
        context.logger.info(`  Repo shape: ${options.repoShape}`);
        context.logger.info(`  App name: ${options.appName}`);
        context.logger.info(`  Lint: ${options.lint}`);
        context.logger.info(`  Format: ${options.format}`);
        logRootPackagePatch(context, rootPackagePatch);
    },
    upsertAgentsMdSection,
    readOatConfig,
    confirmAction,
};
const FRAMEWORK_LABELS = {
    fumadocs: 'Fumadocs (Next.js + MDX)',
    mkdocs: 'MkDocs (Python)',
};
export function buildDocsSectionBody(options) {
    const lines = [
        '## Documentation',
        '',
        `- **Docs root:** \`${options.targetDir}\``,
        `- **Framework:** ${FRAMEWORK_LABELS[options.framework]}`,
        `- **Index file:** \`${options.targetDir}/docs/index.md\``,
    ];
    if (options.framework === 'mkdocs') {
        lines.push(`- **Config:** \`${options.targetDir}/mkdocs.yml\``);
    }
    return lines.join('\n');
}
async function runDocsInitCommand(context, options, dependencies) {
    try {
        const repoShape = await dependencies.detectRepoShape(context.cwd);
        const resolved = await resolveDocsInitOptions({
            repoRoot: context.cwd,
            repoShape,
            interactive: context.interactive,
            acceptDefaults: options.yes ?? false,
            providedFramework: options.framework,
            providedAppName: options.appName,
            providedSiteName: options.siteName,
            providedTargetDir: options.targetDir,
            providedSiteDescription: options.description,
            providedLint: options.lint,
            providedFormat: options.format,
            providedRootPatch: options.rootPatch,
            inputWithDefault: dependencies.inputWithDefault,
            selectWithAbort: dependencies.selectWithAbort,
        });
        if (!resolved) {
            if (!context.json) {
                context.logger.info('Docs init cancelled.');
            }
            process.exitCode = 0;
            return;
        }
        const existingConfig = await dependencies.readOatConfig(context.cwd);
        if (existingConfig.documentation?.root) {
            const configDesc = `root: ${existingConfig.documentation.root}, tooling: ${existingConfig.documentation.tooling ?? 'unknown'}`;
            if (context.json) {
                // JSON mode: include warning in output, proceed only with --yes
                if (!options.yes) {
                    context.logger.json({
                        status: 'error',
                        message: `Existing docs config found (${configDesc}). Use --yes to replace.`,
                    });
                    process.exitCode = 1;
                    return;
                }
            }
            else {
                context.logger.warn(`Existing docs config detected (${configDesc}). This will replace the current setup.`);
                if (!options.yes) {
                    const proceed = await dependencies.confirmAction('Replace existing docs setup?', { interactive: context.interactive });
                    if (!proceed) {
                        context.logger.info('Docs init cancelled.');
                        process.exitCode = 1;
                        return;
                    }
                }
            }
        }
        const assetsRoot = await dependencies.resolveAssetsRoot();
        await dependencies.runDocsInit(context, resolved, assetsRoot);
        const sectionBody = buildDocsSectionBody(resolved);
        const sectionResult = await dependencies.upsertAgentsMdSection(context.cwd, 'docs', sectionBody);
        if (!context.json && sectionResult.action !== 'no-change') {
            context.logger.info(`AGENTS.md docs section ${sectionResult.action}.`);
        }
        if (!context.json) {
            context.logger.info('');
            context.logger.info('Next steps:');
            const commands = buildDocsCommands(resolved.repoShape, resolved.targetDir, resolved.appName);
            context.logger.info(`  ${commands.install}`);
            context.logger.info(`  ${commands.dev}`);
            context.logger.info(`  ${commands.build}`);
            if (resolved.repoShape === 'monorepo') {
                const defaultName = getDefaultDocsAppName(context.cwd, resolved.repoShape);
                if (resolved.appName !== defaultName) {
                    context.logger.info('');
                    context.logger.info(`Note: Your docs app is named "${resolved.appName}" — if you have root scripts or CI filters referencing "${defaultName}", update them to match.`);
                }
            }
        }
        process.exitCode = 0;
    }
    catch (error) {
        const message = error instanceof Error ? error.message : String(error);
        if (context.json) {
            context.logger.json({ status: 'error', message });
        }
        else {
            context.logger.error(message);
        }
        process.exitCode = 1;
    }
}
export function createDocsInitCommand(overrides = {}) {
    const dependencies = {
        ...DEFAULT_DEPENDENCIES,
        ...overrides,
    };
    return new Command('init')
        .description('Scaffold an OAT docs app')
        .addOption(new Option('--framework <framework>', 'Documentation framework').choices([
        'fumadocs',
        'mkdocs',
    ]))
        .addOption(new Option('--app-name <name>', 'Docs app name'))
        .addOption(new Option('--site-name <name>', 'Display title (distinct from --app-name)'))
        .addOption(new Option('--target-dir <path>', 'Target directory for the docs app'))
        .addOption(new Option('--description <text>', 'Site description'))
        .addOption(new Option('--lint <mode>', 'Markdown lint mode').choices([
        'none',
        'markdownlint-cli2',
    ]))
        .addOption(new Option('--format <mode>', 'Markdown format mode').choices([
        'oxfmt',
        'none',
    ]))
        .option('--no-root-patch', 'Skip patching the consumer root package.json')
        .option('--yes', 'Accept defaults without prompting')
        .action(async (options, command) => {
        const context = dependencies.buildCommandContext(readGlobalOptions(command));
        await runDocsInitCommand(context, options, dependencies);
    });
}
