/**
 * V2 Trigger Type Definitions
 *
 * Triggers unify v1's ScheduledMessage, CronTask, and EventSubscription
 * into a single time/signal/compound mechanism that creates or wakes WorkItems.
 *
 * @module types/v2/trigger.types
 */
import { v4 as uuidv4 } from 'uuid';
/** All valid TriggerType values. */
export const TRIGGER_TYPES = ['time', 'signal', 'compound'];
/** All valid TriggerStatus values. */
export const TRIGGER_STATUSES = [
    'active',
    'paused',
    'exhausted',
    'cancelled',
];
// ---------------------------------------------------------------------------
// Constants
// ---------------------------------------------------------------------------
/** Default max idle fires before auto-cancel. From v1 issue #131 lesson. */
export const DEFAULT_MAX_IDLE_FIRES = 3;
// ---------------------------------------------------------------------------
// Type Guards
// ---------------------------------------------------------------------------
/**
 * Checks whether a string is a valid TriggerType.
 *
 * @param value - The string to check
 * @returns True if value is a valid TriggerType
 */
export function isValidTriggerType(value) {
    return TRIGGER_TYPES.includes(value);
}
/**
 * Checks whether a string is a valid TriggerStatus.
 *
 * @param value - The string to check
 * @returns True if value is a valid TriggerStatus
 */
export function isValidTriggerStatus(value) {
    return TRIGGER_STATUSES.includes(value);
}
/**
 * Validates that a trigger config's type field matches its parent type.
 *
 * @param config - The config to validate
 * @returns True if the config is internally consistent
 */
export function isValidTriggerConfig(config) {
    if (!config || typeof config !== 'object')
        return false;
    switch (config.type) {
        case 'time':
            return !!(config.cronExpression || config.delayMs || config.fireAt);
        case 'signal':
            return typeof config.eventType === 'string' && config.eventType.length > 0;
        case 'compound':
            return ((config.operator === 'and' || config.operator === 'or') &&
                Array.isArray(config.conditions) &&
                config.conditions.length > 0);
        default:
            return false;
    }
}
/**
 * Validates that an unknown value is structurally a valid Trigger.
 *
 * @param value - Unknown value to validate
 * @returns True if value conforms to the Trigger interface
 */
export function isTrigger(value) {
    if (typeof value !== 'object' || value === null)
        return false;
    const obj = value;
    return (typeof obj.id === 'string' &&
        typeof obj.type === 'string' &&
        isValidTriggerType(obj.type) &&
        typeof obj.status === 'string' &&
        isValidTriggerStatus(obj.status) &&
        typeof obj.createdAt === 'string' &&
        typeof obj.fireCount === 'number' &&
        typeof obj.maxIdleFires === 'number');
}
/**
 * Checks whether a TriggerAction has at least one action defined.
 *
 * @param action - The action to validate
 * @returns True if at least one action field is set
 */
export function isValidTriggerAction(action) {
    if (!action || typeof action !== 'object')
        return false;
    return !!(action.createWorkItem ||
        action.wakeWorkItemId ||
        action.sendMessage ||
        action.runReconciler);
}
// ---------------------------------------------------------------------------
// Validation
// ---------------------------------------------------------------------------
/**
 * Validates CreateTriggerInput and returns an array of error messages.
 *
 * @param input - The creation input to validate
 * @returns Array of validation error strings (empty = valid)
 */
export function validateCreateTriggerInput(input) {
    const errors = [];
    if (!input.type || !isValidTriggerType(input.type)) {
        errors.push(`type must be one of: ${TRIGGER_TYPES.join(', ')}`);
    }
    if (!input.config) {
        errors.push('config is required');
    }
    else if (!isValidTriggerConfig(input.config)) {
        errors.push('config is invalid for the given trigger type');
    }
    if (!input.action) {
        errors.push('action is required');
    }
    else if (!isValidTriggerAction(input.action)) {
        errors.push('action must have at least one action field set');
    }
    if (!input.createdBy) {
        errors.push('createdBy is required');
    }
    if (input.maxFires !== undefined && (input.maxFires < 1 || !Number.isInteger(input.maxFires))) {
        errors.push('maxFires must be a positive integer');
    }
    if (input.maxIdleFires !== undefined && (input.maxIdleFires < 1 || !Number.isInteger(input.maxIdleFires))) {
        errors.push('maxIdleFires must be a positive integer');
    }
    return errors;
}
// ---------------------------------------------------------------------------
// Factory
// ---------------------------------------------------------------------------
/**
 * Creates a new Trigger with sensible defaults.
 *
 * @param input - Required and optional creation fields
 * @returns A fully populated Trigger object
 *
 * @example
 * ```typescript
 * const trigger = createTrigger({
 *   type: 'time',
 *   config: { type: 'time', cronExpression: '0 9 * * 1' },
 *   action: { runReconciler: true },
 *   createdBy: 'system',
 * });
 * ```
 */
export function createTrigger(input) {
    const now = new Date().toISOString();
    return {
        id: uuidv4(),
        type: input.type,
        config: input.config,
        action: input.action,
        status: 'active',
        createdBy: input.createdBy,
        createdAt: now,
        fireCount: 0,
        maxFires: input.maxFires,
        maxIdleFires: input.maxIdleFires ?? DEFAULT_MAX_IDLE_FIRES,
        consecutiveIdleFires: 0,
        teamId: input.teamId,
        name: input.name,
    };
}
//# sourceMappingURL=trigger.types.js.map