/**
 * SchedulerManager
 *
 * Coordinates all schedulers - starting, stopping, and monitoring
 */

import { PrismaClient } from '@prisma/client';
import logger from '../utils/logger';
import { TabApiClient } from '../api/tab';
import { BaseScheduler } from './base-scheduler';
import { MorningScrapeScheduler } from './morning-scrape-scheduler';
import { PreRaceScheduler } from './pre-race-scheduler';
import { PostRaceScheduler } from './post-race-scheduler';
import { CleanupScheduler } from './cleanup-scheduler';
import { ScheduleType } from './types';

export class SchedulerManager {
  private schedulers: Map<ScheduleType, BaseScheduler> = new Map();

  constructor(
    private apiClient: TabApiClient,
    private prisma: PrismaClient
  ) {
    this.initializeSchedulers();
  }

  /**
   * Initialize all schedulers
   */
  private initializeSchedulers(): void {
    // Morning scrape
    this.schedulers.set(
      ScheduleType.MORNING_SCRAPE,
      new MorningScrapeScheduler(this.apiClient, this.prisma)
    );

    // Pre-race updates
    this.schedulers.set(
      ScheduleType.PRE_RACE_T60,
      new PreRaceScheduler(this.apiClient, this.prisma, ScheduleType.PRE_RACE_T60)
    );

    this.schedulers.set(
      ScheduleType.PRE_RACE_T15,
      new PreRaceScheduler(this.apiClient, this.prisma, ScheduleType.PRE_RACE_T15)
    );

    // Post-race results
    this.schedulers.set(
      ScheduleType.POST_RACE_T5,
      new PostRaceScheduler(this.apiClient, this.prisma)
    );

    // Cleanup scheduler (doesn't need apiClient)
    this.schedulers.set(
      ScheduleType.CLEANUP_JOB_RUNS,
      new CleanupScheduler(this.prisma)
    );

    logger.info({
      schedulersInitialized: this.schedulers.size,
    }, 'Scheduler manager initialized');
  }

  /**
   * Start all enabled schedulers
   */
  startAll(): void {
    logger.info('Starting all schedulers');

    let startedCount = 0;
    for (const [type, scheduler] of this.schedulers) {
      try {
        scheduler.start();
        startedCount++;
      } catch (error) {
        logger.error({
          type,
          error: error instanceof Error ? error.message : 'Unknown error',
        }, 'Failed to start scheduler');
      }
    }

    logger.info({
      total: this.schedulers.size,
      started: startedCount,
    }, 'Schedulers started');
  }

  /**
   * Stop all schedulers
   */
  stopAll(): void {
    logger.info('Stopping all schedulers');

    let stoppedCount = 0;
    for (const [type, scheduler] of this.schedulers) {
      try {
        scheduler.stop();
        stoppedCount++;
      } catch (error) {
        logger.error({
          type,
          error: error instanceof Error ? error.message : 'Unknown error',
        }, 'Failed to stop scheduler');
      }
    }

    logger.info({
      total: this.schedulers.size,
      stopped: stoppedCount,
    }, 'Schedulers stopped');
  }

  /**
   * Start a specific scheduler
   */
  start(type: ScheduleType): void {
    const scheduler = this.schedulers.get(type);
    if (!scheduler) {
      throw new Error(`Scheduler not found: ${type}`);
    }

    scheduler.start();
    logger.info({ type }, 'Scheduler started');
  }

  /**
   * Stop a specific scheduler
   */
  stop(type: ScheduleType): void {
    const scheduler = this.schedulers.get(type);
    if (!scheduler) {
      throw new Error(`Scheduler not found: ${type}`);
    }

    scheduler.stop();
    logger.info({ type }, 'Scheduler stopped');
  }

  /**
   * Get status of all schedulers
   */
  getStatus() {
    const statuses = [];

    for (const scheduler of this.schedulers.values()) {
      statuses.push(scheduler.getStatus());
    }

    return {
      totalSchedulers: this.schedulers.size,
      schedulers: statuses,
    };
  }

  /**
   * Get a specific scheduler (useful for manual triggers)
   */
  getScheduler(type: ScheduleType): BaseScheduler | undefined {
    return this.schedulers.get(type);
  }
}
