import { logger } from '@goodgo/logger';

import { getRedisClient } from '../../config/redis.config';

/**
 * EN: Service for caching data (Redis wrapper)
 * VI: Service cho việc caching dữ liệu (Redis wrapper)
 */
export class CacheService {
    /**
     * EN: Get value from cache
     * VI: Lấy giá trị từ cache
     */
    async get<T>(key: string): Promise<T | null> {
        try {
            const data = await getRedisClient().get(key);
            if (!data) return null;
            return JSON.parse(data) as T;
        } catch (error) {
            logger.error('Cache get error', { key, error });
            return null;
        }
    }

    /**
     * EN: Set value in cache
     * VI: Lưu giá trị vào cache
     */
    async set(key: string, value: any, ttlSeconds?: number): Promise<void> {
        try {
            const stringValue = JSON.stringify(value);
            if (ttlSeconds) {
                await getRedisClient().setex(key, ttlSeconds, stringValue);
            } else {
                await getRedisClient().set(key, stringValue);
            }
        } catch (error) {
            logger.error('Cache set error', { key, error });
        }
    }

    /**
     * EN: Get from cache or fetch from source if missing
     * VI: Lấy từ cache hoặc lấy từ nguồn nếu không có
     */
    async getOrSet<T>(
        key: string,
        fetchFn: () => Promise<T>,
        ttlSeconds: number = 300
    ): Promise<T> {
        const cached = await this.get<T>(key);
        if (cached) return cached;

        const data = await fetchFn();
        await this.set(key, data, ttlSeconds);
        return data;
    }

    /**
     * EN: Delete from cache
     * VI: Xóa khỏi cache
     */
    async del(key: string): Promise<void> {
        try {
            await getRedisClient().del(key);
        } catch (error) {
            logger.error('Cache del error', { key, error });
        }
    }
}

export const cacheService = new CacheService();
