const mongoose = require('mongoose');
const { computeNextRunAt, validateScheduleExpression } = require('@/services/platform/schedules');
const { queueAgentRun } = require('./runtime');

const listSchedules = async ({ tenantId }) =>
  mongoose
    .model('AgentDefinition')
    .find({ tenant: tenantId, removed: false })
    .select('name status schedule updated')
    .sort({ updated: -1 })
    .lean();

const previewSchedule = ({ agent, expression, timezoneName }) =>
  validateScheduleExpression({
    expression: expression || agent?.schedule?.expression,
    timezoneName: timezoneName || agent?.schedule?.timezone || 'Africa/Lagos',
  });

const dispatchDueAgentSchedules = async ({ now = new Date(), limit = 10 } = {}) => {
  const AgentDefinition = mongoose.model('AgentDefinition');
  const dueAgents = await AgentDefinition.find({
    removed: false,
    status: 'published',
    'schedule.enabled': true,
    'schedule.nextRunAt': { $lte: now },
  })
    .sort({ 'schedule.nextRunAt': 1 })
    .limit(limit);

  const results = [];
  for (const agent of dueAgents) {
    const slot = agent.schedule?.nextRunAt?.toISOString();
    const existing = await mongoose.model('AgentRun').findOne({
      tenant: agent.tenant,
      agent: agent._id,
      removed: false,
      'input.scheduleSlot': slot,
    });
    if (!existing) {
      const run = await queueAgentRun({
        agent,
        actor: agent.createdBy ? { _id: agent.createdBy } : null,
        tenant: agent.tenant,
        input: { objective: agent.description || agent.name, scheduleSlot: slot },
        trigger: 'schedule',
        testMode: false,
      });
      results.push(run);
    }
    agent.schedule.lastScheduledAt = now;
    agent.schedule.nextRunAt = computeNextRunAt({
      expression: agent.schedule.expression,
      timezoneName: agent.schedule.timezone || 'Africa/Lagos',
      from: now,
    });
    await agent.save();
  }
  return results;
};

module.exports = {
  listSchedules,
  previewSchedule,
  dispatchDueAgentSchedules,
};
