/**
 * Session Manager Wrapper - Provides a unified interface that can switch between implementations
 */

import type { CacheProvider } from '@stock-bot/cache';
import type { Logger } from '@stock-bot/types';
import { QMSessionManager } from './session-manager';
import { QMSessionManagerRedis } from './session-manager-redis';
import type { QMSession } from './types';

/**
 * Wrapper that delegates to either in-memory or Redis-based implementation
 * Set REDIS_SESSION_MANAGER=true to use Redis implementation
 */
export class SessionManagerWrapper {
  private implementation: QMSessionManager | QMSessionManagerRedis;
  private static instance: SessionManagerWrapper | null = null;

  private constructor() {
    // Use Redis implementation if env var is set or if in production
    const useRedis = process.env.REDIS_SESSION_MANAGER === 'true' || 
                     process.env.NODE_ENV === 'production';
    
    if (useRedis) {
      this.implementation = QMSessionManagerRedis.getInstance();
    } else {
      this.implementation = QMSessionManager.getInstance();
    }
  }

  static getInstance(): SessionManagerWrapper {
    if (!SessionManagerWrapper.instance) {
      SessionManagerWrapper.instance = new SessionManagerWrapper();
    }
    return SessionManagerWrapper.instance;
  }

  /**
   * Reset instance (for testing)
   */
  static resetInstance(): void {
    SessionManagerWrapper.instance = null;
  }

  /**
   * Initialize with cache provider and logger
   */
  initialize(cache?: CacheProvider, logger?: Logger): void {
    this.implementation.initialize(cache, logger);
  }

  /**
   * Get the implementation type
   */
  getImplementationType(): string {
    return this.implementation instanceof QMSessionManagerRedis ? 'redis' : 'memory';
  }

  // Delegate all methods to the implementation
  async getSession(sessionId: string): Promise<QMSession | null> {
    return this.implementation.getSession(sessionId);
  }

  async getSessionByUuid(sessionId: string, uuid: string): Promise<QMSession | null> {
    if (this.implementation instanceof QMSessionManagerRedis) {
      return this.implementation.getSessionByUuid(sessionId, uuid);
    } else {
      return this.implementation.getSessionByUuid(sessionId, uuid);
    }
  }

  async addSession(sessionId: string, session: QMSession): Promise<void> {
    return this.implementation.addSession(sessionId, session);
  }

  async getSessions(sessionId: string): Promise<QMSession[]> {
    if (this.implementation instanceof QMSessionManagerRedis) {
      return this.implementation.getSessions(sessionId);
    } else {
      return this.implementation.getSessions(sessionId);
    }
  }

  async getSessionCount(sessionId?: string): Promise<number> {
    if (this.implementation instanceof QMSessionManagerRedis) {
      return this.implementation.getSessionCount(sessionId);
    } else {
      return this.implementation.getSessionCount();
    }
  }

  async cleanupFailedSessions(): Promise<number> {
    return this.implementation.cleanupFailedSessions();
  }

  async needsMoreSessions(sessionId: string): Promise<boolean> {
    return this.implementation.needsMoreSessions(sessionId);
  }

  async getStats(): Promise<Record<string, { total: number; valid: number; failed: number }>> {
    return this.implementation.getStats();
  }

  async incrementFailedCalls(sessionId: string, sessionUuid: string): Promise<void> {
    return this.implementation.incrementFailedCalls(sessionId, sessionUuid);
  }

  async incrementSuccessfulCalls(sessionId: string, sessionUuid: string): Promise<void> {
    return this.implementation.incrementSuccessfulCalls(sessionId, sessionUuid);
  }

  // Additional methods for memory implementation
  isAtCapacity(sessionId: string): boolean {
    if (this.implementation instanceof QMSessionManager) {
      return this.implementation.isAtCapacity(sessionId);
    }
    // For Redis, we'd need to implement this async
    throw new Error('isAtCapacity not available for Redis implementation');
  }

  // Migration helper
  async migrateToRedis(): Promise<void> {
    if (this.implementation instanceof QMSessionManagerRedis) {
      return this.implementation.migrateFromOldFormat();
    }
    throw new Error('Migration only available for Redis implementation');
  }
}