// src/server/shared/cron.ts
// Cron jobs for scheduled tasks (archiving, cleanup, etc.)

import cron from 'node-cron';
import { db } from './db/client';
import { tasks } from '../features/tasks/db/tasks.table';
import { shiftTasks } from '../features/schedule/db/shift_tasks.table';
import { shifts } from '../features/schedule/db/shifts.table';
import { eq, and, lt, or, isNull, gte, lte, isNotNull } from 'drizzle-orm';
import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc.js';
import timezone from 'dayjs/plugin/timezone.js';
import { logger } from './lib/logger';

// Настройка dayjs с timezone Europe/Moscow
dayjs.extend(utc);
dayjs.extend(timezone);
dayjs.tz.setDefault('Europe/Moscow');

/**
 * Cron 1: Ежедневно в 10:00 (Europe/Moscow) - Архивация Tasks и Shift Tasks
 * - Tasks: archiveAllTasks()
 * - Shift Tasks: archiveAllShiftTasks()
 */
const dailyArchiveCron = cron.schedule('0 10 * * *', async () => {
  try {
    logger.info('[Cron] Starting daily archive at 10:00 MSK');

    // Архивация задач
    await archiveAllTasks();

    // Архивация задач смен
    await archiveAllShiftTasks();

    logger.info('[Cron] Daily archive completed successfully');
  } catch (error) {
    logger.error('[Cron] Daily archive failed', { error });
  }
}, {
  timezone: 'Europe/Moscow',
});

/**
 * Cron 2: Еженедельно (воскресенье, 03:00) - Cleanup
 * - Очистка старых записей (>90 дней)
 * - Оптимизация БД
 */
const weeklyCleanupCron = cron.schedule('0 3 * * 0', async () => {
  try {
    logger.info('[Cron] Starting weekly cleanup at 03:00 MSK (Sunday)');

    // Очистка старых архивированных записей (>90 дней)
    await cleanupOldArchivedRecords();

    // Оптимизация БД
    await optimizeDatabase();

    logger.info('[Cron] Weekly cleanup completed successfully');
  } catch (error) {
    logger.error('[Cron] Weekly cleanup failed', { error });
  }
}, {
  timezone: 'Europe/Moscow',
});

/**
 * Архивация всех активных задач
 */
async function archiveAllTasks() {
  await db.update(tasks)
    .set({ archivedAt: new Date() })
    .where(isNull(tasks.archivedAt));

  logger.info('[Cron] All tasks archived');
}

/**
 * Архивация всех активных задач смен
 */
async function archiveAllShiftTasks() {
  await db.update(shiftTasks)
    .set({ archivedAt: new Date() })
    .where(isNull(shiftTasks.archivedAt));

  logger.info('[Cron] All shift tasks archived');
}

/**
 * Очистка старых архивированных записей (>90 дней)
 */
async function cleanupOldArchivedRecords() {
  const ninetyDaysAgo = dayjs().tz('Europe/Moscow').subtract(90, 'days').toDate();
  const ninetyDaysAgoStr = dayjs().tz('Europe/Moscow').subtract(90, 'days').format('YYYY-MM-DD');

  // Удаление старых задач
  await db.delete(tasks)
    .where(
      and(
        isNotNull(tasks.archivedAt),
        lt(tasks.archivedAt, ninetyDaysAgo)
      )
    );

  // Удаление старых задач смен
  await db.delete(shiftTasks)
    .where(
      and(
        isNotNull(shiftTasks.archivedAt),
        lt(shiftTasks.archivedAt, ninetyDaysAgo)
      )
    );

  logger.info('[Cron] Old archived records (>90 days) deleted');
}

/**
 * Оптимизация БД
 */
async function optimizeDatabase() {
  try {
    // Для MySQL: OPTIMIZE TABLE
    const tables = ['tasks', 'shift_tasks', 'checkins', 'shifts', 'notes', 'users'];

    for (const table of tables) {
      await db.execute(`OPTIMIZE TABLE ${table}`);
    }

    logger.info('[Cron] Database optimization completed');
  } catch (error) {
    logger.error('[Cron] Database optimization failed', { error });
  }
}

// Экспорт функций для использования в других модулях
export {
  archiveAllTasks,
  archiveAllShiftTasks,
  cleanupOldArchivedRecords,
  optimizeDatabase,
};

// Запуск Cron задач при импорте модуля
logger.info('[Cron] All cron jobs scheduled');
