import "server-only";
import Redis from "ioredis";

let redis: Redis | null = null;

function getRedis(): Redis {
  if (!redis) {
    redis = new Redis(process.env.REDIS_URL || "redis://localhost:6379", {
      maxRetriesPerRequest: 3,
      lazyConnect: true,
    });
    redis.on("error", (err) => {
      console.error("[redis] connection error:", err.message);
    });
  }
  return redis;
}

export type SimpleStoreRedisOptions = {
  keyPrefix: string;
  ttlSeconds: number;
};

/**
 * Simple Redis-backed store compatible with @atproto SimpleStore interface.
 * Used for OAuth caches that should survive server restarts.
 */
export class SimpleStoreRedis<V> {
  private keyPrefix: string;
  private ttlSeconds: number;

  constructor(options: SimpleStoreRedisOptions) {
    this.keyPrefix = options.keyPrefix;
    this.ttlSeconds = options.ttlSeconds;
  }

  async get(key: string): Promise<V | undefined> {
    try {
      const value = await getRedis().get(this.keyPrefix + key);
      if (!value) return undefined;
      return JSON.parse(value) as V;
    } catch (err) {
      console.error("[redis-store] get error:", err);
      return undefined;
    }
  }

  async set(key: string, value: V): Promise<void> {
    try {
      await getRedis().set(this.keyPrefix + key, JSON.stringify(value), "EX", this.ttlSeconds);
    } catch (err) {
      console.error("[redis-store] set error:", err);
    }
  }

  async del(key: string): Promise<void> {
    try {
      await getRedis().del(this.keyPrefix + key);
    } catch (err) {
      console.error("[redis-store] del error:", err);
    }
  }
}
