import Redis from "ioredis";

let redisInstance: Redis | null = null;

export async function getRedis(): Promise<Redis> {
  if (redisInstance) {
    return redisInstance;
  }

  const redisUrl = process.env.REDIS_URL || "redis://localhost:6379";
  
  try {
    redisInstance = new Redis(redisUrl, {
      lazyConnect: false,
      maxRetriesPerRequest: null,
      enableReadyCheck: false,
      enableOfflineQueue: true,
      retryStrategy: (times) => {
        const delay = Math.min(times * 50, 2000);
        return delay;
      },
    });

    redisInstance.on("error", (err) => {
      console.error("[Redis] Error:", err.message);
    });

    redisInstance.on("connect", () => {
      console.log("[Redis] Connected");
    });

    redisInstance.on("ready", () => {
      console.log("[Redis] Ready");
    });

    redisInstance.on("reconnecting", () => {
      console.log("[Redis] Reconnecting...");
    });

    // Test connection
    await redisInstance.ping();
    console.log("[Redis] Ping successful");

    return redisInstance;
  } catch (error) {
    console.error("[Redis] Connection failed:", error);
    throw error;
  }
}

export async function closeRedis(): Promise<void> {
  if (redisInstance) {
    await redisInstance.quit();
    redisInstance = null;
  }
}

// Cache helper functions
export async function getCached<T>(key: string): Promise<T | null> {
  try {
    const redis = await getRedis();
    const data = await redis.get(key);
    return data ? JSON.parse(data) : null;
  } catch (error) {
    console.error(`[Redis] Error getting cache for ${key}:`, error);
    return null;
  }
}

export async function setCached<T>(
  key: string,
  value: T,
  expirationSeconds?: number
): Promise<boolean> {
  try {
    const redis = await getRedis();
    const data = JSON.stringify(value);
    
    if (expirationSeconds) {
      await redis.setex(key, expirationSeconds, data);
    } else {
      await redis.set(key, data);
    }
    return true;
  } catch (error) {
    console.error(`[Redis] Error setting cache for ${key}:`, error);
    return false;
  }
}

export async function deleteCached(key: string): Promise<boolean> {
  try {
    const redis = await getRedis();
    const result = await redis.del(key);
    return result > 0;
  } catch (error) {
    console.error(`[Redis] Error deleting cache for ${key}:`, error);
    return false;
  }
}

export async function invalidateCachePattern(pattern: string): Promise<number> {
  try {
    const redis = await getRedis();
    const keys = await redis.keys(pattern);
    if (keys.length === 0) return 0;
    return await redis.del(...keys);
  } catch (error) {
    console.error(`[Redis] Error invalidating cache pattern ${pattern}:`, error);
    return 0;
  }
}

// Session helpers for BetterAuth
export async function getSession(sessionId: string): Promise<any> {
  return getCached(`session:${sessionId}`);
}

export async function setSession(
  sessionId: string,
  sessionData: any,
  expirationSeconds: number = 86400 // 24 hours
): Promise<boolean> {
  return setCached(`session:${sessionId}`, sessionData, expirationSeconds);
}

export async function deleteSession(sessionId: string): Promise<boolean> {
  return deleteCached(`session:${sessionId}`);
}

// Cache key generators
export const cacheKeys = {
  user: (userId: string) => `user:${userId}`,
  userByEmail: (email: string) => `user:email:${email}`,
  session: (sessionId: string) => `session:${sessionId}`,
  webinar: (webinarId: string) => `webinar:${webinarId}`,
  webinars: (page: number = 1) => `webinars:list:${page}`,
  registrations: (userId: string) => `registrations:${userId}`,
  contact: (contactId: string) => `contact:${contactId}`,
  config: "system:config",
  adminSetup: "admin:setup",
};
