package com.ruoyi.jarvis.service.impl;

import com.ruoyi.jarvis.domain.Comment;
import com.ruoyi.jarvis.domain.dto.CommentApiStatistics;
import com.ruoyi.jarvis.domain.dto.CommentStatistics;
import com.ruoyi.jarvis.domain.dto.CommentCallHistory;
import com.ruoyi.jarvis.mapper.CommentMapper;
import com.ruoyi.jarvis.service.ICommentService;
import com.alibaba.fastjson2.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 评论管理 Service 实现
 */
@Service
public class CommentServiceImpl implements ICommentService {

    private static final Logger log = LoggerFactory.getLogger(CommentServiceImpl.class);

    private static final String PRODUCT_TYPE_MAP_PREFIX = "product_type_map";
    private static final String PRODUCT_TYPE_MAP_PREFIX_TB = "product_type_map_tb";
    private static final String API_CALL_STAT_PREFIX = "comment:api:stat:";
    private static final String API_CALL_TODAY_PREFIX = "comment:api:today:";
    private static final String API_CALL_HISTORY_KEY = "comment:api:history:list";
    private static final int MAX_HISTORY_SIZE = 1000; // 最多保留1000条历史记录

    @Autowired
    private CommentMapper commentMapper;

    @Autowired(required = false)
    private com.ruoyi.jarvis.mapper.TaobaoCommentMapper taobaoCommentMapper;

    @Autowired(required = false)
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public List<Comment> selectCommentList(Comment comment) {
        List<Comment> list = commentMapper.selectCommentList(comment);
        // 填充Redis映射的产品类型信息
        if (stringRedisTemplate != null) {
            Map<String, String> jdMap = getJdProductTypeMap();
            for (Comment c : list) {
                // 查找对应的产品类型
                String productId = c.getProductId();
                if (jdMap != null) {
                    for (Map.Entry<String, String> entry : jdMap.entrySet()) {
                        if (entry.getValue().equals(productId)) {
                            c.setProductType(entry.getKey());
                            c.setMappedProductId(productId);
                            break;
                        }
                    }
                }
            }
        }
        return list;
    }

    @Override
    public Comment selectCommentById(Long id) {
        Comment comment = commentMapper.selectCommentById(id);
        if (comment != null && stringRedisTemplate != null) {
            Map<String, String> jdMap = getJdProductTypeMap();
            if (jdMap != null) {
                String productId = comment.getProductId();
                for (Map.Entry<String, String> entry : jdMap.entrySet()) {
                    if (entry.getValue().equals(productId)) {
                        comment.setProductType(entry.getKey());
                        comment.setMappedProductId(productId);
                        break;
                    }
                }
            }
        }
        return comment;
    }

    @Override
    public int updateCommentIsUse(Comment comment) {
        return commentMapper.updateCommentIsUse(comment);
    }

    @Override
    public int deleteCommentByIds(Long[] ids) {
        return commentMapper.deleteCommentByIds(ids);
    }

    @Override
    public int resetCommentIsUseByProductId(String productId) {
        return commentMapper.resetCommentIsUseByProductId(productId);
    }

