import Redis from 'ioredis';
import { REDIS_DEFAULTS } from './constants';
import type { RedisConfig } from './types';

interface ConnectionConfig {
  name: string;
  singleton?: boolean;
  db?: number;
  redisConfig: RedisConfig;
  logger?: unknown;
}

/**
 * Simplified Redis Connection Manager
 */
export class RedisConnectionManager {
  private static connections = new Map<string, Redis>();
  private static instance: RedisConnectionManager;

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

  /**
   * Get or create a Redis connection
   */
  getConnection(config: ConnectionConfig): Redis {
    const { name, singleton = true, redisConfig } = config;

    if (singleton) {
      const existing = RedisConnectionManager.connections.get(name);
      if (existing) {
        return existing;
      }
    }

    const connection = this.createConnection(redisConfig);

    if (singleton) {
      RedisConnectionManager.connections.set(name, connection);
    }

    return connection;
  }

  /**
   * Create a new Redis connection
   */
  private createConnection(config: RedisConfig): Redis {
    return new Redis({
      host: config.host,
      port: config.port,
      password: config.password,
      username: config.username,
      db: config.db ?? REDIS_DEFAULTS.DB,
      maxRetriesPerRequest: config.maxRetriesPerRequest ?? REDIS_DEFAULTS.MAX_RETRIES,
      connectTimeout: config.connectTimeout ?? REDIS_DEFAULTS.CONNECT_TIMEOUT,
      commandTimeout: config.commandTimeout ?? REDIS_DEFAULTS.COMMAND_TIMEOUT,
      lazyConnect: false,
      ...(config.tls && { tls: config.tls }),
    });
  }

  /**
   * Close all connections
   */
  static async closeAll(): Promise<void> {
    const promises = Array.from(this.connections.values()).map(conn => conn.quit().catch(() => {}));
    await Promise.all(promises);
    this.connections.clear();
  }
}
