import * as cron from 'node-cron';
import { db } from '@/src/db/db_index'
import { productInfo, productAvailabilitySchedules } from '@/src/db/schema'
import { inArray } from 'drizzle-orm';
import { initializeAllStores } from '../stores/store-initializer';

// Module-level storage for cron jobs
const scheduleJobs: Map<string, cron.ScheduledTask> = new Map();

// Stop all existing schedule-based jobs
const stopAllScheduleJobs = () => {
  for (const [time, job] of scheduleJobs) {
    job.stop();
    console.log(`Stopped cron job for ${time}`);
  }
  scheduleJobs.clear();
};

// Main function to refresh jobs (called on init and after schedule changes)
export const refreshScheduleJobs = async (): Promise<void> => {
  // Stop existing jobs
  stopAllScheduleJobs();
  
  // Fetch all schedules from DB
  const schedules = await db.query.productAvailabilitySchedules.findMany();
  
  if (schedules.length === 0) {
    console.log('No schedules found, no jobs created');
    return;
  }
  
  // Group schedules by time
  const schedulesByTime = new Map<string, typeof schedules>();
  
  for (const schedule of schedules) {
    if (!schedulesByTime.has(schedule.time)) {
      schedulesByTime.set(schedule.time, []);
    }
    schedulesByTime.get(schedule.time)!.push(schedule);
  }
  
  // For each time slot, resolve conflicts and create job
  for (const [time, timeSchedules] of schedulesByTime) {
    // Sort by ID descending (highest ID = latest = wins in conflicts)
    const sortedSchedules = timeSchedules.sort((a, b) => b.id - a.id);
    
    // Build final product states (later schedules override earlier ones)
    const productStates = new Map<number, 'in' | 'out'>();
    
    for (const schedule of sortedSchedules) {
      for (const productId of schedule.productIds) {
        if (!productStates.has(productId)) {
          productStates.set(productId, schedule.action);
        }
      }
    }
    
    // Separate into in-stock and out-of-stock lists
    const toTurnOn: number[] = [];
    const toTurnOff: number[] = [];
    
    for (const [productId, action] of productStates) {
      if (action === 'in') {
        toTurnOn.push(productId);
      } else {
        toTurnOff.push(productId);
      }
    }
    
    // Create cron schedule from time (HH:mm to cron format)
    const [hours, minutes] = time.split(':');
    const cronExpression = `${minutes} ${hours} * * *`;
    
    // Create and store the job
    const job = cron.schedule(cronExpression, async () => {
      console.log(`Running scheduled availability job for ${time}`);
      
      // Batch update in single queries
      if (toTurnOn.length > 0) {
        await db.update(productInfo)
          .set({ isOutOfStock: false })
          .where(inArray(productInfo.id, toTurnOn));
        console.log(`[${time}] Turned ON ${toTurnOn.length} products`);
      }
      
      if (toTurnOff.length > 0) {
        await db.update(productInfo)
          .set({ isOutOfStock: true })
          .where(inArray(productInfo.id, toTurnOff));
        console.log(`[${time}] Turned OFF ${toTurnOff.length} products`);
      }

      initializeAllStores();
    });
    
    scheduleJobs.set(time, job);
    console.log(`Created cron job for ${time} (${toTurnOn.length} ON, ${toTurnOff.length} OFF)`);
  }
};

// Initialize all automated jobs
export const startAutomatedJobs = () => {
  // Only schedule-based jobs (flash delivery jobs removed)
  refreshScheduleJobs().catch(err => {
    console.error('Failed to initialize schedule jobs:', err);
  });
  
  console.log('Automated jobs scheduled');
};
