/**
 * Workflow rule operations.
 */
import { PMO_TABLES } from '../schema.js';
import { PMOError } from '../types.js';
import { slugify } from '../utils.js';
const T = PMO_TABLES;
export class WorkflowRuleStorage {
    ctx;
    constructor(ctx) {
        this.ctx = ctx;
    }
    /**
     * List workflow rules.
     */
    async listWorkflowRules(filter) {
        let sql = `SELECT * FROM ${T.workflow_rules}`;
        const conditions = [];
        const params = [];
        if (filter?.toState) {
            conditions.push('to_state = ?');
            params.push(filter.toState);
        }
        if (filter?.fromState) {
            conditions.push('(from_state = ? OR from_state IS NULL)');
            params.push(filter.fromState);
        }
        if (filter?.actionId) {
            conditions.push('action_id = ?');
            params.push(filter.actionId);
        }
        if (filter?.trigger) {
            conditions.push('trigger = ?');
            params.push(filter.trigger);
        }
        if (filter?.enabled !== undefined) {
            conditions.push('enabled = ?');
            params.push(filter.enabled ? 1 : 0);
        }
        if (conditions.length > 0) {
            sql += ` WHERE ${conditions.join(' AND ')}`;
        }
        sql += ' ORDER BY to_state ASC, from_state ASC';
        const rows = this.ctx.db.prepare(sql).all(...params);
        return rows.map((row) => this.rowToRule(row));
    }
    /**
     * Get a workflow rule by ID.
     */
    async getWorkflowRule(id) {
        const row = this.ctx.db.prepare(`SELECT * FROM ${T.workflow_rules} WHERE id = ?`).get(id);
        if (!row)
            return null;
        return this.rowToRule(row);
    }
    /**
     * Create a new workflow rule.
     */
    async createWorkflowRule(rule) {
        if (!rule.toState) {
            throw new PMOError('INVALID', 'to_state is required');
        }
        if (!rule.actionId) {
            throw new PMOError('INVALID', 'action_id is required');
        }
        // Verify action exists
        const actionExists = this.ctx.db.prepare(`
      SELECT id FROM ${T.actions} WHERE id = ?
    `).get(rule.actionId);
        if (!actionExists) {
            throw new PMOError('NOT_FOUND', `Action not found: ${rule.actionId}`);
        }
        const id = rule.id || slugify(`${rule.fromState || 'any'}-to-${rule.toState}-${rule.actionId}`);
        // Check for duplicate
        const existing = this.ctx.db.prepare(`
      SELECT id FROM ${T.workflow_rules} WHERE id = ?
    `).get(id);
        if (existing) {
            throw new PMOError('CONFLICT', `Workflow rule with id "${id}" already exists`);
        }
        const now = new Date().toISOString();
        const trigger = rule.trigger || 'manual';
        const enabled = rule.enabled !== false;
        this.ctx.db.prepare(`
      INSERT INTO ${T.workflow_rules} (id, from_state, to_state, action_id, trigger, enabled, created_at, updated_at)
      VALUES (?, ?, ?, ?, ?, ?, ?, ?)
    `).run(id, rule.fromState || null, rule.toState, rule.actionId, trigger, enabled ? 1 : 0, now, now);
        return {
            id,
            fromState: rule.fromState,
            toState: rule.toState,
            actionId: rule.actionId,
            trigger,
            enabled,
            createdAt: new Date(now),
            updatedAt: new Date(now),
        };
    }
    /**
     * Update a workflow rule.
     */
    async updateWorkflowRule(id, changes) {
        const existing = await this.getWorkflowRule(id);
        if (!existing) {
            throw new PMOError('NOT_FOUND', `Workflow rule not found: ${id}`);
        }
        // If changing action_id, verify new action exists
        if (changes.actionId) {
            const actionExists = this.ctx.db.prepare(`
        SELECT id FROM ${T.actions} WHERE id = ?
      `).get(changes.actionId);
            if (!actionExists) {
                throw new PMOError('NOT_FOUND', `Action not found: ${changes.actionId}`);
            }
        }
        const updates = [];
        const params = [];
        if (changes.fromState !== undefined) {
            updates.push('from_state = ?');
            params.push(changes.fromState || null);
        }
        if (changes.toState !== undefined) {
            updates.push('to_state = ?');
            params.push(changes.toState);
        }
        if (changes.actionId !== undefined) {
            updates.push('action_id = ?');
            params.push(changes.actionId);
        }
        if (changes.trigger !== undefined) {
            updates.push('trigger = ?');
            params.push(changes.trigger);
        }
        if (changes.enabled !== undefined) {
            updates.push('enabled = ?');
            params.push(changes.enabled ? 1 : 0);
        }
        if (updates.length > 0) {
            updates.push('updated_at = ?');
            params.push(new Date().toISOString());
            params.push(id);
            this.ctx.db.prepare(`UPDATE ${T.workflow_rules} SET ${updates.join(', ')} WHERE id = ?`).run(...params);
        }
        return (await this.getWorkflowRule(id));
    }
    /**
     * Delete a workflow rule.
     */
    async deleteWorkflowRule(id) {
        const existing = await this.getWorkflowRule(id);
        if (!existing) {
            throw new PMOError('NOT_FOUND', `Workflow rule not found: ${id}`);
        }
        this.ctx.db.prepare(`DELETE FROM ${T.workflow_rules} WHERE id = ?`).run(id);
    }
    /**
     * Get all enabled workflow rules that match a target state.
     * Used when a ticket transitions to a new state.
     */
    async getWorkflowRulesForState(toState) {
        const rows = this.ctx.db.prepare(`
      SELECT * FROM ${T.workflow_rules}
      WHERE to_state = ? AND enabled = 1
      ORDER BY
        CASE WHEN from_state IS NOT NULL THEN 0 ELSE 1 END,
        from_state ASC
    `).all(toState);
        return rows.map((row) => this.rowToRule(row));
    }
    rowToRule(row) {
        return {
            id: row.id,
            fromState: row.from_state || undefined,
            toState: row.to_state,
            actionId: row.action_id,
            trigger: row.trigger,
            enabled: row.enabled === 1,
            createdAt: new Date(row.created_at),
            updatedAt: row.updated_at ? new Date(row.updated_at) : undefined,
        };
    }
}
//# sourceMappingURL=workflow-rules.js.map