import { queryWithRLS, mutateWithRLS } from "../db";
import { APP_CONFIG_MERGED } from "../config";
import { getActionHandler } from "./registry";
import { scheduleAction } from "./scheduler";
const DEFAULT_BATCH_SIZE = 10;
const DEFAULT_TIMEOUT = 3e4;
async function processPendingActions(batchSize) {
  var _a;
  const effectiveBatchSize = batchSize ?? ((_a = APP_CONFIG_MERGED.scheduledActions) == null ? void 0 : _a.batchSize) ?? DEFAULT_BATCH_SIZE;
  const result = {
    processed: 0,
    succeeded: 0,
    failed: 0,
    errors: []
  };
  try {
    const actions = await queryWithRLS(
      `SELECT * FROM "scheduled_actions"
       WHERE status = 'pending'
         AND "scheduledAt" <= NOW()
       ORDER BY "scheduledAt" ASC
       LIMIT $1`,
      [effectiveBatchSize],
      null
      // System operation
    );
    console.log(`[ScheduledActions] Found ${actions.length} pending action(s) to process`);
    for (const action of actions) {
      result.processed++;
      try {
        await executeAction(action);
        result.succeeded++;
      } catch (error) {
        result.failed++;
        result.errors.push({
          actionId: action.id,
          error: error instanceof Error ? error.message : "Unknown error"
        });
      }
    }
    console.log(`[ScheduledActions] Processing complete: ${result.succeeded} succeeded, ${result.failed} failed`);
  } catch (error) {
    console.error("[ScheduledActions] Error fetching pending actions:", error);
    throw error;
  }
  return result;
}
async function executeAction(action) {
  var _a;
  const startTime = Date.now();
  const configDefaultTimeout = ((_a = APP_CONFIG_MERGED.scheduledActions) == null ? void 0 : _a.defaultTimeout) ?? DEFAULT_TIMEOUT;
  console.log(`[ScheduledActions] Executing action ${action.id} (${action.actionType})`);
  await markActionRunning(action.id);
  try {
    const actionDef = getActionHandler(action.actionType);
    if (!actionDef) {
      throw new Error(`No handler registered for action type: ${action.actionType}`);
    }
    const timeout = actionDef.timeout ?? configDefaultTimeout;
    await executeWithTimeout(
      actionDef.handler(action.payload, action),
      timeout,
      `Action ${action.actionType} exceeded timeout of ${timeout}ms`
    );
    const executionTime = Date.now() - startTime;
    console.log(`[ScheduledActions] Action ${action.id} completed in ${executionTime}ms`);
    await markActionCompleted(action.id);
    if (action.recurringInterval) {
      await rescheduleRecurringAction(action);
    }
  } catch (error) {
    const executionTime = Date.now() - startTime;
    const errorMessage = error instanceof Error ? error.message : "Unknown error";
    console.error(`[ScheduledActions] Action ${action.id} failed after ${executionTime}ms:`, errorMessage);
    await markActionFailed(action.id, errorMessage);
    throw error;
  }
}
async function executeWithTimeout(promise, timeoutMs, timeoutMessage) {
  const timeoutPromise = new Promise((_, reject) => {
    setTimeout(() => reject(new Error(timeoutMessage)), timeoutMs);
  });
  return Promise.race([promise, timeoutPromise]);
}
async function markActionRunning(actionId) {
  await mutateWithRLS(
    `UPDATE "scheduled_actions"
     SET status = 'running',
         "startedAt" = NOW(),
         attempts = attempts + 1,
         "updatedAt" = NOW()
     WHERE id = $1`,
    [actionId],
    null
  );
}
async function markActionCompleted(actionId) {
  await mutateWithRLS(
    `UPDATE "scheduled_actions"
     SET status = 'completed',
         "completedAt" = NOW(),
         "updatedAt" = NOW()
     WHERE id = $1`,
    [actionId],
    null
  );
}
async function markActionFailed(actionId, errorMessage) {
  await mutateWithRLS(
    `UPDATE "scheduled_actions"
     SET status = 'failed',
         "completedAt" = NOW(),
         "errorMessage" = $2,
         "updatedAt" = NOW()
     WHERE id = $1`,
    [actionId, errorMessage],
    null
  );
}
async function rescheduleRecurringAction(action) {
  if (!action.recurringInterval) {
    return;
  }
  const nextScheduledAt = calculateNextScheduledTime(action.recurringInterval);
  await scheduleAction(
    action.actionType,
    action.payload,
    {
      scheduledAt: nextScheduledAt,
      teamId: action.teamId ?? void 0,
      recurringInterval: action.recurringInterval ?? void 0
    }
  );
  console.log(`[ScheduledActions] Rescheduled recurring action ${action.actionType} for ${nextScheduledAt.toISOString()}`);
}
function calculateNextScheduledTime(interval) {
  const now = /* @__PURE__ */ new Date();
  switch (interval) {
    case "hourly":
      return new Date(now.getTime() + 60 * 60 * 1e3);
    case "daily":
      return new Date(now.getTime() + 24 * 60 * 60 * 1e3);
    case "weekly":
      return new Date(now.getTime() + 7 * 24 * 60 * 60 * 1e3);
    default:
      console.warn(`[ScheduledActions] Unknown interval '${interval}', defaulting to 1 hour`);
      return new Date(now.getTime() + 60 * 60 * 1e3);
  }
}
export {
  processPendingActions
};
