/**
 * Cron Builder
 *
 * Converts CronSchedulerState to Unix 5-field cron expression
 * Format: minute hour day-of-month month day-of-week
 */

import type { CronSchedulerState } from '../types';

/**
 * Builds Unix 5-field cron expression from state
 *
 * @example
 * // Daily at 9:00
 * buildCron({ type: 'daily', hour: 9, minute: 0, ... }) // '0 9 * * *'
 *
 * // Weekly on Mon, Wed, Fri at 14:30
 * buildCron({ type: 'weekly', hour: 14, minute: 30, weekDays: [1, 3, 5], ... }) // '30 14 * * 1,3,5'
 *
 * // Monthly on 1st and 15th at 0:00
 * buildCron({ type: 'monthly', hour: 0, minute: 0, monthDays: [1, 15], ... }) // '0 0 1,15 * *'
 */
export function buildCron(state: CronSchedulerState): string {
  // Guard against invalid state
  if (!state || typeof state !== 'object') {
    return '0 0 * * *';
  }

  const { type, hour = 0, minute = 0, weekDays = [], monthDays = [], customCron = '' } = state;

  // Ensure valid hour/minute
  const h = Math.max(0, Math.min(23, Number(hour) || 0));
  const m = Math.max(0, Math.min(59, Number(minute) || 0));

  // Ensure arrays
  const safeWeekDays = Array.isArray(weekDays) ? weekDays : [];
  const safeMonthDays = Array.isArray(monthDays) ? monthDays : [];

  switch (type) {
    case 'daily':
      // Run every day at specified time
      return `${m} ${h} * * *`;

    case 'weekly': {
      // Run on specified days of week at specified time
      const sortedDays = [...safeWeekDays].sort((a, b) => a - b);
      const daysStr = sortedDays.length > 0 ? formatNumberList(sortedDays) : '*';
      return `${m} ${h} * * ${daysStr}`;
    }

    case 'monthly': {
      // Run on specified days of month at specified time
      const sortedDays = [...safeMonthDays].sort((a, b) => a - b);
      const daysStr = sortedDays.length > 0 ? formatNumberList(sortedDays) : '1';
      return `${m} ${h} ${daysStr} * *`;
    }

    case 'custom':
      // Return user-provided expression
      return (customCron || '').trim() || '* * * * *';

    default:
      return '0 0 * * *';
  }
}

/**
 * Formats a list of numbers as ranges where possible
 * [1,2,3,5,7,8,9] -> "1-3,5,7-9"
 */
function formatNumberList(nums: number[]): string {
  if (nums.length === 0) return '';
  if (nums.length === 1) return nums[0].toString();

  const sorted = [...nums].sort((a, b) => a - b);
  const ranges: string[] = [];
  let start = sorted[0];
  let end = sorted[0];

  for (let i = 1; i < sorted.length; i++) {
    if (sorted[i] === end + 1) {
      // Continue the range
      end = sorted[i];
    } else {
      // End current range, start new one
      ranges.push(start === end ? `${start}` : `${start}-${end}`);
      start = sorted[i];
      end = sorted[i];
    }
  }

  // Don't forget the last range
  ranges.push(start === end ? `${start}` : `${start}-${end}`);

  return ranges.join(',');
}

/**
 * Builds cron for a specific schedule type with defaults
 */
export function buildDefaultCron(type: CronSchedulerState['type']): string {
  const defaults: Record<typeof type, string> = {
    daily: '0 9 * * *',      // Every day at 9:00
    weekly: '0 9 * * 1-5',   // Weekdays at 9:00
    monthly: '0 9 1 * *',    // 1st of month at 9:00
    custom: '* * * * *',     // Every minute
  };
  return defaults[type];
}
