package org.dromara.mp.service.impl;

import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.datacube.*;
import org.dromara.mp.service.WxMpStatisticsService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * 微信公众号数据统计服务实现类
 *
 * @author pengles
 */
@Service
public class WxMpStatisticsServiceImpl implements WxMpStatisticsService {

    private static final Logger logger = LoggerFactory.getLogger(WxMpStatisticsServiceImpl.class);
    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    @Autowired
    private WxMpService wxMpService;

    @Override
    public List<Map<String, Object>> getUserSummary(LocalDate beginDate, LocalDate endDate) {
        try {
            List<WxDataCubeUserSummary> summaries = wxMpService.getDataCubeService()
                    .getUserSummary(Date.from(beginDate.atStartOfDay(ZoneId.systemDefault()).toInstant()), Date.from(endDate.atStartOfDay(ZoneId.systemDefault()).toInstant()));

            List<Map<String, Object>> result = new ArrayList<>();
            for (WxDataCubeUserSummary summary : summaries) {
                Map<String, Object> data = new HashMap<>();
                data.put("refDate", summary.getRefDate());
                data.put("userSource", summary.getUserSource());
                data.put("newUser", summary.getNewUser());
                data.put("cancelUser", summary.getCancelUser());
                result.add(data);
            }

            logger.info("获取用户增减数据成功: {} - {}", beginDate, endDate);
            return result;
        } catch (WxErrorException e) {
            logger.error("获取用户增减数据失败: {}", e.getMessage(), e);
            return new ArrayList<>();
        }
    }

    @Override
    public List<Map<String, Object>> getUserCumulate(LocalDate beginDate, LocalDate endDate) {
        try {
            List<WxDataCubeUserCumulate> cumulates = wxMpService.getDataCubeService()
                    .getUserCumulate(Date.from(beginDate.atStartOfDay(ZoneId.systemDefault()).toInstant()), Date.from(endDate.atStartOfDay(ZoneId.systemDefault()).toInstant()));

            List<Map<String, Object>> result = new ArrayList<>();
            for (WxDataCubeUserCumulate cumulate : cumulates) {
                Map<String, Object> data = new HashMap<>();
                data.put("refDate", cumulate.getRefDate());
                data.put("cumulateUser", cumulate.getCumulateUser());
                result.add(data);
            }

            logger.info("获取用户累计数据成功: {} - {}", beginDate, endDate);
            return result;
        } catch (WxErrorException e) {
            logger.error("获取用户累计数据失败: {}", e.getMessage(), e);
            return new ArrayList<>();
        }
    }

    @Override
    public List<Map<String, Object>> getArticleSummary(LocalDate beginDate, LocalDate endDate) {
        try {
            List<WxDataCubeArticleResult> summaries = wxMpService.getDataCubeService()
                    .getArticleSummary(Date.from(beginDate.atStartOfDay(ZoneId.systemDefault()).toInstant()), Date.from(endDate.atStartOfDay(ZoneId.systemDefault()).toInstant()));

            List<Map<String, Object>> result = new ArrayList<>();
            for (WxDataCubeArticleResult summary : summaries) {
                Map<String, Object> data = new HashMap<>();
                data.put("refDate", summary.getRefDate());
                data.put("msgid", summary.getMsgId());
                data.put("title", summary.getTitle());
                data.put("intPageReadUser", summary.getIntPageReadUser());
                data.put("intPageReadCount", summary.getIntPageReadCount());
                data.put("oriPageReadUser", summary.getOriPageReadUser());
                data.put("oriPageReadCount", summary.getOriPageReadCount());
                data.put("shareUser", summary.getShareUser());
                data.put("shareCount", summary.getShareCount());
                data.put("addToFavUser", summary.getAddToFavUser());
                data.put("addToFavCount", summary.getAddToFavCount());
                result.add(data);
            }

            logger.info("获取图文群发每日数据成功: {} - {}", beginDate, endDate);
            return result;
        } catch (WxErrorException e) {
            logger.error("获取图文群发每日数据失败: {}", e.getMessage(), e);
            return new ArrayList<>();
        }
    }

