/**
 * @ai-summary Service for classifying backups into tiered retention categories
 * @ai-context Pure functions for timestamp-based classification, no database dependencies
 */

import { BackupCategory, TIERED_RETENTION } from './backup.types';

/**
 * Classifies a backup by its timestamp into retention categories.
 * A backup can belong to multiple categories simultaneously.
 *
 * Categories:
 * - hourly: All backups
 * - daily: First backup at midnight UTC (hour = 0)
 * - weekly: First backup on Sunday at midnight UTC
 * - monthly: First backup on 1st of month at midnight UTC
 */
export function classifyBackup(timestamp: Date): BackupCategory[] {
  const categories: BackupCategory[] = ['hourly'];

  const utcHour = timestamp.getUTCHours();
  const utcDay = timestamp.getUTCDate();
  const utcDayOfWeek = timestamp.getUTCDay(); // 0 = Sunday

  // Midnight UTC qualifies for daily
  if (utcHour === 0) {
    categories.push('daily');

    // Sunday at midnight qualifies for weekly
    if (utcDayOfWeek === 0) {
      categories.push('weekly');
    }

    // 1st of month at midnight qualifies for monthly
    if (utcDay === 1) {
      categories.push('monthly');
    }
  }

  return categories;
}

/**
 * Calculates the expiration date based on the backup's categories.
 * Uses the longest retention period among all applicable categories.
 *
 * Retention periods are count-based in the actual cleanup, but for display
 * we estimate based on typical backup frequency:
 * - hourly: 8 hours (8 backups * 1 hour)
 * - daily: 7 days (7 backups * 1 day)
 * - weekly: 4 weeks (4 backups * 1 week)
 * - monthly: 12 months (12 backups * 1 month)
 */
export function calculateExpiration(
  categories: BackupCategory[],
  timestamp: Date
): Date {
  const expirationDate = new Date(timestamp);

  if (categories.includes('monthly')) {
    expirationDate.setUTCMonth(expirationDate.getUTCMonth() + TIERED_RETENTION.monthly);
  } else if (categories.includes('weekly')) {
    expirationDate.setUTCDate(expirationDate.getUTCDate() + TIERED_RETENTION.weekly * 7);
  } else if (categories.includes('daily')) {
    expirationDate.setUTCDate(expirationDate.getUTCDate() + TIERED_RETENTION.daily);
  } else {
    // Hourly only - 8 hours
    expirationDate.setUTCHours(expirationDate.getUTCHours() + TIERED_RETENTION.hourly);
  }

  return expirationDate;
}

/**
 * Checks if a backup timestamp represents the first backup of the day (midnight UTC).
 */
export function isFirstBackupOfDay(timestamp: Date): boolean {
  return timestamp.getUTCHours() === 0;
}

/**
 * Checks if a timestamp falls on a Sunday.
 */
export function isSunday(timestamp: Date): boolean {
  return timestamp.getUTCDay() === 0;
}

/**
 * Checks if a timestamp falls on the first day of the month.
 */
export function isFirstDayOfMonth(timestamp: Date): boolean {
  return timestamp.getUTCDate() === 1;
}

/**
 * Classifies a backup and calculates its expiration in one call.
 * Convenience function for backup creation flow.
 */
export function classifyAndCalculateExpiration(timestamp: Date): {
  categories: BackupCategory[];
  expiresAt: Date;
} {
  const categories = classifyBackup(timestamp);
  const expiresAt = calculateExpiration(categories, timestamp);
  return { categories, expiresAt };
}
