package com.nisemoe.nise.service

import org.slf4j.LoggerFactory
import org.springframework.data.redis.core.RedisTemplate
import org.springframework.stereotype.Service
import java.time.Duration
import java.time.LocalDateTime

@Service
class CacheService(
    private val redisTemplate: RedisTemplate<Any, Any>
) {

    private val logger = LoggerFactory.getLogger(javaClass)

    fun setVariable(key: String, value: Any, ttl: Duration = Duration.ofDays(1)) {
        redisTemplate.opsForValue().set(key, value, ttl)
    }

    fun deleteVariable(key: String) {
        val deleted = redisTemplate.delete(key)
        if(!deleted)
            this.logger.error("Failed to delete key: $key")
    }

    fun <T> getVariable(key: String, returnType: Class<T>): T? {
        val result = try {
            redisTemplate.opsForValue().get(key)
        } catch (e: Exception) {
            this.logger.error("Error while getting variable from cache: $e")
            this.deleteVariable(key)
            null
        }

        if(result == null) {
            this.logger.debug("No value found for key: $key")
            return null
        }

        if (LocalDateTime::class.java.isAssignableFrom(returnType) && result is ArrayList<*>) {
            @Suppress("UNCHECKED_CAST")
            return LocalDateTime.of(
                result[0] as Int,
                result[1] as Int,
                result[2] as Int,
                result[3] as Int,
                result[4] as Int,
                result[5] as Int
            ) as T
        }

        if (returnType.isInstance(result))
            return returnType.cast(result)

        this.logger.error("Failed to deserialize cache entry.")
        this.logger.error("Expected type ${returnType.simpleName}, got ${result::class.simpleName}")
        this.deleteVariable(key)
        return null
    }

}