// src/server/shared/cron/index.ts
// Cron jobs initialization and management

import cron from 'node-cron';
import { db } from '../db/client';
import { dayjs } from '../lib/dayjs';
import { logger } from '../lib/logger';
import { getAllRoleSessionPolicies } from '@features/system/system.service';
import { USER_ROLES } from '@shared/constants/roles';
import { employees } from '@features/personnel/db/employees.table';
import { eq, and, isNull } from 'drizzle-orm';
import { notifyRoom, getUserRoom } from '../plugins/socket';

const ROLE_ROOMS: Record<string, string> = {
  [USER_ROLES.ADMIN]: 'room:admins',
  [USER_ROLES.MANAGER]: 'room:managers',
};

const processedLogoutMinutes = new Set<string>();

async function initializeLogoutTimeCron(): Promise<void> {
  cron.schedule('* * * * *', async () => {
    try {
      const now = dayjs().tz('Europe/Moscow');
      const currentTime = now.format('HH:mm');
      const dateKey = now.format('YYYY-MM-DD');

      const policies = await getAllRoleSessionPolicies();

      for (const policy of policies) {
        if (!policy.logoutTime) continue;

        const cacheKey = `${policy.role}:${dateKey}:${policy.logoutTime}`;
        if (processedLogoutMinutes.has(cacheKey)) continue;

        if (currentTime >= policy.logoutTime) {
          processedLogoutMinutes.add(cacheKey);
          const reason = `Время сессии для роли ${policy.role} истекло (${policy.logoutTime} МСК)`;

          let userCount = 0;
          const roomId = ROLE_ROOMS[policy.role];
          if (roomId) {
            await notifyRoom(roomId, 'session:kill' as any, { reason });
          } else {
            const activeUsers = await db
              .select({ id: employees.id })
              .from(employees)
              .where(and(eq(employees.role, policy.role as any), isNull(employees.archivedAt)));

            for (const user of activeUsers) {
              await notifyRoom(getUserRoom(user.id), 'session:kill' as any, { reason });
            }
            userCount = activeUsers.length;
          }

          logger.info(`[Cron] Logout time triggered for role ${policy.role} at ${policy.logoutTime} MSK (${userCount} users)`);
        }
      }

      if (processedLogoutMinutes.size > 1000) {
        processedLogoutMinutes.clear();
      }
    } catch (error) {
      logger.error('[Cron] Error in logout time cron job:', error);
    }
  }, {
    timezone: 'Europe/Moscow',
  });

  logger.info('[Cron] Logout time cron job scheduled for every minute');
}

function initializeReminderWorkerCron(): void {
  cron.schedule('* * * * *', async () => {
    try {
      const { checkAndTriggerPersonalReminders } = await import('@features/notes/lib/reminder-worker.service');
      await checkAndTriggerPersonalReminders();
    } catch (error) {
      logger.error('[Cron] Error in Personal reminder worker cron job:', error);
    }
  }, {
    timezone: 'Europe/Moscow',
  });

  logger.info('[Cron] Personal reminder worker cron job scheduled for every minute');
}

export function initializeCronJobs(): void {
  logger.info('[Cron] Initializing cron jobs...');

  initializeLogoutTimeCron();
  initializeReminderWorkerCron();

  logger.info('[Cron] All cron jobs initialized successfully');
}
