/**
 * Redis Cache Adapter
 * Decoupled Redis implementation
 */

import type { CacheAdapter, CacheConfig } from './interfaces';

export class RedisCacheAdapter implements CacheAdapter {
  private client: any = null;
  private prefix: string;
  private defaultTTL: number;
  private redisUrl: string;

  constructor(config: CacheConfig & { redisUrl?: string } = {}) {
    this.prefix = config.prefix || 'mintel:';
    this.defaultTTL = config.defaultTTL || 3600;
    this.redisUrl = config.redisUrl || process.env.REDIS_URL || 'redis://localhost:6379';
  }

  private async init(): Promise<boolean> {
    if (this.client !== null) return true;

    try {
      const Redis = await import('ioredis');
      this.client = new Redis.default(this.redisUrl);
      
      this.client.on('error', (err: Error) => {
        console.warn('Redis connection error:', err.message);
        this.client = null;
      });

      this.client.on('connect', () => {
        console.log('✅ Redis connected');
      });

      // Test connection
      await this.client.set(this.prefix + '__test__', 'ok', 'EX', 1);
      return true;
    } catch (error) {
      console.warn('Redis unavailable:', error);
      this.client = null;
      return false;
    }
  }

  async get<T>(key: string): Promise<T | null> {
    const available = await this.init();
    if (!available || !this.client) return null;

    try {
      const data = await this.client.get(this.prefix + key);
      return data ? JSON.parse(data) : null;
    } catch (error) {
      console.warn('Redis get error:', error);
      return null;
    }
  }

  async set<T>(key: string, value: T, ttl?: number): Promise<void> {
    const available = await this.init();
    if (!available || !this.client) return;

    try {
      const finalTTL = ttl || this.defaultTTL;
      await this.client.setex(this.prefix + key, finalTTL, JSON.stringify(value));
    } catch (error) {
      console.warn('Redis set error:', error);
    }
  }

  async del(key: string): Promise<void> {
    const available = await this.init();
    if (!available || !this.client) return;

    try {
      await this.client.del(this.prefix + key);
    } catch (error) {
      console.warn('Redis del error:', error);
    }
  }

  async clear(): Promise<void> {
    const available = await this.init();
    if (!available || !this.client) return;

    try {
      const keys = await this.client.keys(this.prefix + '*');
      if (keys.length > 0) {
        await this.client.del(...keys);
      }
    } catch (error) {
      console.warn('Redis clear error:', error);
    }
  }
}