    @Override
    public List<CommentStatistics> getCommentStatistics(String source) {
        List<CommentStatistics> statisticsList = new ArrayList<>();
        
        Map<String, String> productTypeMap = null;
        if ("jd".equals(source) || source == null) {
            productTypeMap = getJdProductTypeMap();
        } else if ("tb".equals(source)) {
            productTypeMap = getTbProductTypeMap();
        }

        if (productTypeMap == null || productTypeMap.isEmpty()) {
            return statisticsList;
        }

        for (Map.Entry<String, String> entry : productTypeMap.entrySet()) {
            String productType = entry.getKey();
            String productId = entry.getValue();

            CommentStatistics stats = new CommentStatistics();
            stats.setSource("jd".equals(source) ? "京东评论" : "淘宝评论");
            stats.setProductType(productType);
            stats.setProductId(productId);

            // 查询评论统计
            Map<String, Object> statMap = null;
            if ("jd".equals(source) || source == null) {
                statMap = commentMapper.selectCommentStatisticsByProductId(productId);
            } else if ("tb".equals(source) && taobaoCommentMapper != null) {
                statMap = taobaoCommentMapper.selectTaobaoCommentStatisticsByProductId(productId);
            }
            
            if (statMap != null) {
                stats.setTotalCount(toLong(statMap.get("totalCount")));
                stats.setAvailableCount(toLong(statMap.get("availableCount")));
                stats.setUsedCount(toLong(statMap.get("usedCount")));
                // 设置最后一条评论的创建时间
                Object lastUpdateTime = statMap.get("lastCommentUpdateTime");
                if (lastUpdateTime != null) {
                    if (lastUpdateTime instanceof Date) {
                        stats.setLastCommentUpdateTime((Date) lastUpdateTime);
                    } else if (lastUpdateTime instanceof java.sql.Timestamp) {
                        stats.setLastCommentUpdateTime(new Date(((java.sql.Timestamp) lastUpdateTime).getTime()));
                    }
                }
            }

            // 获取接口调用统计
            if (stringRedisTemplate != null) {
                String todayKey = API_CALL_TODAY_PREFIX + source + ":" + productType + ":" + getTodayDate();
                String todayCount = stringRedisTemplate.opsForValue().get(todayKey);
                stats.setTodayCallCount(todayCount != null ? Long.parseLong(todayCount) : 0L);

                // 获取总调用次数（从Redis中统计）
                String statKey = API_CALL_STAT_PREFIX + source + ":" + productType;
                String totalCount = stringRedisTemplate.opsForValue().get(statKey);
                stats.setApiCallCount(totalCount != null ? Long.parseLong(totalCount) : 0L);
            }

            statisticsList.add(stats);
        }

        return statisticsList;
    }

    @Override
    public void recordApiCall(String apiType, String productType, boolean success) {
        if (stringRedisTemplate == null) {
            return;
        }

        try {
            String today = getTodayDate();
            String todayKey = API_CALL_TODAY_PREFIX + apiType + ":" + productType + ":" + today;
            stringRedisTemplate.opsForValue().increment(todayKey);
            stringRedisTemplate.expire(todayKey, 7, TimeUnit.DAYS); // 保留7天

            String statKey = API_CALL_STAT_PREFIX + apiType + ":" + productType;
            stringRedisTemplate.opsForValue().increment(statKey);

            // 记录成功/失败统计
            String successKey = API_CALL_STAT_PREFIX + apiType + ":" + productType + ":success";
            String failKey = API_CALL_STAT_PREFIX + apiType + ":" + productType + ":fail";
            if (success) {
                stringRedisTemplate.opsForValue().increment(successKey);
            } else {
                stringRedisTemplate.opsForValue().increment(failKey);
            }
        } catch (Exception e) {
            log.error("记录接口调用统计失败", e);
        }
    }

