/**
 * scheduler.mjs — Recurring scheduled task support
 *
 * Schedules are stored in config.schedules as:
 * { id, name, skill, interval, lastRun, enabled }
 *
 * interval: 'hourly' | 'daily' | 'weekly' | number (minutes)
 */

import { randomBytes } from 'crypto';
import { getConfig, updateConfig } from './config.mjs';

/**
 * Convert interval string/number to milliseconds.
 * number → number * 60000 (treat as minutes)
 */
export function intervalToMs(interval) {
  if (typeof interval === 'number') return interval * 60000;
  switch (interval) {
    case 'hourly':  return 3_600_000;
    case 'daily':   return 86_400_000;
    case 'weekly':  return 604_800_000;
    default: {
      const n = Number(interval);
      return isFinite(n) && n > 0 ? n * 60000 : 3_600_000;
    }
  }
}

/**
 * Check all enabled schedules and run any that are due.
 *
 * @param {object} config - current config object
 * @param {{ runSkill: (name, args) => Promise<any>, addEvent: fn }} ctx
 */
export async function checkSchedules(config, { runSkill, addEvent }) {
  const schedules = config.schedules;
  if (!Array.isArray(schedules) || schedules.length === 0) return;

  const now = Date.now();
  let changed = false;

  for (const schedule of schedules) {
    if (!schedule.enabled) continue;
    const intervalMs = intervalToMs(schedule.interval);
    const lastRun = schedule.lastRun ? new Date(schedule.lastRun).getTime() : 0;

    if (now - lastRun >= intervalMs) {
      console.log(`[scheduler] Running scheduled task "${schedule.name}" (skill: ${schedule.skill})`);
      addEvent('system', 'scheduler', `Running scheduled task: ${schedule.name}`, {
        scheduleId: schedule.id,
        skill: schedule.skill
      });

      try {
        await runSkill(schedule.skill, { topic: schedule.name, task: schedule.name });
        schedule.lastRun = new Date(now).toISOString();
        changed = true;
        addEvent('system', 'scheduler', `Completed scheduled task: ${schedule.name}`);
      } catch (err) {
        console.error(`[scheduler] Failed to run "${schedule.name}": ${err.message}`);
        addEvent('error', 'scheduler', `Scheduled task "${schedule.name}" failed: ${err.message}`);
      }
    }
  }

  if (changed) {
    // Persist updated lastRun values
    updateConfig({ schedules });
  }
}

/**
 * Create a new schedule entry.
 */
export function createSchedule({ name, skill, interval, enabled = true }) {
  return {
    id: randomBytes(8).toString('hex'),
    name: String(name).trim(),
    skill: String(skill).trim(),
    interval,
    lastRun: null,
    enabled: !!enabled
  };
}

/**
 * Get all schedules from config.
 */
export function getSchedules() {
  return getConfig().schedules || [];
}

/**
 * Add a schedule to config and persist.
 */
export function addSchedule(schedule) {
  const config = getConfig();
  const schedules = [...(config.schedules || []), schedule];
  updateConfig({ schedules });
  return schedule;
}

/**
 * Update a schedule by id.
 */
export function updateSchedule(id, updates) {
  const config = getConfig();
  const schedules = (config.schedules || []).map(s =>
    s.id === id ? { ...s, ...updates, id } : s
  );
  updateConfig({ schedules });
  return schedules.find(s => s.id === id) || null;
}

/**
 * Delete a schedule by id.
 */
export function deleteSchedule(id) {
  const config = getConfig();
  const schedules = (config.schedules || []).filter(s => s.id !== id);
  updateConfig({ schedules });
}
