import { readFile as defaultReadFile, writeFile as defaultWriteFile, } from 'node:fs/promises';
import { join } from 'node:path';
import { buildCommandContext } from '../../../app/command-context.js';
import { getFrontmatterBlock } from '../../shared/frontmatter.js';
import { removeFrontmatterField, replaceFrontmatter, upsertFrontmatterField, } from '../../shared/frontmatter-write.js';
import { resolveProjectsRoot } from '../../shared/oat-paths.js';
import { readGlobalOptions } from '../../shared/shared.utils.js';
import { generateStateDashboard as defaultGenerateStateDashboard, } from '../../state/generate.js';
import { clearActiveProject, readOatLocalConfig, } from '../../../config/oat-config.js';
import { dirExists, fileExists } from '../../../fs/io.js';
import { resolveProjectRoot } from '../../../fs/paths.js';
import { assertValidProjectStateFilesystemContent } from '../../../validation/project-state.js';
import { Command } from 'commander';
const DEFAULT_DEPENDENCIES = {
    buildCommandContext,
    resolveProjectRoot,
    resolveProjectsRoot,
    readOatLocalConfig,
    clearActiveProject,
    generateStateDashboard: defaultGenerateStateDashboard,
    readFile: defaultReadFile,
    writeFile: defaultWriteFile,
    dirExists,
    fileExists,
    processEnv: process.env,
    now: () => new Date(),
};
async function runProjectPause(projectName, options, context, dependencies) {
    try {
        const repoRoot = await dependencies.resolveProjectRoot(context.cwd);
        const projectsRoot = await dependencies.resolveProjectsRoot(repoRoot, dependencies.processEnv);
        const localConfig = await dependencies.readOatLocalConfig(repoRoot);
        const activeProject = localConfig.activeProject ?? null;
        let projectPath;
        let resolvedProjectName;
        if (projectName) {
            projectPath = join(projectsRoot, projectName);
            resolvedProjectName = projectName;
        }
        else {
            if (!activeProject) {
                throw new Error('No project specified and no active project');
            }
            projectPath = activeProject;
            resolvedProjectName = projectPath.split('/').at(-1) ?? projectPath;
        }
        const fullProjectPath = join(repoRoot, projectPath);
        if (!(await dependencies.dirExists(fullProjectPath))) {
            throw new Error(`Project not found: ${resolvedProjectName}`);
        }
        const statePath = join(fullProjectPath, 'state.md');
        if (!(await dependencies.fileExists(statePath))) {
            throw new Error(`Project state.md not found: ${statePath}`);
        }
        const content = await dependencies.readFile(statePath, 'utf8');
        const frontmatter = getFrontmatterBlock(content);
        if (!frontmatter) {
            throw new Error(`state.md is missing frontmatter: ${statePath}`);
        }
        let nextBlock = upsertFrontmatterField(frontmatter, 'oat_lifecycle', 'paused', true).nextBlock;
        const nowIso = dependencies.now().toISOString();
        nextBlock = upsertFrontmatterField(nextBlock, 'oat_pause_timestamp', nowIso, true).nextBlock;
        nextBlock = upsertFrontmatterField(nextBlock, 'oat_project_state_updated', nowIso, true).nextBlock;
        if (options.reason) {
            nextBlock = upsertFrontmatterField(nextBlock, 'oat_pause_reason', options.reason, true).nextBlock;
        }
        else {
            nextBlock = removeFrontmatterField(nextBlock, 'oat_pause_reason');
        }
        if (nextBlock !== frontmatter) {
            const nextContent = replaceFrontmatter(content, nextBlock);
            await assertValidProjectStateFilesystemContent(nextContent, {
                filePath: statePath,
                projectPath: fullProjectPath,
            });
            await dependencies.writeFile(statePath, nextContent, 'utf8');
        }
        const pointerCleared = activeProject === projectPath;
        if (pointerCleared) {
            await dependencies.clearActiveProject(repoRoot, {
                lastPaused: projectPath,
            });
        }
        await dependencies.generateStateDashboard({ repoRoot });
        if (context.json) {
            context.logger.json({
                status: 'ok',
                projectName: resolvedProjectName,
                projectPath,
                pointerCleared,
                reason: options.reason ?? null,
            });
        }
        else {
            context.logger.info(`Paused project: ${resolvedProjectName}`);
            if (pointerCleared) {
                context.logger.info('Cleared active project pointer.');
            }
        }
        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 createProjectPauseCommand(overrides = {}) {
    const dependencies = {
        ...DEFAULT_DEPENDENCIES,
        ...overrides,
    };
    return new Command('pause')
        .description('Pause an OAT project')
        .argument('[name]', 'Project name (defaults to active project)')
        .option('--reason <string>', 'Optional reason to persist in project state')
        .action(async (name, options, command) => {
        const context = dependencies.buildCommandContext(readGlobalOptions(command));
        await runProjectPause(name, options, context, dependencies);
    });
}