    @Override
    public List<Map<String, Object>> getArticleTotal(LocalDate beginDate, LocalDate endDate) {
        try {
            List<WxDataCubeArticleTotal> totals = wxMpService.getDataCubeService()
                    .getArticleTotal(Date.from(beginDate.atStartOfDay(ZoneId.systemDefault()).toInstant()), Date.from(endDate.atStartOfDay(ZoneId.systemDefault()).toInstant()));

            List<Map<String, Object>> result = new ArrayList<>();
            for (WxDataCubeArticleTotal total : totals) {
                Map<String, Object> data = new HashMap<>();
                data.put("refDate", total.getRefDate());
                data.put("msgid", total.getMsgId());
                data.put("title", total.getTitle());
                data.put("details", total.getDetails());
                result.add(data);
            }

            logger.info("获取图文群发总数据成功: {} - {}", beginDate, endDate);
            return result;
        } catch (WxErrorException e) {
            logger.error("获取图文群发总数据失败: {}", e.getMessage(), e);
            return new ArrayList<>();
        }
    }

    @Override
    public List<Map<String, Object>> getUserRead(LocalDate beginDate, LocalDate endDate) {
        try {
            List<WxDataCubeArticleResult> reads = wxMpService.getDataCubeService()
                    .getUserRead(Date.from(beginDate.atStartOfDay(ZoneId.systemDefault()).toInstant()), Date.from(endDate.atStartOfDay(ZoneId.systemDefault()).toInstant()));


            List<Map<String, Object>> result = new ArrayList<>();
            for (WxDataCubeArticleResult read : reads) {
                Map<String, Object> data = new HashMap<>();
                data.put("refDate", read.getRefDate());
                data.put("userSource", read.getUserSource());
                data.put("intPageReadUser", read.getIntPageReadUser());
                data.put("intPageReadCount", read.getIntPageReadCount());
                data.put("oriPageReadUser", read.getOriPageReadUser());
                data.put("oriPageReadCount", read.getOriPageReadCount());
                data.put("shareUser", read.getShareUser());
                data.put("shareCount", read.getShareCount());
                data.put("addToFavUser", read.getAddToFavUser());
                data.put("addToFavCount", read.getAddToFavCount());
                result.add(data);
            }

            logger.info("获取图文统计数据成功: {} - {}", beginDate, endDate);
            return result;
        } catch (WxErrorException e) {
            logger.error("获取图文统计数据失败: {}", e.getMessage(), e);
            return new ArrayList<>();
        }
    }

    @Override
    public List<Map<String, Object>> getUserReadHour(LocalDate beginDate, LocalDate endDate) {
        try {
            List<WxDataCubeArticleResult> reads = wxMpService.getDataCubeService()
                    .getUserReadHour(Date.from(beginDate.atStartOfDay(ZoneId.systemDefault()).toInstant()), Date.from(endDate.atStartOfDay(ZoneId.systemDefault()).toInstant()));


            List<Map<String, Object>> result = new ArrayList<>();
            for (WxDataCubeArticleResult read : reads) {
                Map<String, Object> data = new HashMap<>();
                data.put("refDate", read.getRefDate());
                data.put("refHour", read.getRefHour());
                data.put("userSource", read.getUserSource());
                data.put("intPageReadUser", read.getIntPageReadUser());
                data.put("intPageReadCount", read.getIntPageReadCount());
                data.put("oriPageReadUser", read.getOriPageReadUser());
                data.put("oriPageReadCount", read.getOriPageReadCount());
                data.put("shareUser", read.getShareUser());
                data.put("shareCount", read.getShareCount());
                data.put("addToFavUser", read.getAddToFavUser());
                data.put("addToFavCount", read.getAddToFavCount());
                result.add(data);
            }

            logger.info("获取图文统计分时数据成功: {} - {}", beginDate, endDate);
            return result;
        } catch (WxErrorException e) {
            logger.error("获取图文统计分时数据失败: {}", e.getMessage(), e);
            return new ArrayList<>();
        }
    }

