import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import { builtInWorkflows } from '../../../modules/orchestration/workflows/built-in-workflows.js';
const TERMINAL_RUN_STATES = new Set(['completed', 'failed', 'canceled']);
const TERMINAL_NODE_STATES = new Set(['completed', 'failed', 'canceled', 'skipped']);
export class WorkflowStore {
    filePath = process.env.WORKFLOW_RUNS_PATH ??
        path.join(os.homedir(), '.pixcode', 'workflow-runs.json');
    tmpPath = `${this.filePath}.tmp`;
    runs = new Map();
    constructor() {
        this.load();
    }
    listWorkflows() {
        return builtInWorkflows;
    }
    getWorkflow(id) {
        return builtInWorkflows.find((workflow) => workflow.id === id);
    }
    listRuns() {
        return [...this.runs.values()].sort((a, b) => b.startedAt - a.startedAt);
    }
    getRun(id) {
        return this.runs.get(id);
    }
    setRun(run) {
        this.runs.set(run.id, run);
        this.flush();
    }
    load() {
        fs.mkdirSync(path.dirname(this.filePath), { recursive: true });
        if (!fs.existsSync(this.filePath)) {
            this.flush();
            return;
        }
        let repaired = false;
        try {
            const parsed = JSON.parse(fs.readFileSync(this.filePath, 'utf8'));
            for (const run of Array.isArray(parsed.runs) ? parsed.runs : []) {
                if (run && typeof run.id === 'string') {
                    if (!TERMINAL_RUN_STATES.has(run.status)) {
                        run.status = 'failed';
                        run.finishedAt = run.finishedAt ?? Date.now();
                        run.metadata = {
                            ...run.metadata,
                            error: 'Pixcode restarted before this workflow run reached a terminal state.',
                        };
                        for (const node of run.nodeRuns ?? []) {
                            if (!TERMINAL_NODE_STATES.has(node.status)) {
                                node.status = 'failed';
                                node.finishedAt = node.finishedAt ?? run.finishedAt;
                                node.error = node.error ?? 'Workflow runner stopped before this node reached a terminal state.';
                            }
                        }
                        repaired = true;
                    }
                    this.runs.set(run.id, run);
                }
            }
        }
        catch {
            this.flush();
            return;
        }
        if (repaired) {
            this.flush();
        }
    }
    flush() {
        fs.writeFileSync(this.tmpPath, JSON.stringify({ version: 1, runs: [...this.runs.values()] }, null, 2), 'utf8');
        fs.renameSync(this.tmpPath, this.filePath);
    }
}
export const workflowStore = new WorkflowStore();
//# sourceMappingURL=workflow-store.js.map