// SPEC-094 AC-2 + AC-10: Transaction with auto-rollback and error classification
import { randomUUID } from 'node:crypto';
export class SafetyTransactionError extends Error {
    code;
    severity;
    recovery;
    rollbackEvent;
    constructor(message, code, severity, recovery, rollbackEvent) {
        super(message);
        this.name = 'SafetyTransactionError';
        this.code = code;
        this.severity = severity;
        this.recovery = recovery;
        this.rollbackEvent = rollbackEvent;
    }
}
function createRollbackEvent(transactionId, failedStep, stepsRolledBack, error) {
    const event = {
        transactionId,
        failedStep,
        stepsRolledBack,
        error,
        timestamp: new Date().toISOString(),
    };
    console.warn('[Transaction] Rollback event:', JSON.stringify(event));
    return event;
}
export class Transaction {
    id;
    steps = [];
    completedSteps = [];
    constructor() {
        this.id = randomUUID();
    }
    addStep(step) {
        this.steps.push(step);
    }
    async commit() {
        for (const step of this.steps) {
            try {
                await step.doFn();
                this.completedSteps.push(step.name);
            }
            catch (err) {
                const errorMessage = err instanceof Error ? err.message : String(err);
                await this.rollback();
                const rollbackEvent = createRollbackEvent(this.id, step.name, [...this.completedSteps], errorMessage);
                throw new SafetyTransactionError(`Transaction failed at step "${step.name}": ${errorMessage}`, 'ROLLBACK_TRIGGERED', 'critical', `Review the failed step "${step.name}" and retry the operation. ` +
                    `${this.completedSteps.length} step(s) were rolled back.`, rollbackEvent);
            }
        }
    }
    async rollback() {
        const stepsToUndo = [...this.completedSteps].reverse();
        for (const stepName of stepsToUndo) {
            const step = this.steps.find((s) => s.name === stepName);
            if (!step) {
                continue;
            }
            try {
                await step.undoFn();
            }
            catch (undoErr) {
                const msg = undoErr instanceof Error ? undoErr.message : String(undoErr);
                console.warn(`[Transaction] Undo failed for step "${stepName}": ${msg}`);
            }
        }
    }
}
//# sourceMappingURL=transaction.js.map