    @Override
    public List<Map<String, Object>> getUserShare(LocalDate beginDate, LocalDate endDate) {
        try {
            List<WxDataCubeArticleResult> shares = wxMpService.getDataCubeService()
                    .getUserShare(Date.from(beginDate.atStartOfDay(ZoneId.systemDefault()).toInstant()), Date.from(endDate.atStartOfDay(ZoneId.systemDefault()).toInstant()));

            List<Map<String, Object>> result = new ArrayList<>();
            for (WxDataCubeArticleResult share : shares) {
                Map<String, Object> data = new HashMap<>();
                data.put("refDate", share.getRefDate());
                data.put("shareScene", share.getShareScene());
                data.put("shareUser", share.getShareUser());
                data.put("shareCount", share.getShareCount());
                result.add(data);
            }

            logger.info("获取图文分享转发数据成功: {} - {}", beginDate, endDate);
            return result;
        } catch (WxErrorException e) {
            logger.error("获取图文分享转发数据失败: {}", e.getMessage(), e);
            return new ArrayList<>();
        }
    }

    @Override
    public List<Map<String, Object>> getUserShareHour(LocalDate beginDate, LocalDate endDate) {
        try {
            List<WxDataCubeArticleResult> shares = wxMpService.getDataCubeService()
                    .getUserShareHour(Date.from(beginDate.atStartOfDay(ZoneId.systemDefault()).toInstant()), Date.from(endDate.atStartOfDay(ZoneId.systemDefault()).toInstant()));

            List<Map<String, Object>> result = new ArrayList<>();
            for (WxDataCubeArticleResult share : shares) {
                Map<String, Object> data = new HashMap<>();
                data.put("refDate", share.getRefDate());
                data.put("refHour", share.getRefHour());
                data.put("shareScene", share.getShareScene());
                data.put("shareUser", share.getShareUser());
                data.put("shareCount", share.getShareCount());
                result.add(data);
            }

            logger.info("获取图文分享转发分时数据成功: {} - {}", beginDate, endDate);
            return result;
        } catch (WxErrorException e) {
            logger.error("获取图文分享转发分时数据失败: {}", e.getMessage(), e);
            return new ArrayList<>();
        }
    }

    @Override
    public List<Map<String, Object>> getUpstreamMsg(LocalDate beginDate, LocalDate endDate) {
        try {
            List<WxDataCubeMsgResult> msgs = wxMpService.getDataCubeService()
                    .getUpstreamMsg(Date.from(beginDate.atStartOfDay(ZoneId.systemDefault()).toInstant()), Date.from(endDate.atStartOfDay(ZoneId.systemDefault()).toInstant()));

            List<Map<String, Object>> result = new ArrayList<>();
            for (WxDataCubeMsgResult msg : msgs) {
                Map<String, Object> data = new HashMap<>();
                data.put("refDate", msg.getRefDate());
                data.put("msgType", msg.getMsgType());
                data.put("msgUser", msg.getMsgUser());
                data.put("msgCount", msg.getMsgCount());
                result.add(data);
            }

            logger.info("获取消息发送概况数据成功: {} - {}", beginDate, endDate);
            return result;
        } catch (WxErrorException e) {
            logger.error("获取消息发送概况数据失败: {}", e.getMessage(), e);
            return new ArrayList<>();
        }
    }

    @Override
    public List<Map<String, Object>> getUpstreamMsgHour(LocalDate beginDate, LocalDate endDate) {
        try {
            List<WxDataCubeMsgResult> msgs = wxMpService.getDataCubeService()
                    .getUpstreamMsgHour(Date.from(beginDate.atStartOfDay(ZoneId.systemDefault()).toInstant()), Date.from(endDate.atStartOfDay(ZoneId.systemDefault()).toInstant()));

            List<Map<String, Object>> result = new ArrayList<>();
            for (WxDataCubeMsgResult msg : msgs) {
                Map<String, Object> data = new HashMap<>();
                data.put("refDate", msg.getRefDate());
                data.put("refHour", msg.getRefHour());
                data.put("msgType", msg.getMsgType());
                data.put("msgUser", msg.getMsgUser());
                data.put("msgCount", msg.getMsgCount());
                result.add(data);
            }

            logger.info("获取消息分送分时数据成功: {} - {}", beginDate, endDate);
            return result;
        } catch (WxErrorException e) {
            logger.error("获取消息分送分时数据失败: {}", e.getMessage(), e);
            return new ArrayList<>();
        }
    }

