/**
 * QM Prices Actions - Fetch and update daily price data
 */

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 daily prices for a single symbol
 */
export async function updatePrices(
  this: QMHandler,
  input: {
    qmSearchCode: string;
    lastRecordDate?: Date;
    symbol: string;
    exchange: string;
  },
  _context?: ExecutionContext
): Promise<{
  success: boolean;
  qmSearchCode: string;
  message: string;
  data?: any;
}> {
  const { qmSearchCode, lastRecordDate, symbol, exchange } = input;
  
  this.logger.info(`Fetching daily prices ${qmSearchCode}`, { qmSearchCode });

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

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

  try {
    // Build API request for daily prices
    const searchParams = new URLSearchParams({
    zeroTradeDays: 'false',
    start: lastRecordDate ? new Date(lastRecordDate).toISOString().split('T')[0] + '' : '1960-01-01',
    interval: '1',
    marketSession: 'mkt',
    freq: 'day',
    adjusted: 'false',
    adjustmentType: 'none',
    unadjusted: 'true',
    datatype: 'eod',
    symbol: qmSearchCode,
    });
    // https://app.quotemedia.com/datatool/getEnhancedChartData.json?zeroTradeDays=false&start=2025-06-22&interval=1&marketSession=mkt&freq=day&adjusted=true&adjustmentType=none&unadjusted=false&datatype=int&symbol=AAPL
    // TODO: Update with correct prices endpoint
    const apiUrl = `${QM_CONFIG.PRICES_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 responseData = await response.json();

    // Update session success stats
    await sessionManager.incrementSuccessfulCalls(sessionId, session.uuid);
    // Update symbol to track last price update
    
    const priceData = responseData.results?.history[0].eoddata || [];
    
    if(!priceData || priceData.length === 0) {
      this.logger.warn(`No price data found for symbol ${qmSearchCode}`);
      await this.operationRegistry.updateOperation('qm', qmSearchCode, 'price_update', {
        status: 'success',
        recordCount: priceData.length
      });
      return {
        success: false,
        qmSearchCode,
        message: `No price data found for symbol ${qmSearchCode}`
      };
    }

    // Process and store price data
    if (priceData && priceData.length > 0) {
      // Store prices in a separate collection
      const processedPrices = priceData.map((price: any) => ({
        ...price,
        symbol,
        exchange,
        qmSearchCode,
        dateTime: new Date(price.date),
      }));

      await this.mongodb.batchUpsert(
        'qmPrices',
        processedPrices,
        ['qmSearchCode', 'date'] // Unique keys
      );

      // Find the latest price date
      const latestDate = processedPrices.reduce((latest: Date, price: any) => 
        price.dateTime > latest ? price.dateTime : latest, 
        new Date(0)
      );

      
      await this.operationRegistry.updateOperation('qm', qmSearchCode, 'price_update', {
        status: 'success',
        lastRecordDate: latestDate,
        recordCount: priceData.length
      });

      this.logger.info('Prices updated successfully', { 
        qmSearchCode,
        priceCount: priceData.length,
        latestDate
      });

      return {
        success: true,
        qmSearchCode,
        message: `Prices updated for ${qmSearchCode}`,
        data: { 
          count: priceData.length,
          latestDate 
        }
      };
    } else {
      this.logger.warn('No price data returned from API', { qmSearchCode });
      return {
        success: false,
        qmSearchCode,
        message: `No price data found for qmSearchCode ${qmSearchCode}`
      };
    }

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

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

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

  try {
    // Get symbols that need updating
    const staleSymbols = await this.operationRegistry.getStaleSymbols('qm', 'price_update', {
      minHoursSinceRun: forceUpdate ? 0 : 24, // Daily updates
      limit
    });

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

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

    let queued = 0;
    let errors = 0;

    // Schedule individual update jobs for each symbol
    for (const item of staleSymbols) {
      try {
        await this.scheduleOperation('update-prices', {
          qmSearchCode: item.symbol.qmSearchCode,
          lastRecordDate: item.operations?.price_update?.lastRecordDate,
          symbol: item.symbol.symbol,
          exchange: item.symbol.exchange
        }, {
          priority: 7, // High priority for price data
          delay: queued * 100 // 0.1 seconds between jobs
        });
        
        queued++;
      } catch (error) {
        this.logger.error(`Failed to schedule price update for ${item.symbol.qmSearchCode}`, { error });
        errors++;
      }
    }

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

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