/**
 * Workflow State Manager - Persists and manages workflow state
 */
import fs from 'fs';
import path from 'path';
import os from 'os';
export class WorkflowStateManager {
    statesDir;
    states = new Map();
    constructor(statesDir) {
        this.statesDir = statesDir || path.join(os.homedir(), '.codebuddy', 'workflows');
        this.ensureDir();
        this.loadStates();
    }
    /**
     * Ensure the states directory exists
     */
    ensureDir() {
        if (!fs.existsSync(this.statesDir)) {
            fs.mkdirSync(this.statesDir, { recursive: true });
        }
    }
    /**
     * Load existing states from disk
     */
    loadStates() {
        try {
            const files = fs.readdirSync(this.statesDir);
            for (const file of files) {
                if (!file.endsWith('.json'))
                    continue;
                try {
                    const statePath = path.join(this.statesDir, file);
                    const data = JSON.parse(fs.readFileSync(statePath, 'utf-8'));
                    const state = this.deserializeState(data);
                    this.states.set(state.instanceId, state);
                }
                catch {
                    // Skip invalid state files
                }
            }
        }
        catch {
            // Directory doesn't exist or can't be read
        }
    }
    /**
     * Serialize state for storage
     */
    serializeState(state) {
        return {
            ...state,
            context: {
                ...state.context,
                stepResults: Array.from(state.context.stepResults.entries()),
            },
            stepExecutions: Array.from(state.stepExecutions.entries()),
            createdAt: state.createdAt.toISOString(),
            startedAt: state.startedAt?.toISOString(),
            completedAt: state.completedAt?.toISOString(),
            pausedAt: state.pausedAt?.toISOString(),
        };
    }
    /**
     * Deserialize state from storage
     */
    deserializeState(data) {
        const contextData = data.context;
        return {
            ...data,
            context: {
                ...contextData,
                stepResults: new Map(contextData.stepResults),
            },
            stepExecutions: new Map(data.stepExecutions),
            createdAt: new Date(data.createdAt),
            startedAt: data.startedAt ? new Date(data.startedAt) : undefined,
            completedAt: data.completedAt ? new Date(data.completedAt) : undefined,
            pausedAt: data.pausedAt ? new Date(data.pausedAt) : undefined,
        };
    }
    /**
     * Generate unique instance ID
     */
    generateInstanceId() {
        const timestamp = Date.now().toString(36);
        const random = Math.random().toString(36).substring(2, 8);
        return `wf_${timestamp}_${random}`;
    }
    /**
     * Create a new workflow state
     */
    createState(workflowId, initialContext = {}) {
        const instanceId = this.generateInstanceId();
        const state = {
            instanceId,
            workflowId,
            status: 'pending',
            context: {
                workflowId,
                instanceId,
                variables: { ...initialContext },
                stepResults: new Map(),
                metadata: {},
            },
            stepExecutions: new Map(),
            currentStepIndex: 0,
            createdAt: new Date(),
        };
        this.states.set(instanceId, state);
        this.saveState(state);
        return state;
    }
    /**
     * Get a workflow state by instance ID
     */
    getState(instanceId) {
        return this.states.get(instanceId);
    }
    /**
     * Update a workflow state
     */
    updateState(instanceId, updates) {
        const state = this.states.get(instanceId);
        if (!state)
            return undefined;
        Object.assign(state, updates);
        this.saveState(state);
        return state;
    }
    /**
     * Save state to disk
     */
    saveState(state) {
        const statePath = path.join(this.statesDir, `${state.instanceId}.json`);
        fs.writeFileSync(statePath, JSON.stringify(this.serializeState(state), null, 2));
    }
    /**
     * Delete a workflow state
     */
    deleteState(instanceId) {
        const existed = this.states.delete(instanceId);
        if (existed) {
            const statePath = path.join(this.statesDir, `${instanceId}.json`);
            if (fs.existsSync(statePath)) {
                fs.unlinkSync(statePath);
            }
        }
        return existed;
    }
    /**
     * Get all states
     */
    getAllStates() {
        return Array.from(this.states.values());
    }
    /**
     * Get states by workflow ID
     */
    getStatesByWorkflow(workflowId) {
        return Array.from(this.states.values()).filter(s => s.workflowId === workflowId);
    }
    /**
     * Get states by status
     */
    getStatesByStatus(status) {
        return Array.from(this.states.values()).filter(s => s.status === status);
    }
    /**
     * Clear completed states
     */
    clearCompleted() {
        const completed = this.getStatesByStatus('completed');
        const failed = this.getStatesByStatus('failed');
        const cancelled = this.getStatesByStatus('cancelled');
        const toDelete = [...completed, ...failed, ...cancelled];
        for (const state of toDelete) {
            this.deleteState(state.instanceId);
        }
        return toDelete.length;
    }
    /**
     * Get statistics
     */
    getStats() {
        const states = this.getAllStates();
        return {
            total: states.length,
            pending: states.filter(s => s.status === 'pending').length,
            running: states.filter(s => s.status === 'running').length,
            paused: states.filter(s => s.status === 'paused').length,
            completed: states.filter(s => s.status === 'completed').length,
            failed: states.filter(s => s.status === 'failed').length,
            cancelled: states.filter(s => s.status === 'cancelled').length,
        };
    }
}
//# sourceMappingURL=state-manager.js.map