import {
  BaseHandler,
  Disabled,
  Handler,
  Operation,
  ScheduledOperation,
} from '@stock-bot/handlers';
import type { OperationRegistry } from '../../shared/operation-manager';
import type { DataIngestionServices } from '../../types';
import {
  checkSessions,
  createSession,
  deduplicateSymbols,
  scheduleEventsUpdates,
  scheduleFinancialsUpdates,
  scheduleInsidersUpdates,
  schedulePriceUpdates,
  scheduleSymbolInfoUpdates,
  scheduleSymbolNewsUpdates,
  searchSymbols,
  spiderSymbol,
  updateEvents,
  updateExchangeStats,
  updateExchangeStatsAndDeduplicate,
  updateFinancials,
  updateGeneralNews,
  updateInsiders,
  updatePrices,
  updateSymbolInfo,
  updateSymbolNews
} from './actions';
import { crawlIntradayData, scheduleIntradayCrawls } from './actions/intraday-crawl.action';
import { createQMOperationRegistry } from './shared/operation-provider';

@Handler('qm')
@Disabled() // Disable by default, enable specific operations as needed
export class QMHandler extends BaseHandler<DataIngestionServices> {
  public operationRegistry: OperationRegistry;

  constructor(services: any) {
    super(services); // Handler name read from @Handler decorator
    
    // Use pre-initialized registry if available, otherwise create new one
    if ((QMHandler as any).operationRegistry) {
      this.operationRegistry = (QMHandler as any).operationRegistry;
      this.logger.info('Using pre-initialized QM operation registry');
    } else {
      // Fallback: Initialize operation registry with QM provider
      createQMOperationRegistry(this.mongodb, this.logger)
        .then(registry => {
          this.operationRegistry = registry;
        })
        .catch(error => {
          this.logger.error('Failed to initialize QM operations', { error });
        });
    }
  }

  /**
   * SESSIONS
   */
  @ScheduledOperation('check-sessions', '*/1 * * * *', {
    priority: 8,
    immediately: true,
    description: 'Check and maintain QM sessions every 1 minutes',
  })
  checkSessions = checkSessions;

  @Operation('create-session')
  createSession = createSession;

  /**
   * SYMBOLS
   */
  @Operation('search-symbols')
  searchSymbols = searchSymbols;

  @Disabled()
  @ScheduledOperation('spider-symbols', '0 0 * * 0', {
    priority: 9,
    immediately: false,
    description: 'Weekly comprehensive symbol search using QM API spider - runs every Saturday at midnight'
  })
  spiderSymbol = spiderSymbol;

  /**
   * EXCHANGE STATS & DEDUPLICATION
   */
  @Operation('update-exchange-stats')
  updateExchangeStats = updateExchangeStats;

  @Operation('deduplicate-symbols')
  deduplicateSymbols = deduplicateSymbols;

  @Operation('update-exchange-stats-and-deduplicate')
  updateExchangeStatsAndDeduplicate = updateExchangeStatsAndDeduplicate;

  @ScheduledOperation('schedule-exchange-stats-and-dedup', '0 1 * * *', {
    priority: 7,
    immediately: false,
    description: 'Update exchange statistics and deduplicate symbols daily at 1 AM'
  })
  scheduleExchangeStatsAndDedup = updateExchangeStatsAndDeduplicate;

  /**
   * SYMBOL INFO
   */
  @Operation('update-symbol-info')
  updateSymbolInfo = updateSymbolInfo;

  @Disabled()
  @ScheduledOperation('schedule-symbol-info-updates', '0 */6 * * *', {
    priority: 7,
    immediately: false,
    description: 'Check for symbols needing info updates every 6 hours'
  })
  scheduleSymbolInfoUpdates = scheduleSymbolInfoUpdates;

  /**
   * FINANCIALS
   */
  @Operation('update-financials')
  updateFinancials = updateFinancials;

  @Disabled()
  @ScheduledOperation('schedule-financials-updates', '0 2 * * *', {
    priority: 6,
    immediately: false,
    description: 'Check for symbols needing financials updates daily at 2 AM'
  })
  scheduleFinancialsUpdates = scheduleFinancialsUpdates;

  /**
   * EVENTS (Dividends, Splits, Earnings)
   */
  @Operation('update-events')
  updateEvents = updateEvents;

  @Disabled()
  @ScheduledOperation('schedule-events-updates', '0 3 * * *', {
    priority: 6,
    immediately: false,
    description: 'Check for symbols needing events updates daily at 3 AM'
  })
  scheduleEventsUpdates = scheduleEventsUpdates;

  /**
   * PRICE DATA
   */
  @Operation('update-prices')
  updatePrices = updatePrices;

  @Disabled()
  @ScheduledOperation('schedule-price-updates', '0 */6 * * *', {
    priority: 8,
    immediately: false,
    description: 'Check for symbols needing price updates every 6 hours'
  })
  schedulePriceUpdates = schedulePriceUpdates;

  /**
   * INTRADAY DATA
   */
  @Operation('crawl-intraday-data')
  crawlIntradayData = crawlIntradayData;

  @Operation('schedule-intraday-crawls')
  scheduleIntradayCrawls = scheduleIntradayCrawls;

  // @Disabled()
  @ScheduledOperation('schedule-intraday-crawls-batch', '0 0 * * 0', {
    priority: 5,
    immediately: false,
    description: 'Schedule intraday crawls for incomplete symbols every 12 hours'
  })
  scheduleIntradayCrawlsBatch = async () => {
    return scheduleIntradayCrawls.call(this, {
      priorityMode: 'incomplete'
    });
  };

  /**
   * INSIDER TRADING
   */
  @Operation('update-insiders')
  updateInsiders = updateInsiders;

  @Disabled()
  @ScheduledOperation('schedule-insiders-updates', '0 4 * * 1', {
    priority: 5,
    immediately: false,
    description: 'Check for symbols needing insider updates weekly on Monday at 4 AM'
  })
  scheduleInsidersUpdates = scheduleInsidersUpdates;

  /**
   * NEWS
   */
  @Operation('update-symbol-news')
  updateSymbolNews = updateSymbolNews;

  @Operation('update-general-news')
  updateGeneralNews = updateGeneralNews;

  @Disabled()
  @ScheduledOperation('schedule-symbol-news-updates', '0 5 * * 1', {
    priority: 4,
    immediately: false,
    description: 'Check for symbols needing news updates weekly on Monday at 5 AM'
  })
  scheduleSymbolNewsUpdates = scheduleSymbolNewsUpdates;

  @Disabled()
  @ScheduledOperation('update-general-news-frequent', '*/1 * * * *', {
    priority: 9,
    immediately: true,
    description: 'Update general market news every minute'
  })
  updateGeneralNewsFrequent = async () => {
    return updateGeneralNews.call(this, {
      categories: ['market', 'economy', 'politics', 'breaking'],
      lookbackMinutes: 5 // Only look back 5 minutes to avoid duplicates
    });
  };

    /**
   * FILINGS
   */
  // @Operation('update-filings')
  // updateFilings = updateFilings;

  // // @Disabled()
  // @ScheduledOperation('schedule-filings-updates', '0 */8 * * *', {
  //   priority: 5,
  //   immediately: false,
  //   description: 'Check for symbols needing filings updates every 8 hours'
  // })
  // scheduleFilingsUpdates = scheduleFilingsUpdates;
}