/**
 * QM Financials Actions - Fetch and update financial statements
 */

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 financials for a single symbol
 */
export async function updateFinancials(
  this: QMHandler,
  input: {
    symbol: string;
    exchange: number;
    qmSearchCode: string;
    reportType: 'Q' | 'A'; // Quarterly or Annual
    lastRecordDate?: Date; // Optional, used for tracking
  },
  _context?: ExecutionContext
): Promise<{
  success: boolean;
  qmSearchCode: string;
  message: string;
  data?: any;
}> {
  const { symbol, exchange, qmSearchCode, reportType, lastRecordDate } = input;
  
  this.logger.info('Fetching financials', { 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 for financials
  const sessionId = QM_SESSION_IDS.FINANCIALS; // 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 financials`);
  }

  try {
    // Build API request for financials
    const searchParams = new URLSearchParams({
      currency: 'true',
      lang: 'en',
      latestfiscaldate: 'true',
      numberOfReports: lastRecordDate ? '5' : '250',
      pathName: '/demo/portal/company-research.php',
      qmodTool: 'Financials',
      reportType: reportType,
      symbol: 'AAPL',
      webmasterId: '500',
    });
    // TODO: Update with correct financials endpoint
    const apiUrl = `${QM_CONFIG.FINANCIALS_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 financialData = await response.json();
    let reports = [];
    if(Array.isArray(financialData.results.Company)){ //WEIRD BUG ON THEIR END FOR SOME REASON FOR ONE COMP ITS A ARRAY INSTEAD OF OBJECT
      reports = financialData?.results?.Company[0].Report || [];
    }else{
      reports = financialData?.results?.Company.Report || [];
    }

    // Process and store financial data
    if (reports && reports.length > 0) {
      // Store financial statements in a separate collection
      await this.mongodb.batchUpsert(
        'qmFinancials-new',
        reports.map((statement: any) => ({
          ...statement,
          symbol,
          exchange,
          qmSearchCode
        })),
        ['qmSearchCode', 'reportPeriod', 'reportDate'] // Unique keys
      );

      // Update symbol to track last financials update
      await this.operationRegistry.updateOperation('qm', qmSearchCode, `financials_update_${reportType === 'Q'? 'quarterly' : 'annual'}`, {
        status: 'success',
        lastRecordDate: new Date(),
        recordCount: reports.length
      });

      this.logger.info(`Financials updated successfully ${reportType} - ${qmSearchCode} (${reports.length})`, { 
        qmSearchCode,
        statementCount: reports.length
      });

      return {
        success: true,
        qmSearchCode,
        message: `Financials updated for ${qmSearchCode} - ${reportType} - ${reports.length}`,
        data: { count: reports.length }
      };
    } else {
      this.logger.warn('No financial data returned from API', { qmSearchCode });
      return {
        success: false,
        qmSearchCode,
        message: `No financial data found for symbol ${qmSearchCode}`
      };
    }

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

    this.logger.error('Error fetching financials', { 
      symbol,
      error: error instanceof Error ? error.message : 'Unknown error'
    });
    
    // Track failure
    await this.operationRegistry.updateOperation('qm', qmSearchCode, `financials_update_${reportType === 'Q'? 'quarterly' : 'annual'}`, {
      status: 'failure',
    });
    
    return {
      success: false,
      qmSearchCode,
      message: `Failed to fetch financials: ${error instanceof Error ? error.message : 'Unknown error'}`
    };
  }
}

/**
 * Schedule financial updates for symbols that need refreshing
 */
export async function scheduleFinancialsUpdates(
  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 financials updates', { limit, forceUpdate });

  try {
    // Get symbols that need updating for both quarterly and annual
    const staleSymbolsQ = await this.operationRegistry.getStaleSymbols('qm', 'financials_update_quarterly', {
      minHoursSinceRun: forceUpdate ? 0 : 24 * 7, // Weekly by default
      limit
    });
    const staleSymbolsA = await this.operationRegistry.getStaleSymbols('qm', 'financials_update_annual', {
      minHoursSinceRun: forceUpdate ? 0 : 24 * 7, // Weekly by default
      limit
    });

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

    this.logger.info(`Found ${staleSymbolsQ.length} symbols needing quarterly updates and ${staleSymbolsA.length} symbols needing annual updates`);

    // Create a map of symbols needing updates
    const symbolsNeedingUpdates = new Map<string, { quarterly: boolean, annual: boolean, item: any }>();
    
    // Add quarterly symbols
    for (const item of staleSymbolsQ) {
      const key = item.symbol.qmSearchCode;
      if (!symbolsNeedingUpdates.has(key)) {
        symbolsNeedingUpdates.set(key, { quarterly: true, annual: false, item });
      } else {
        symbolsNeedingUpdates.get(key)!.quarterly = true;
      }
    }
    
    // Add annual symbols
    for (const item of staleSymbolsA) {
      const key = item.symbol.qmSearchCode;
      if (!symbolsNeedingUpdates.has(key)) {
        symbolsNeedingUpdates.set(key, { quarterly: false, annual: true, item });
      } else {
        symbolsNeedingUpdates.get(key)!.annual = true;
      }
    }

    let queued = 0;
    let errors = 0;

    // Schedule individual update jobs for each symbol and report type
    for (const [qmSearchCode, { quarterly, annual, item }] of symbolsNeedingUpdates) {
      // Schedule quarterly updates if needed
      if (quarterly) {
        try {
          await this.scheduleOperation('update-financials', {
            symbol: item.symbol.symbol,
            exchange: item.symbol.exchange,
            qmSearchCode: qmSearchCode,
            reportType: 'Q',
            lastRecordDate: item.operations?.financials_update_quarterly?.lastRecordDate,
          }, {
            priority: 4,
            delay: queued  // 1 second between jobs
          });
          
          queued++;
        } catch (error) {
          this.logger.error(`Failed to schedule quarterly financials update for ${qmSearchCode}`, { error });
          errors++;
        }
      }

      // Schedule annual updates if needed
      if (annual) {
        try {
          await this.scheduleOperation('update-financials', {
            symbol: item.symbol.symbol,
            exchange: item.symbol.exchange,
            qmSearchCode: qmSearchCode,
            reportType: 'A',
            lastRecordDate: item.operations?.financials_update_annual?.lastRecordDate,
          }, {
            priority: 4,
            delay: queued // 1 second between jobs
          });
          
          queued++;
        } catch (error) {
          this.logger.error(`Failed to schedule annual financials update for ${qmSearchCode}`, { error });
          errors++;
        }
      }
    }

    this.logger.info('Financials update scheduling completed', {
      symbolsQueued: queued,
      errors,
      totalQuarterly: staleSymbolsQ.length,
      totalAnnual: staleSymbolsA.length
    });

    return {
      message: `Scheduled ${queued} financials updates (${staleSymbolsQ.length} quarterly, ${staleSymbolsA.length} annual)`,
      symbolsQueued: queued,
      errors
    };
  } catch (error) {
    this.logger.error('Financials scheduling failed', { error });
    throw error;
  }
}