import {
  BaseHandler,
  Handler,
  Operation,
  ScheduledOperation
} from '@stock-bot/handlers';
import type { DataIngestionServices } from '../../types';
import { crawlScheduler, dataFetch, dataScheduler, fetchCountries, fetchIndicators, marketDataFetch, marketDataScheduler, spiderUrl } from './actions';

@Handler('te')
export class TeHandler extends BaseHandler<DataIngestionServices> {
  constructor(services: any) {
    super(services);
  }

  /**
   * Initialize handler and create necessary indexes
   */
  async onInit(): Promise<void> {
    this.logger.info('Initializing TeHandler and creating indexes');
    
    if (!this.mongodb) {
      this.logger.warn('MongoDB not available, skipping index creation');
      return;
    }

    try {
      // Create indexes for teUrls collection
      const indexes = [
        // Compound index for finding URLs to crawl
        {
          indexSpec: { lastCrawled: 1, url: 1 },
          options: { 
            name: 'crawl_status_idx',
            background: true 
          }
        },
        // Unique index on URL to prevent duplicates
        {
          indexSpec: { url: 1 },
          options: { 
            name: 'url_unique_idx',
            unique: true,
            background: true 
          }
        },
        // Index for finding URLs by symbol
        {
          indexSpec: { teSymbol: 1 },
          options: { 
            name: 'symbol_idx',
            sparse: true,
            background: true 
          }
        },
        // Index for skip reason filtering
        {
          indexSpec: { skipReason: 1 },
          options: { 
            name: 'skip_reason_idx',
            sparse: true,
            background: true 
          }
        },
        // Compound index for efficient batch queries
        {
          indexSpec: { lastCrawled: 1, skipReason: 1 },
          options: { 
            name: 'batch_query_idx',
            background: true 
          }
        },
        // Index for finding URLs with chart data
        {
          indexSpec: { teChartUrl: 1 },
          options: {
            name: 'chart_url_idx',
            sparse: true,
            background: true
          }
        },
        // Index for data-scheduler: filter by teType + sort by lastDataFetch
        {
          indexSpec: { teType: 1, lastDataFetch: 1 },
          options: {
            name: 'data_fetch_schedule_idx',
            background: true,
          }
        }
      ];

      for (const index of indexes) {
        try {
          await this.mongodb.createIndex('teUrls', index.indexSpec, index.options);
          this.logger.info(`Created/verified index: ${index.options.name}`);
        } catch (error) {
          // Index might already exist, that's OK
          this.logger.debug(`Index ${index.options.name} may already exist:`, error);
        }
      }

      // Indexes for teData collection (one doc per symbol with data array)
      const teDataIndexes = [
        {
          indexSpec: { teSymbol: 1 },
          options: {
            name: 'symbol_unique_idx',
            unique: true,
            background: true,
          },
        },
        {
          indexSpec: { country: 1, category: 1 },
          options: {
            name: 'country_category_idx',
            background: true,
          },
        },
      ];

      for (const index of teDataIndexes) {
        try {
          await this.mongodb.createIndex('teData', index.indexSpec, index.options);
          this.logger.info(`Created/verified teData index: ${index.options.name}`);
        } catch (error) {
          this.logger.debug(`teData index ${index.options.name} may already exist:`, error);
        }
      }

      // Indexes for teMarketData collection
      const teMarketDataIndexes = [
        {
          indexSpec: { teSymbol: 1 },
          options: {
            name: 'symbol_unique_idx',
            unique: true,
            background: true,
          },
        },
        {
          indexSpec: { category: 1 },
          options: {
            name: 'category_idx',
            background: true,
          },
        },
      ];

      for (const index of teMarketDataIndexes) {
        try {
          await this.mongodb.createIndex('teMarketData', index.indexSpec, index.options);
          this.logger.info(`Created/verified teMarketData index: ${index.options.name}`);
        } catch (error) {
          this.logger.debug(`teMarketData index ${index.options.name} may already exist:`, error);
        }
      }

      // Check collection stats
      const count = await this.mongodb.countDocuments('teUrls', {});
      this.logger.info(`TeUrls collection has ${count} documents`);

    } catch (error) {
      this.logger.error('Error creating indexes for TeHandler:', error);
      // Don't throw - allow handler to continue even if indexes fail
    }
  }

  @ScheduledOperation('te-countries', '0 0 * * 0', {
    priority: 5,
    description: 'Fetch and update Trading Economics countries data',
    immediately: true,
  })
  fetchCountries = fetchCountries;

  @ScheduledOperation('te-indicators', '0 0 * * 0', {
    priority: 5,
    description: 'Fetch and update Trading Economics indicators list',
    immediately: true,
  })
  fetchIndicators = fetchIndicators;

  @ScheduledOperation('te-spider', '* * * * *', {
    priority: 5,
    description: 'Spider Trading Economics URLs for data extraction (every minute)',
    immediately: true,
  })
  spiderUrlSchedule = spiderUrl;

  @ScheduledOperation('te-crawl-scheduler', '*/5 * * * *', {
    priority: 8,
    description: 'Schedule spider jobs for stale/uncrawled URLs (every 5 min)',
    immediately: true,
  })
  crawlScheduler = crawlScheduler;

  @ScheduledOperation('te-data-scheduler', '*/10 * * * *', {
    priority: 7,
    description: 'Schedule TE CDN data fetch jobs for symbols with new data (every 10 min)',
    immediately: true,
  })
  dataScheduler = dataScheduler;

  @Operation('te-data-fetch')
  dataFetch = dataFetch;

  @ScheduledOperation('te-market-data-scheduler', '*/10 * * * *', {
    priority: 7,
    description: 'Schedule market data fetch jobs for MK/TV symbols with new data (every 10 min)',
    immediately: true,
  })
  marketDataScheduler = marketDataScheduler;

  @Operation('te-market-data-fetch')
  marketDataFetch = marketDataFetch;
}