package com.tasteby.service;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.util.Set;

@Service
public class CacheService {

    private static final Logger log = LoggerFactory.getLogger(CacheService.class);
    private static final String PREFIX = "tasteby:";

    private final StringRedisTemplate redis;
    private final ObjectMapper mapper;
    private final Duration ttl;
    private boolean disabled = false;

    public CacheService(StringRedisTemplate redis, ObjectMapper mapper,
                        @Value("${app.cache.ttl-seconds:600}") int ttlSeconds) {
        this.redis = redis;
        this.mapper = mapper;
        this.ttl = Duration.ofSeconds(ttlSeconds);
        try {
            redis.getConnectionFactory().getConnection().ping();
            log.info("Redis connected");
        } catch (Exception e) {
            log.warn("Redis unavailable ({}), caching disabled", e.getMessage());
            disabled = true;
        }
    }

    public String makeKey(String... parts) {
        return PREFIX + String.join(":", parts);
    }

    public <T> T get(String key, Class<T> type) {
        if (disabled) return null;
        try {
            String val = redis.opsForValue().get(key);
            if (val != null) {
                return mapper.readValue(val, type);
            }
        } catch (Exception e) {
            log.debug("Cache get error: {}", e.getMessage());
        }
        return null;
    }

    public String getRaw(String key) {
        if (disabled) return null;
        try {
            return redis.opsForValue().get(key);
        } catch (Exception e) {
            log.debug("Cache get error: {}", e.getMessage());
            return null;
        }
    }

    public void set(String key, Object value) {
        if (disabled) return;
        try {
            String json = mapper.writeValueAsString(value);
            redis.opsForValue().set(key, json, ttl);
        } catch (JsonProcessingException e) {
            log.debug("Cache set error: {}", e.getMessage());
        }
    }

    public void flush() {
        if (disabled) return;
        try {
            Set<String> keys = redis.keys(PREFIX + "*");
            if (keys != null && !keys.isEmpty()) {
                redis.delete(keys);
            }
            log.info("Cache flushed");
        } catch (Exception e) {
            log.debug("Cache flush error: {}", e.getMessage());
        }
    }
}