    @Override
    public List<CommentApiStatistics> getApiStatistics(String apiType, String productType, String startDate, String endDate) {
        List<CommentApiStatistics> statisticsList = new ArrayList<>();
        
        if (stringRedisTemplate == null) {
            return statisticsList;
        }

        try {
            // 如果指定了产品类型，只查询该类型的统计
            if (productType != null && !productType.isEmpty()) {
                CommentApiStatistics stats = new CommentApiStatistics();
                stats.setApiType(apiType);
                stats.setProductType(productType);
                
                String statKey = API_CALL_STAT_PREFIX + apiType + ":" + productType;
                String totalCount = stringRedisTemplate.opsForValue().get(statKey);
                stats.setCallCount(totalCount != null ? Long.parseLong(totalCount) : 0L);

                String successKey = statKey + ":success";
                String successCount = stringRedisTemplate.opsForValue().get(successKey);
                stats.setSuccessCount(successCount != null ? Long.parseLong(successCount) : 0L);

                String failKey = statKey + ":fail";
                String failCount = stringRedisTemplate.opsForValue().get(failKey);
                stats.setFailCount(failCount != null ? Long.parseLong(failCount) : 0L);

                statisticsList.add(stats);
            } else {
                // 查询所有产品类型的统计
                Map<String, String> productTypeMap = "jd".equals(apiType) ? getJdProductTypeMap() : getTbProductTypeMap();
                if (productTypeMap != null) {
                    for (String pt : productTypeMap.keySet()) {
                        CommentApiStatistics stats = new CommentApiStatistics();
                        stats.setApiType(apiType);
                        stats.setProductType(pt);
                        
                        String statKey = API_CALL_STAT_PREFIX + apiType + ":" + pt;
                        String totalCount = stringRedisTemplate.opsForValue().get(statKey);
                        stats.setCallCount(totalCount != null ? Long.parseLong(totalCount) : 0L);

                        String successKey = statKey + ":success";
                        String successCount = stringRedisTemplate.opsForValue().get(successKey);
                        stats.setSuccessCount(successCount != null ? Long.parseLong(successCount) : 0L);

                        String failKey = statKey + ":fail";
                        String failCount = stringRedisTemplate.opsForValue().get(failKey);
                        stats.setFailCount(failCount != null ? Long.parseLong(failCount) : 0L);

                        statisticsList.add(stats);
                    }
                }
            }
        } catch (Exception e) {
            log.error("获取接口调用统计失败", e);
        }

        return statisticsList;
    }

    @Override
    public Map<String, String> getJdProductTypeMap() {
        if (stringRedisTemplate == null) {
            return new HashMap<>();
        }
        try {
            Map<Object, Object> rawMap = stringRedisTemplate.opsForHash().entries(PRODUCT_TYPE_MAP_PREFIX);
            Map<String, String> result = new LinkedHashMap<>();
            for (Map.Entry<Object, Object> entry : rawMap.entrySet()) {
                result.put(entry.getKey().toString(), entry.getValue().toString());
            }
            return result;
        } catch (Exception e) {
            log.error("获取京东产品类型映射失败", e);
            return new HashMap<>();
        }
    }

    @Override
    public Map<String, String> getTbProductTypeMap() {
        if (stringRedisTemplate == null) {
            return new HashMap<>();
        }
        try {
            Map<Object, Object> rawMap = stringRedisTemplate.opsForHash().entries(PRODUCT_TYPE_MAP_PREFIX_TB);
            Map<String, String> result = new LinkedHashMap<>();
            for (Map.Entry<Object, Object> entry : rawMap.entrySet()) {
                result.put(entry.getKey().toString(), entry.getValue().toString());
            }
            return result;
        } catch (Exception e) {
            log.error("获取淘宝产品类型映射失败", e);
            return new HashMap<>();
        }
    }

