/**
 * QM Session Actions - Session management and creation
 */

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

/**
 * Check existing sessions and queue creation jobs for needed sessions
 * This is the main session management function that handles cleanup, maintenance, and initialization
 */
export async function checkSessions(
  this: QMHandler,
  _input: unknown,
  _context: ExecutionContext
): Promise<{
  cleaned: number;
  queued: number;
  message: string;
}> {
  this.logger.info('Checking QM sessions');
  
  const sessionManager = QMSessionManager.getInstance();
  
  // Initialize with cache provider and logger
  await sessionManager.initialize(this.cache, this.logger);

  // Cleanup failed sessions (this now handles its own cache sync)
  const cleanedCount = await sessionManager.cleanupFailedSessions();
  
  // Check which session IDs need more sessions and queue creation jobs
  let queuedCount = 0;
  for (const [sessionType, sessionId] of Object.entries(QM_SESSION_IDS)) {
    this.logger.debug(`Checking session ID: ${sessionId}`);
    if (await sessionManager.needsMoreSessions(sessionId)) {
      const currentCount = await sessionManager.getSessionCount(sessionId);
      const neededSessions = SESSION_CONFIG.MAX_SESSIONS - currentCount;
      
      // Queue up to 10 at a time to avoid overwhelming the system
      const toQueue = Math.min(neededSessions, 40);
      
      for (let i = 0; i < toQueue; i++) {
        await this.scheduleOperation('create-session', { sessionId, sessionType }, {
          priority: 0,
          // delay: i * 2000, // Stagger creation by 2 seconds
        });
        queuedCount++;
      }
      
      this.logger.info(`Queued ${toQueue} jobs to create sessions for ${sessionType}`, {
        currentCount,
        targetCount: SESSION_CONFIG.MAX_SESSIONS,
      });
    }
  }

  this.logger.info('QM session check completed', {
    cleaned: cleanedCount,
    queued: queuedCount,
  });

  return {
    cleaned: cleanedCount,
    queued: queuedCount,
    message: `Session check completed: cleaned ${cleanedCount}, queued ${queuedCount}`,
  };
}

/**
 * Create a single session for a specific session ID
 */
interface CreateSessionInput {
  sessionId?: string;
  sessionType?: string;
}

export async function createSession(
  this: QMHandler,
  input: CreateSessionInput
): Promise<{ sessionId: string; status: string; sessionType: string, session?: QMSession }> {
  const { sessionId, sessionType = 'LOOKUP' } = input || {};
  const sessionManager = QMSessionManager.getInstance();

  // Get the actual session ID from config
  const actualSessionId = sessionId || QM_SESSION_IDS[sessionType as keyof typeof QM_SESSION_IDS];
  
  if (!actualSessionId) {
    throw new Error(`Invalid session type: ${sessionType}`);
  }

  // Initialize with cache provider and logger
  await sessionManager.initialize(this.cache, this.logger);

  try {
    // Get proxy from proxy service
    const proxyUrl: string | null = this.proxy ? this.proxy.getProxy() : null;
    if (!proxyUrl) {
      this.logger.warn(`No proxy available for session type ${sessionType}`);
      throw new Error(`No proxy available for session type ${sessionType}`);
    }

    // Authenticate with QM API inline
    const sessionUrl = `${QM_CONFIG.BASE_URL}${QM_CONFIG.SESSION_PATH}/${sessionId}`;
    
    // Build request options
    const sessionRequest = {
      proxy: proxyUrl || undefined,
      headers: getQmHeaders(),
    };

    this.logger.debug('Authenticating with QM API', { sessionUrl, sessionRequest });

    const sessionResponse = await fetch(sessionUrl, sessionRequest);

    // Check if authentication was successful
    if (!(sessionResponse.status === 200 || sessionResponse.status === 302)) {
      this.logger.warn('QM authentication failed', {
        status: sessionResponse.status,
        statusText: sessionResponse.statusText,
      });
      throw new Error(`QM authentication failed with status ${sessionResponse.status}`);
    }

    const sessionData = await sessionResponse.json();
    
    // Add token to headers
    sessionRequest.headers['Datatool-Token'] = sessionData.token;

    // Create session object with unique ID
    const session: QMSession = {
      uuid: `${sessionType.toLowerCase()}_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
      proxy: proxyUrl,
      headers: sessionRequest.headers,
      successfulCalls: 0,
      failedCalls: 0,
      lastUsed: new Date(),
      createdAt: new Date(),
    };

    // Add session to manager (this now handles cache sync)
    await sessionManager.addSession(actualSessionId, session);

    this.logger.info(`Successfully created session for ${sessionType}`, { session });

    return {
      sessionId: actualSessionId,
      status: 'created',
      sessionType,
      session,
    };
  } catch (error) {
    this.logger.error(`Failed to create session for ${sessionType}`, { error });
    return {
      sessionId: actualSessionId,
      status: 'error',
      sessionType,
    };
  }
}