/**
 * BeadsStateManager
 *
 * Manages beads-specific conversation state including phase task mappings
 * and epic information. Provides persistent storage for beads integration
 * data with proper separation of concerns from conversation management.
 */
import { writeFile, readFile, mkdir, access } from 'node:fs/promises';
import { join, dirname } from 'node:path';
import { createLogger } from './logger.js';
const logger = createLogger('BeadsStateManager');
/**
 * Manager for beads conversation state persistence
 */
export class BeadsStateManager {
    projectPath;
    constructor(projectPath) {
        this.projectPath = projectPath;
    }
    /**
     * Get the path to the beads state file for a conversation
     */
    getBeadsStatePath(conversationId) {
        return join(this.projectPath, '.vibe', `beads-state-${conversationId}.json`);
    }
    /**
     * Create beads state for a conversation
     */
    async createState(conversationId, epicId, phaseTasks) {
        const state = {
            conversationId,
            projectPath: this.projectPath,
            epicId,
            phaseTasks,
            createdAt: new Date().toISOString(),
            updatedAt: new Date().toISOString(),
        };
        await this.saveState(state);
        logger.info('Created beads conversation state', {
            conversationId,
            epicId,
            phaseCount: phaseTasks.length,
            projectPath: this.projectPath,
        });
        return state;
    }
    /**
     * Get beads state for a conversation
     */
    async getState(conversationId) {
        const statePath = this.getBeadsStatePath(conversationId);
        try {
            // Check if file exists
            await access(statePath);
            const content = await readFile(statePath, 'utf-8');
            const state = JSON.parse(content);
            logger.debug('Retrieved beads conversation state', {
                conversationId,
                epicId: state.epicId,
                phaseCount: state.phaseTasks.length,
                projectPath: this.projectPath,
            });
            return state;
        }
        catch (error) {
            if (error.code === 'ENOENT') {
                // File doesn't exist - this is normal for conversations without beads
                logger.debug('No beads state found for conversation', {
                    conversationId,
                    projectPath: this.projectPath,
                });
                return null;
            }
            // Other errors (permission, invalid JSON, etc.)
            const errorMessage = error instanceof Error ? error.message : String(error);
            logger.warn('Failed to read beads state file', {
                error: errorMessage,
                conversationId,
                statePath,
                projectPath: this.projectPath,
            });
            return null;
        }
    }
    /**
     * Get phase task ID for a specific phase
     */
    async getPhaseTaskId(conversationId, phase) {
        const state = await this.getState(conversationId);
        if (!state) {
            return null;
        }
        const phaseTask = state.phaseTasks.find(task => task.phaseId === phase);
        if (phaseTask) {
            logger.debug('Found phase task ID', {
                conversationId,
                phase,
                taskId: phaseTask.taskId,
                projectPath: this.projectPath,
            });
            return phaseTask.taskId;
        }
        logger.debug('No task ID found for phase', {
            conversationId,
            phase,
            availablePhases: state.phaseTasks.map(t => t.phaseId),
            projectPath: this.projectPath,
        });
        return null;
    }
    /**
     * Update beads state for a conversation
     */
    async updateState(conversationId, updates) {
        const existingState = await this.getState(conversationId);
        if (!existingState) {
            logger.warn('Cannot update non-existent beads state', {
                conversationId,
                projectPath: this.projectPath,
            });
            return null;
        }
        const updatedState = {
            ...existingState,
            ...updates,
            conversationId, // Ensure conversationId doesn't change
            updatedAt: new Date().toISOString(),
        };
        await this.saveState(updatedState);
        logger.info('Updated beads conversation state', {
            conversationId,
            updatedFields: Object.keys(updates),
            projectPath: this.projectPath,
        });
        return updatedState;
    }
    /**
     * Clean up beads state for a conversation
     */
    async cleanup(conversationId) {
        const statePath = this.getBeadsStatePath(conversationId);
        try {
            await access(statePath);
            await writeFile(statePath + '.backup', await readFile(statePath));
            logger.info('Cleaned up beads conversation state', {
                conversationId,
                statePath,
                projectPath: this.projectPath,
            });
        }
        catch (error) {
            if (error.code === 'ENOENT') {
                // File doesn't exist - nothing to clean up
                logger.debug('No beads state to clean up', {
                    conversationId,
                    projectPath: this.projectPath,
                });
                return;
            }
            const errorMessage = error instanceof Error ? error.message : String(error);
            logger.warn('Failed to clean up beads state', {
                error: errorMessage,
                conversationId,
                statePath,
                projectPath: this.projectPath,
            });
        }
    }
    /**
     * Check if beads state exists for a conversation
     */
    async hasState(conversationId) {
        const statePath = this.getBeadsStatePath(conversationId);
        try {
            await access(statePath);
            return true;
        }
        catch {
            return false;
        }
    }
    /**
     * Save beads state to file
     */
    async saveState(state) {
        const statePath = this.getBeadsStatePath(state.conversationId);
        const stateDir = dirname(statePath);
        try {
            // Ensure .vibe directory exists
            await mkdir(stateDir, { recursive: true });
            // Write state with pretty formatting for readability
            const content = JSON.stringify(state, null, 2);
            await writeFile(statePath, content, 'utf-8');
            logger.debug('Saved beads state to file', {
                conversationId: state.conversationId,
                statePath,
                fileSize: content.length,
                projectPath: this.projectPath,
            });
        }
        catch (error) {
            const errorMessage = error instanceof Error ? error.message : String(error);
            logger.error('Failed to save beads state', error instanceof Error ? error : new Error(errorMessage), {
                conversationId: state.conversationId,
                statePath,
                projectPath: this.projectPath,
            });
            throw error;
        }
    }
}
//# sourceMappingURL=beads-state-manager.js.map