    @Override
    public List<Map<String, Object>> getUpstreamMsgWeek(LocalDate beginDate, LocalDate endDate) {
        try {
            List<WxDataCubeMsgResult> msgs = wxMpService.getDataCubeService()
                    .getUpstreamMsgWeek(Date.from(beginDate.atStartOfDay(ZoneId.systemDefault()).toInstant()), Date.from(endDate.atStartOfDay(ZoneId.systemDefault()).toInstant()));

            List<Map<String, Object>> result = new ArrayList<>();
            for (WxDataCubeMsgResult msg : msgs) {
                Map<String, Object> data = new HashMap<>();
                data.put("refDate", msg.getRefDate());
                data.put("msgType", msg.getMsgType());
                data.put("msgUser", msg.getMsgUser());
                data.put("msgCount", msg.getMsgCount());
                result.add(data);
            }

            logger.info("获取消息关键词发送概况(周)成功: {} - {}", beginDate, endDate);
            return result;
        } catch (WxErrorException e) {
            logger.error("获取消息关键词发送概况(周)失败: {}", e.getMessage(), e);
            return new ArrayList<>();
        }
    }

    @Override
    public List<Map<String, Object>> getMenuSummary(LocalDate beginDate, LocalDate endDate) {
        // 微信API暂不支持菜单分析数据接口，这里提供模拟数据结构
        List<Map<String, Object>> result = new ArrayList<>();

        // 模拟菜单点击数据
        Map<String, Object> menuData = new HashMap<>();
        menuData.put("refDate", beginDate.format(DATE_FORMATTER));
        menuData.put("menuId", "ABOUT_US");
        menuData.put("menuName", "关于我们");
        menuData.put("clickCount", 0);
        menuData.put("clickUser", 0);
        result.add(menuData);

        logger.info("获取菜单分析数据(模拟): {} - {}", beginDate, endDate);
        return result;
    }

    @Override
    public Map<String, Object> getStatisticsOverview() {
        Map<String, Object> overview = new HashMap<>();

        try {
            LocalDate today = LocalDate.now();
            LocalDate yesterday = today.minusDays(1);
            LocalDate weekAgo = today.minusDays(7);

            // 获取用户数据
            List<Map<String, Object>> userSummary = getUserSummary(yesterday, yesterday);
            List<Map<String, Object>> userCumulate = getUserCumulate(yesterday, yesterday);

            int newUsers = userSummary.stream()
                    .mapToInt(data -> (Integer) data.getOrDefault("newUser", 0))
                    .sum();
            int cancelUsers = userSummary.stream()
                    .mapToInt(data -> (Integer) data.getOrDefault("cancelUser", 0))
                    .sum();
            int totalUsers = userCumulate.stream()
                    .mapToInt(data -> (Integer) data.getOrDefault("cumulateUser", 0))
                    .max().orElse(0);

            overview.put("newUsers", newUsers);
            overview.put("cancelUsers", cancelUsers);
            overview.put("totalUsers", totalUsers);
            overview.put("netGrowth", newUsers - cancelUsers);

            // 获取消息数据
            List<Map<String, Object>> msgData = getUpstreamMsg(yesterday, yesterday);
            int totalMessages = msgData.stream()
                    .mapToInt(data -> (Integer) data.getOrDefault("msgCount", 0))
                    .sum();
            int activeUsers = msgData.stream()
                    .mapToInt(data -> (Integer) data.getOrDefault("msgUser", 0))
                    .sum();

            overview.put("totalMessages", totalMessages);
            overview.put("activeUsers", activeUsers);

            // 计算活跃度
            double activityRate = totalUsers > 0 ? (double) activeUsers / totalUsers * 100 : 0;
            overview.put("activityRate", Math.round(activityRate * 100.0) / 100.0);

            overview.put("updateTime", LocalDate.now().format(DATE_FORMATTER));

            logger.info("获取统计概览数据成功");

        } catch (Exception e) {
            logger.error("获取统计概览数据失败: {}", e.getMessage(), e);
            // 返回默认数据
            overview.put("newUsers", 0);
            overview.put("cancelUsers", 0);
            overview.put("totalUsers", 0);
            overview.put("netGrowth", 0);
            overview.put("totalMessages", 0);
            overview.put("activeUsers", 0);
            overview.put("activityRate", 0.0);
            overview.put("updateTime", LocalDate.now().format(DATE_FORMATTER));
        }

        return overview;
    }

