/**
 * Workflow Rule Evaluator
 *
 * Subscribes to ticket:status_changed events on the global EventBus and
 * evaluates workflow rules when a ticket enters a new state.
 *
 * For on_enter rules, emits a work:rule_matched event so that
 * downstream systems (orchestrators, hooks) can fire the associated action.
 * For manual rules, the match is logged but no action is auto-fired.
 */
import { getEventBus } from '../events/event-bus.js';
import { PMO_TABLES } from '../pmo/schema.js';
export class WorkflowRuleEvaluator {
    unsubscribers = [];
    db;
    constructor(db) {
        this.db = db;
    }
    /**
     * Start listening for ticket state changes.
     */
    start() {
        const bus = getEventBus();
        this.unsubscribers.push(bus.on('ticket:status_changed', (event) => {
            this.evaluate(event);
        }));
    }
    /**
     * Stop listening for events.
     */
    stop() {
        for (const unsub of this.unsubscribers) {
            unsub();
        }
        this.unsubscribers = [];
    }
    /**
     * Evaluate workflow rules for a status change event.
     * Finds all enabled rules matching the new state and emits events for on_enter rules.
     */
    evaluate(event) {
        if (!event.newStatusName)
            return;
        try {
            // Find all enabled rules where to_state matches the new status
            const rows = this.db.prepare(`
        SELECT * FROM ${PMO_TABLES.workflow_rules}
        WHERE to_state = ? AND enabled = 1
      `).all(event.newStatusName);
            if (rows.length === 0)
                return;
            const bus = getEventBus();
            for (const row of rows) {
                // If from_state is set, it must match the previous status
                if (row.from_state && row.from_state !== event.previousStatusName) {
                    continue;
                }
                // Emit rule_matched event for on_enter triggers
                if (row.trigger === 'on_enter') {
                    bus.emit('workflow_rule:matched', {
                        ruleId: row.id,
                        ticketId: event.ticketId,
                        projectId: event.projectId,
                        actionId: row.action_id,
                        trigger: row.trigger,
                        fromState: row.from_state,
                        toState: row.to_state,
                        timestamp: new Date(),
                    });
                }
            }
        }
        catch {
            // Rule evaluation errors are non-fatal
        }
    }
}
// =============================================================================
// Singleton
// =============================================================================
let _evaluator;
/**
 * Initialize and start the workflow rule evaluator.
 * Safe to call multiple times — subsequent calls are no-ops.
 */
export function initWorkflowRuleEvaluator(db) {
    if (!_evaluator) {
        _evaluator = new WorkflowRuleEvaluator(db);
        _evaluator.start();
    }
    return _evaluator;
}
/**
 * Stop the workflow rule evaluator (primarily for testing).
 */
export function stopWorkflowRuleEvaluator() {
    if (_evaluator) {
        _evaluator.stop();
        _evaluator = undefined;
    }
}
//# sourceMappingURL=rule-evaluator.js.map