/**
 * QM Events Actions - Fetch and update dividends, splits, and earnings together
 */

import type { ExecutionContext } from '@stock-bot/handlers';
import type { QMHandler } from '../qm.handler';
import { QM_CONFIG, QM_SESSION_IDS } from '../shared/config';
import { QMSessionManager } from '../shared/session-manager';

/**
 * Update events (dividends, splits, earnings) for a single symbol
 * Single API call returns all three data types
 */
export async function updateEvents(
  this: QMHandler,
  input: {
    symbol: string;
    exchange: string;
    qmSearchCode: string;
  },
  _context?: ExecutionContext
): Promise<{
  success: boolean;
  symbol: string;
  message: string;
  data?: {
    dividends: number;
    splits: number;
    earnings: number;
  };
}> {
  const { symbol, exchange, qmSearchCode } = input;
  
  this.logger.info(`Fetching events ${qmSearchCode}`, { symbol, exchange, qmSearchCode });

  const sessionManager = QMSessionManager.getInstance();
  await sessionManager.initialize(this.cache, this.logger);

  // Get a session - you'll need to add the appropriate session ID
  const sessionId = QM_SESSION_IDS.PRICES; // TODO: Update with correct session ID
  const session = await sessionManager.getSession(sessionId);
  
  if (!session || !session.uuid) {
    throw new Error(`No active session found for QM events ${qmSearchCode}`);
  }

  try {
    // Build API request for events
    const searchParams = new URLSearchParams({
      earnings: 'true',
      splits: 'true',
      dividends: 'true',
      symbol: qmSearchCode,          
    });


    // TODO: Update with correct events endpoint
    const apiUrl = `${QM_CONFIG.EVENTS_URL}?${searchParams.toString()}`;

    const response = await fetch(apiUrl, {
      method: 'GET',
      headers: session.headers,
      proxy: session.proxy,
    });

    if (!response.ok) {
      throw new Error(`QM API request failed: ${response.status} ${response.statusText}`);
    }

    const corporateData = await response.json();
    const results = corporateData.results;
    if (typeof results.error === 'object') {
      await this.operationRegistry.updateOperation('qm', qmSearchCode, 'events_update', {
        status: 'success',
      });
      throw new Error(`Invalid response structure from QM API for ${qmSearchCode}`);
    }
    
    // Update session success stats
    await sessionManager.incrementSuccessfulCalls(sessionId, session.uuid);

    
    let dividendCount = 0;
    let splitCount = 0;
    let earningsCount = 0;

    // Process dividends
    if (results.dividends[0].dividend && results.dividends[0].dividend.length > 0 && Array.isArray(results.dividends[0].dividend)) {
      await this.mongodb.batchUpsert(
        'qmDividends',
        results.dividends[0].dividend.map((dividend: any) => ({
          ...dividend,
          symbol,
          exchange,
          qmSearchCode,
          reportDate: new Date(dividend.date),
        })),
        ['qmSearchCode','reportDate']
      );
      dividendCount = results.dividends[0].dividend.length;
    }

    // Process splits
    if (results.splits[0].split && results.splits[0].split.length > 0 && Array.isArray(results.splits[0].split)) {
      await this.mongodb.batchUpsert(
        'qmSplits',
        results.splits[0].split.map((split: any) => ({
          ...split,
          symbol,
          exchange,
          qmSearchCode,
          reportDate: new Date(split.date),
        })),
        ['qmSearchCode','reportDate']
      );
      splitCount = results.splits[0].split.length;
    }

    // Process earnings
    if (results.earnings[0].earning && results.earnings[0].earning.length > 0 && Array.isArray(results.earnings[0].earning)) {
      await this.mongodb.batchUpsert(
        'qmEarnings',
        results.earnings[0].earning.map((earning: any) => ({
          ...earning,
          symbol,
          exchange,
          qmSearchCode,
          reportDate: new Date(earning.reportDate[0]),
        })),
        ['qmSearchCode','reportDate']
      );
      earningsCount = results.earnings[0].earning.length;
    }

    // Update tracking for events
    const updateTime = new Date();
    
    await this.operationRegistry.updateOperation('qm', qmSearchCode, 'events_update', {
      status: 'success',
      lastRecordDate: updateTime,
      recordCount: dividendCount + splitCount + earningsCount
    });

    this.logger.info(`Events updated successfully ${qmSearchCode}`, { 
      symbol,
      dividendCount,
      splitCount,
      earningsCount
    });

    return {
      success: true,
      symbol,
      message: `Events updated for ${qmSearchCode}`,
      data: { 
        dividends: dividendCount,
        splits: splitCount,
        earnings: earningsCount
      }
    };

  } catch (error) {
    // Update session failure stats
    if (session.uuid) {
      await sessionManager.incrementFailedCalls(sessionId, session.uuid);
    }

    this.logger.error('Error fetching events', { 
      symbol,
      error: error instanceof Error ? error.message : 'Unknown error'
    });
    
    // Track failure for events
    
    await this.operationRegistry.updateOperation('qm', qmSearchCode, 'events_update', {
      status: 'failure'
    });
    
    return {
      success: false,
      symbol,
      message: `Failed to fetch events: ${error instanceof Error ? error.message : 'Unknown error'}`
    };
  }
}

/**
 * Schedule events updates for symbols that need refreshing
 */
export async function scheduleEventsUpdates(
  this: QMHandler,
  input: {
    limit?: number;
    forceUpdate?: boolean;
  } = {},
  _context?: ExecutionContext
): Promise<{
  message: string;
  symbolsQueued: number;
  errors: number;
}> {
  const { limit = 100000, forceUpdate = false } = input;
  
  this.logger.info('Scheduling events updates', { limit, forceUpdate });

  try {
    // Get symbols that need events updates
    const staleSymbols = await this.operationRegistry.getStaleSymbols('qm', 'events_update', {
      minHoursSinceRun: forceUpdate ? 0 : 24 * 7, // Weekly
      limit
    });

    if (staleSymbols.length === 0) {
      this.logger.info('No symbols need events updates');
      return {
        message: 'No symbols need events updates',
        symbolsQueued: 0,
        errors: 0
      };
    }

    this.logger.info(`Found ${staleSymbols.length} symbols needing events updates`);

    let queued = 0;
    let errors = 0;

    // Schedule individual update jobs for each symbol
    for (const item of staleSymbols) {
      try {
        await this.scheduleOperation('update-events', {
          symbol: item.symbol.symbol,
          exchange: item.symbol.exchange,
          qmSearchCode: item.symbol.qmSearchCode
        }, {
          priority: 4,
          delay: queued * 0.05 // 1.5 seconds between jobs
        });
        
        queued++;
      } catch (error) {
        this.logger.error(`Failed to schedule events update for ${item.symbol.symbol}`, { error });
        errors++;
      }
    }

    this.logger.info('Events update scheduling completed', {
      symbolsQueued: queued,
      errors,
      total: staleSymbols.length
    });

    return {
      message: `Scheduled events updates for ${queued} symbols`,
      symbolsQueued: queued,
      errors
    };
  } catch (error) {
    this.logger.error('Events scheduling failed', { error });
    throw error;
  }
}