    @Override
    public Map<String, Object> getUserPortrait(LocalDate beginDate, LocalDate endDate) {
        Map<String, Object> portrait = new HashMap<>();

        try {
            // 获取用户来源分析
            List<Map<String, Object>> userSummary = getUserSummary(beginDate, endDate);

            Map<String, Integer> sourceAnalysis = new HashMap<>();
            for (Map<String, Object> data : userSummary) {
                String source = (String) data.get("userSource");
                int newUser = (Integer) data.getOrDefault("newUser", 0);
                sourceAnalysis.put(source, sourceAnalysis.getOrDefault(source, 0) + newUser);
            }

            portrait.put("sourceAnalysis", sourceAnalysis);

            // 获取消息类型分析
            List<Map<String, Object>> msgData = getUpstreamMsg(beginDate, endDate);

            Map<String, Integer> msgTypeAnalysis = new HashMap<>();
            for (Map<String, Object> data : msgData) {
                String msgType = (String) data.get("msgType");
                int msgCount = (Integer) data.getOrDefault("msgCount", 0);
                msgTypeAnalysis.put(msgType, msgTypeAnalysis.getOrDefault(msgType, 0) + msgCount);
            }

            portrait.put("msgTypeAnalysis", msgTypeAnalysis);

            logger.info("获取用户画像数据成功: {} - {}", beginDate, endDate);

        } catch (Exception e) {
            logger.error("获取用户画像数据失败: {}", e.getMessage(), e);
            portrait.put("sourceAnalysis", new HashMap<>());
            portrait.put("msgTypeAnalysis", new HashMap<>());
        }

        return portrait;
    }

    @Override
    public List<Map<String, Object>> getPopularContent(LocalDate beginDate, LocalDate endDate, int limit) {
        try {
            List<Map<String, Object>> articleData = getArticleSummary(beginDate, endDate);

            // 按阅读量排序
            articleData.sort((a, b) -> {
                int readCountA = (Integer) a.getOrDefault("intPageReadCount", 0);
                int readCountB = (Integer) b.getOrDefault("intPageReadCount", 0);
                return Integer.compare(readCountB, readCountA);
            });

            // 限制返回数量
            List<Map<String, Object>> result = articleData.stream()
                    .limit(limit)
                    .collect(ArrayList::new, (list, item) -> list.add(item), ArrayList::addAll);

            logger.info("获取热门内容排行成功: {} - {}, limit={}", beginDate, endDate, limit);
            return result;

        } catch (Exception e) {
            logger.error("获取热门内容排行失败: {}", e.getMessage(), e);
            return new ArrayList<>();
        }
    }

    @Override
    public List<Map<String, Object>> getKeywordStatistics(LocalDate beginDate, LocalDate endDate, int limit) {
        // 这里需要结合实际的消息记录数据库来统计关键词
        // 目前提供模拟数据结构
        List<Map<String, Object>> result = new ArrayList<>();

        // 模拟关键词统计数据
        String[] keywords = {"帮助", "客服", "产品", "价格", "使用", "问题", "联系", "服务"};
        Random random = new Random();

        for (int i = 0; i < Math.min(keywords.length, limit); i++) {
            Map<String, Object> data = new HashMap<>();
            data.put("keyword", keywords[i]);
            data.put("count", random.nextInt(100) + 1);
            data.put("userCount", random.nextInt(50) + 1);
            result.add(data);
        }

        // 按使用次数排序
        result.sort((a, b) -> {
            int countA = (Integer) a.get("count");
            int countB = (Integer) b.get("count");
            return Integer.compare(countB, countA);
        });

        logger.info("获取关键词统计(模拟)成功: {} - {}, limit={}", beginDate, endDate, limit);
        return result;
    }
}