/**
 * Scheduled Job Types
 *
 * Defines the types for scheduled jobs in the sync orchestration system.
 *
 * @module core/scheduler/scheduled-job
 */
/**
 * Create a new scheduled job from config
 *
 * @param config - Job configuration
 * @returns New scheduled job
 */
export function createScheduledJob(config) {
    const now = new Date().toISOString();
    const intervalMs = config.intervalMs;
    const nextRun = new Date(Date.now() + intervalMs).toISOString();
    return {
        id: config.id,
        type: config.type,
        schedule: {
            intervalMs,
            enabled: config.enabled ?? true,
            nextRun,
            retryCount: 0,
            maxRetries: config.maxRetries ?? 3,
        },
        status: 'idle',
        lastStateChange: now,
    };
}
/**
 * Calculate next run time with optional exponential backoff
 *
 * @param job - The job to calculate next run for
 * @param withBackoff - Whether to apply exponential backoff (for retries)
 * @returns ISO timestamp of next run
 */
export function calculateNextRun(job, withBackoff = false) {
    let delayMs = job.schedule.intervalMs;
    if (withBackoff && job.schedule.retryCount > 0) {
        // Exponential backoff: 2^retryCount * base interval, capped at 1 hour
        const backoffMultiplier = Math.pow(2, job.schedule.retryCount);
        delayMs = Math.min(delayMs * backoffMultiplier, 60 * 60 * 1000);
    }
    return new Date(Date.now() + delayMs).toISOString();
}
/**
 * Check if a job is due for execution
 *
 * @param job - The job to check
 * @returns true if job should run now
 */
export function isJobDue(job) {
    // Job must be enabled and idle
    if (!job.schedule.enabled || job.status !== 'idle') {
        return false;
    }
    // If no next run scheduled, it's due
    if (!job.schedule.nextRun) {
        return true;
    }
    // Check if current time is past scheduled time
    const now = Date.now();
    const nextRun = new Date(job.schedule.nextRun).getTime();
    return now >= nextRun;
}
/**
 * Update job state after successful execution
 *
 * @param job - The job to update
 * @returns Updated job
 */
export function markJobComplete(job) {
    const now = new Date().toISOString();
    return {
        ...job,
        status: 'idle',
        schedule: {
            ...job.schedule,
            lastRun: now,
            nextRun: calculateNextRun(job),
            retryCount: 0, // Reset retry count on success
        },
        lastError: undefined,
        lastStateChange: now,
    };
}
/**
 * Update job state after failed execution
 *
 * @param job - The job to update
 * @param error - Error message
 * @returns Updated job
 */
export function markJobFailed(job, error) {
    const now = new Date().toISOString();
    const newRetryCount = job.schedule.retryCount + 1;
    const maxRetriesReached = newRetryCount >= job.schedule.maxRetries;
    const updatedJob = {
        ...job,
        status: maxRetriesReached ? 'failed' : 'idle',
        schedule: {
            ...job.schedule,
            retryCount: newRetryCount,
            nextRun: maxRetriesReached ? undefined : calculateNextRun(job, true),
        },
        lastError: error,
        lastStateChange: now,
    };
    return updatedJob;
}
/**
 * Mark job as running
 *
 * @param job - The job to update
 * @returns Updated job
 */
export function markJobRunning(job) {
    return {
        ...job,
        status: 'running',
        lastStateChange: new Date().toISOString(),
    };
}
/**
 * Pause a job (disable without clearing schedule)
 *
 * @param job - The job to pause
 * @returns Updated job
 */
export function pauseJob(job) {
    return {
        ...job,
        status: 'disabled',
        schedule: {
            ...job.schedule,
            enabled: false,
        },
        lastStateChange: new Date().toISOString(),
    };
}
/**
 * Resume a paused job
 *
 * @param job - The job to resume
 * @returns Updated job
 */
export function resumeJob(job) {
    return {
        ...job,
        status: 'idle',
        schedule: {
            ...job.schedule,
            enabled: true,
            nextRun: calculateNextRun(job),
            retryCount: 0, // Reset retries on resume
        },
        lastError: undefined,
        lastStateChange: new Date().toISOString(),
    };
}
/**
 * Reset a failed job for retry
 *
 * @param job - The job to reset
 * @returns Updated job
 */
export function resetJob(job) {
    return {
        ...job,
        status: 'idle',
        schedule: {
            ...job.schedule,
            retryCount: 0,
            nextRun: calculateNextRun(job),
        },
        lastError: undefined,
        lastStateChange: new Date().toISOString(),
    };
}
//# sourceMappingURL=scheduled-job.js.map