    private String getTodayDate() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        return sdf.format(new Date());
    }

    @Override
    public void recordApiCallHistory(String productType, String ip) {
        if (stringRedisTemplate == null) {
            return;
        }

        try {
            CommentCallHistory history = new CommentCallHistory();
            history.setProductType(productType);
            history.setIp(ip);
            history.setCreateTime(new Date());
            
            String historyJson = JSON.toJSONString(history);
            
            // 使用List存储历史记录，从左侧推入
            stringRedisTemplate.opsForList().leftPush(API_CALL_HISTORY_KEY, historyJson);
            
            // 限制列表大小，只保留最近MAX_HISTORY_SIZE条
            stringRedisTemplate.opsForList().trim(API_CALL_HISTORY_KEY, 0, MAX_HISTORY_SIZE - 1);
        } catch (Exception e) {
            log.error("记录接口调用历史失败", e);
        }
    }

    @Override
    public List<CommentCallHistory> getApiCallHistory(int pageNum, int pageSize) {
        List<CommentCallHistory> historyList = new ArrayList<>();
        
        if (stringRedisTemplate == null) {
            return historyList;
        }

        try {
            long start = (pageNum - 1) * pageSize;
            long end = start + pageSize - 1;
            
            List<String> jsonList = stringRedisTemplate.opsForList().range(API_CALL_HISTORY_KEY, start, end);
            if (jsonList != null) {
                for (String json : jsonList) {
                    try {
                        CommentCallHistory history = JSON.parseObject(json, CommentCallHistory.class);
                        historyList.add(history);
                    } catch (Exception e) {
                        log.warn("解析历史记录失败: " + json, e);
                    }
                }
            }
        } catch (Exception e) {
            log.error("获取接口调用历史失败", e);
        }

        return historyList;
    }

    @Override
    public Map<String, Long> getUsageStatistics() {
        Map<String, Long> statistics = new HashMap<>();
        statistics.put("today", 0L);
        statistics.put("last7Days", 0L);
        statistics.put("last30Days", 0L);
        statistics.put("total", 0L);

        if (stringRedisTemplate == null) {
            return statistics;
        }

        try {
            String today = getTodayDate();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            Date todayDate = sdf.parse(today);
            Calendar calendar = Calendar.getInstance();

            // 统计今天
            long todayCount = 0;
            String todayPattern = API_CALL_TODAY_PREFIX + "jd:*:" + today;
            Set<String> todayKeys = stringRedisTemplate.keys(todayPattern);
            if (todayKeys != null) {
                for (String key : todayKeys) {
                    String count = stringRedisTemplate.opsForValue().get(key);
                    if (count != null) {
                        todayCount += Long.parseLong(count);
                    }
                }
            }
            statistics.put("today", todayCount);

            // 统计近7天
            long last7DaysCount = 0;
            calendar.setTime(todayDate);
            for (int i = 0; i < 7; i++) {
                String dateStr = sdf.format(calendar.getTime());
                String pattern = API_CALL_TODAY_PREFIX + "jd:*:" + dateStr;
                Set<String> keys = stringRedisTemplate.keys(pattern);
                if (keys != null) {
                    for (String key : keys) {
                        String count = stringRedisTemplate.opsForValue().get(key);
                        if (count != null) {
                            last7DaysCount += Long.parseLong(count);
                        }
                    }
                }
                calendar.add(Calendar.DAY_OF_MONTH, -1);
            }
            statistics.put("last7Days", last7DaysCount);

            // 统计近30天
            long last30DaysCount = 0;
            calendar.setTime(todayDate);
            for (int i = 0; i < 30; i++) {
                String dateStr = sdf.format(calendar.getTime());
                String pattern = API_CALL_TODAY_PREFIX + "jd:*:" + dateStr;
                Set<String> keys = stringRedisTemplate.keys(pattern);
                if (keys != null) {
                    for (String key : keys) {
                        String count = stringRedisTemplate.opsForValue().get(key);
                        if (count != null) {
                            last30DaysCount += Long.parseLong(count);
                        }
                    }
                }
                calendar.add(Calendar.DAY_OF_MONTH, -1);
            }
            statistics.put("last30Days", last30DaysCount);

            // 统计累计（从统计key获取）
            long totalCount = 0;
            String totalPattern = API_CALL_STAT_PREFIX + "jd:*";
            Set<String> totalKeys = stringRedisTemplate.keys(totalPattern);
            if (totalKeys != null) {
                for (String key : totalKeys) {
                    // 排除success和fail后缀的key
                    if (!key.endsWith(":success") && !key.endsWith(":fail")) {
                        String count = stringRedisTemplate.opsForValue().get(key);
                        if (count != null) {
                            totalCount += Long.parseLong(count);
                        }
                    }
                }
            }
            statistics.put("total", totalCount);

        } catch (Exception e) {
            log.error("获取使用统计失败", e);
        }

        return statistics;
    }

    /**
     * 将 Map 中的统计值安全转为 long，null 或不存在时返回 0
     */
    private static long toLong(Object value) {
        if (value == null) {
            return 0L;
        }
        if (value instanceof Number) {
            return ((Number) value).longValue();
        }
        try {
            return Long.parseLong(value.toString());
        } catch (NumberFormatException e) {
            return 0L;
        }
    }
}

