/**
 * Loop State Manager
 * CCW Loop System - JSON state persistence layer
 * Reference: .workflow/.scratchpad/loop-system-complete-design-20260121.md section 4.1
 */
import { readFile, writeFile, unlink, mkdir, copyFile } from 'fs/promises';
import { join } from 'path';
import { existsSync } from 'fs';
export class LoopStateManager {
    baseDir;
    constructor(workflowDir) {
        // State files stored in .workflow/.loop/
        this.baseDir = join(workflowDir, '.workflow', '.loop');
    }
    /**
     * Create new loop state
     */
    async createState(loopId, taskId, config) {
        await this.ensureDir();
        const state = {
            loop_id: loopId,
            task_id: taskId,
            status: 'created',
            current_iteration: 1,
            max_iterations: config.max_iterations,
            current_cli_step: 0,
            cli_sequence: config.cli_sequence,
            session_mapping: {},
            state_variables: {},
            success_condition: config.success_condition,
            error_policy: {
                on_failure: config.error_policy.on_failure,
                retry_count: 0,
                max_retries: config.error_policy.max_retries || 3
            },
            created_at: new Date().toISOString(),
            updated_at: new Date().toISOString(),
            execution_history: []
        };
        await this.writeState(loopId, state);
        return state;
    }
    /**
     * Read loop state
     */
    async readState(loopId) {
        const filePath = this.getStateFilePath(loopId);
        if (!existsSync(filePath)) {
            throw new Error(`Loop state not found: ${loopId}`);
        }
        const content = await readFile(filePath, 'utf-8');
        return JSON.parse(content);
    }
    /**
     * Update loop state
     */
    async updateState(loopId, updates) {
        const currentState = await this.readState(loopId);
        const newState = {
            ...currentState,
            ...updates,
            updated_at: new Date().toISOString()
        };
        await this.writeState(loopId, newState);
        return newState;
    }
    /**
     * Delete loop state
     */
    async deleteState(loopId) {
        const filePath = this.getStateFilePath(loopId);
        if (existsSync(filePath)) {
            await unlink(filePath);
        }
    }
    /**
     * List all loop states
     */
    async listStates() {
        if (!existsSync(this.baseDir)) {
            return [];
        }
        const { readdir } = await import('fs/promises');
        const files = await readdir(this.baseDir);
        const stateFiles = files.filter(f => f.startsWith('loop-') && f.endsWith('.json'));
        const states = [];
        for (const file of stateFiles) {
            const loopId = file.replace('.json', '');
            try {
                const state = await this.readState(loopId);
                states.push(state);
            }
            catch (err) {
                console.error(`Failed to read state ${loopId}:`, err);
            }
        }
        return states;
    }
    /**
     * Read state with recovery from backup
     */
    async readStateWithRecovery(loopId) {
        try {
            return await this.readState(loopId);
        }
        catch (error) {
            console.warn(`State file corrupted, attempting recovery for ${loopId}...`);
            // Try reading from backup
            const backupFile = `${this.getStateFilePath(loopId)}.backup`;
            if (existsSync(backupFile)) {
                const content = await readFile(backupFile, 'utf-8');
                const state = JSON.parse(content);
                // Restore from backup
                await this.writeState(loopId, state);
                return state;
            }
            throw error;
        }
    }
    /**
     * Get state file path
     */
    getStateFilePath(loopId) {
        return join(this.baseDir, `${loopId}.json`);
    }
    /**
     * Ensure directory exists
     */
    async ensureDir() {
        if (!existsSync(this.baseDir)) {
            await mkdir(this.baseDir, { recursive: true });
        }
    }
    /**
     * Write state file with automatic backup
     */
    async writeState(loopId, state) {
        const filePath = this.getStateFilePath(loopId);
        // Create backup if file exists
        if (existsSync(filePath)) {
            const backupPath = `${filePath}.backup`;
            await copyFile(filePath, backupPath).catch(() => {
                // Ignore backup errors
            });
        }
        await writeFile(filePath, JSON.stringify(state, null, 2), 'utf-8');
    }
}
//# sourceMappingURL=loop-state-manager.js.map