package com.smyhub.infogenie.infogeniebackendjava.service;

import com.smyhub.infogenie.infogeniebackendjava.config.AppProperties;
import com.smyhub.infogenie.infogeniebackendjava.dto.response.FeatureClickResponse;
import com.smyhub.infogenie.infogeniebackendjava.entity.SiteFeatureCardClick;
import com.smyhub.infogenie.infogeniebackendjava.repository.SiteFeatureCardClickRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Duration;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * Manages feature card click counts with Redis cache-aside (optional).
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class FeatureClickService {

    private static final String KEY_CLICKS_PREFIX = "site:feature-clicks:";

    private final SiteFeatureCardClickRepository clickRepo;
    private final RedisTemplate<String, Object> redisTemplate;
    private final AppProperties appProperties;

    @SuppressWarnings("unchecked")
    public FeatureClickResponse getClicksForSection(String section) {
        String cacheKey = cacheKey(KEY_CLICKS_PREFIX + section);
        if (appProperties.isRedisEnabled()) {
            try {
                Object cached = redisTemplate.opsForValue().get(cacheKey);
                if (cached instanceof Map<?, ?> map) {
                    FeatureClickResponse resp = new FeatureClickResponse();
                    resp.setSection(section);
                    resp.setCounts((Map<String, Long>) cached);
                    return resp;
                }
            } catch (Exception e) {
                log.warn("Redis read failed for {}: {}", cacheKey, e.getMessage());
            }
        }

        List<SiteFeatureCardClick> rows = clickRepo.findBySection(section);
        Map<String, Long> counts = rows.stream()
                .collect(Collectors.toMap(
                        SiteFeatureCardClick::getItemId,
                        SiteFeatureCardClick::getClickCount));

        cacheWrite(cacheKey, counts);

        FeatureClickResponse resp = new FeatureClickResponse();
        resp.setSection(section);
        resp.setCounts(counts);
        return resp;
    }

    @Transactional
    public FeatureClickResponse increment(String section, String itemId) {
        clickRepo.upsertIncrement(section, itemId);
        evict(cacheKey(KEY_CLICKS_PREFIX + section));

        SiteFeatureCardClick.ClickId id = new SiteFeatureCardClick.ClickId();
        id.setSection(section);
        id.setItemId(itemId);
        long count = clickRepo.findById(id)
                .map(SiteFeatureCardClick::getClickCount)
                .orElse(0L);

        FeatureClickResponse resp = new FeatureClickResponse();
        resp.setSection(section);
        resp.setItemId(itemId);
        resp.setCount(count);
        return resp;
    }

    private String cacheKey(String suffix) {
        return appProperties.getRedisKeyPrefix() + suffix;
    }

    private void cacheWrite(String key, Object value) {
        if (!appProperties.isRedisEnabled()) return;
        try {
            redisTemplate.opsForValue().set(key, value,
                    Duration.ofSeconds(appProperties.getRedisSiteTtl()));
        } catch (Exception e) {
            log.warn("Redis write failed for {}: {}", key, e.getMessage());
        }
    }

    private void evict(String key) {
        if (!appProperties.isRedisEnabled()) return;
        try {
            redisTemplate.delete(key);
        } catch (Exception e) {
            log.warn("Redis evict failed for {}: {}", key, e.getMessage());
        }
    }
}
