package shop.alien.store.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import shop.alien.entity.store.StoreTrackEvent;
import shop.alien.store.config.BaseRedisService;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 埋点事件消费服务
 * 定时从Redis List批量消费数据并写入数据库
 *
 * @author system
 * @since 2026-01-14
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class TrackEventConsumer {

    private final BaseRedisService baseRedisService;
    private final TrackEventService trackEventService;
    private final ObjectMapper objectMapper;
    
    private static final String REDIS_QUEUE_KEY = "track:event:queue";
    private static final String CONSUMER_LOCK_KEY = "track:event:consumer:lock";

    /**
     * 定时消费埋点数据
     * 每10秒执行一次
     */
    @Scheduled(cron = "0/10 * * * * ?")
    public void consumeTrackEvents() {
        // 获取分布式锁
        String lockId = baseRedisService.lock(CONSUMER_LOCK_KEY, 5000, 1000);
        if (lockId == null) {
            log.debug("获取消费锁失败，跳过本次消费");
            return;
        }

        try {
            // 批量从Redis List取出数据
            List<String> eventList = baseRedisService.popBatchFromList(REDIS_QUEUE_KEY);
            
            if (eventList == null || eventList.isEmpty()) {
                return;
            }

            log.debug("从Redis List取出{}条埋点数据", eventList.size());

            // 转换为实体对象
            List<StoreTrackEvent> events = eventList.stream()
                    .map(json -> {
                        try {
                            return objectMapper.readValue(json, StoreTrackEvent.class);
                        } catch (Exception e) {
                            log.error("解析埋点数据JSON失败: {}", json, e);
                            return null;
                        }
                    })
                    .filter(event -> event != null)
                    .collect(Collectors.toList());

            if (events.isEmpty()) {
                return;
            }

            // 批量保存到数据库
            trackEventService.batchSaveTrackEvents(events);
            
            log.info("成功消费{}条埋点数据", events.size());
        } catch (Exception e) {
            log.error("消费埋点数据失败", e);
        } finally {
            // 释放锁
            baseRedisService.unlock(CONSUMER_LOCK_KEY, lockId);
        }
    }
}