package com.fs.live.service.impl;


import com.fs.common.core.domain.R;
import com.fs.common.core.redis.RedisCache;
import com.fs.common.utils.DateUtils;
import com.fs.common.utils.spring.SpringUtils;
import com.fs.company.domain.Company;
import com.fs.company.domain.CompanyUser;
import com.fs.company.mapper.CompanyMapper;
import com.fs.company.mapper.CompanyUserMapper;
import com.fs.live.domain.*;
import com.fs.live.mapper.*;
import com.fs.live.param.LiveDataParam;
import com.fs.live.service.ILiveDataService;
import com.fs.live.service.ILiveUserFavoriteService;
import com.fs.live.service.ILiveUserFollowService;
import com.fs.live.service.ILiveUserLikeService;
import com.fs.live.vo.*;
import com.fs.store.domain.FsStoreProduct;
import com.fs.store.domain.FsUser;
import com.fs.store.mapper.FsStoreProductMapper;
import com.fs.store.mapper.FsUserMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.fs.common.constant.LiveKeysConstant.*;


/**
 * 直播数据Service业务层处理
 *
 * @author fs
 * @date 2025-03-05
 */
@Service
public class LiveDataServiceImpl implements ILiveDataService {


    private static final Logger log = LoggerFactory.getLogger(LiveDataServiceImpl.class);
    @Autowired
    private LiveDataMapper liveDataMapper;
    private final RedisCache redisCache = SpringUtils.getBean(RedisCache.class);
    private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    private final String COLUMNS_CONFIG = "columnsConfigKey";

    @Autowired
    private ILiveUserLikeService liveUserLikeService;

    @Autowired
    private ILiveUserFollowService liveUserFollowService;

    @Autowired
    private ILiveUserFavoriteService liveUserFavoriteService;
    @Autowired
    private LiveDataMapper baseMapper;
    @Autowired
    private FsUserMapper fsUserMapper;
    @Autowired
    private LiveWatchUserMapper liveWatchUserMapper;
    @Autowired
    private CompanyMapper companyMapper;
    @Autowired
    private CompanyUserMapper companyUserMapper;
    @Autowired
    private LiveOrderMapper liveOrderMapper;
    @Autowired
    private LiveMapper liveMapper;
    /**
     * 查询直播数据
     *
     * @param liveId 直播数据主键
     * @return 直播数据
     */
    @Override
    public LiveData selectLiveDataByLiveId(Long liveId)
    {
        return baseMapper.selectLiveDataByLiveId(liveId);
    }

    /**
     * 查询直播数据列表
     *
     * @param liveData 直播数据
     * @return 直播数据
     */
    @Override
    public List<LiveData> selectLiveDataList(LiveData liveData)
    {
        return baseMapper.selectLiveDataList(liveData);
    }

    /**
     * 新增直播数据
     *
     * @param liveData 直播数据
     * @return 结果
     */
    @Override
    public int insertLiveData(LiveData liveData)
    {
        return baseMapper.insertLiveData(liveData);
    }

    /**
     * 修改直播数据
     *
     * @param liveData 直播数据
     * @return 结果
     */
    @Override
    public int updateLiveData(LiveData liveData)
    {
        return baseMapper.updateLiveData(liveData);
    }

    /**
     * 批量删除直播数据
     *
     * @param liveIds 需要删除的直播数据主键
     * @return 结果
     */
    @Override
    public int deleteLiveDataByLiveIds(Long[] liveIds)
    {
        return baseMapper.deleteLiveDataByLiveIds(liveIds);
    }

    /**
     * 删除直播数据信息
     *
     * @param liveId 直播数据主键
     * @return 结果
     */
    @Override
    public int deleteLiveDataByLiveId(Long liveId)
    {
        return baseMapper.deleteLiveDataByLiveId(liveId);
    }

    @Override
    public List<Long> getAllLiveIds() {
        return Collections.emptyList();
    }

    /**
     * 查询所有正在直播的直播间
     *
     * @return
     */
    @Override
    public List<LiveData> getAllLiveDatas() {
        return baseMapper.getAllLiveDatas();
    }

    @Override
    public void updateBatchById(List<LiveData> liveDatas) {
        baseMapper.updateBatchLiveData(liveDatas);
    }


    @Override
    public List<RecentLiveDataVo> getRecentLive() {
        return liveDataMapper.getRecentLive();
    }

    @Override
    public List<RecentLiveDataVo> getCompanyRecentLive(Long companyId) {
        return liveDataMapper.getCompanyRecentLive(companyId);
    }

    @Override
    public List<RecentLiveDataVo> getCompanyLiveTop(String rankType, Long companyId) {
        return liveDataMapper.getCompanyLiveTop(rankType,companyId);
    }

    @Override
    public TrendDataVO getCompanyTrendData(String type, String selectedDate, String category, Long companyId) {
        //DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate date = LocalDate.parse(selectedDate, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        DateRange currentRange = getDateRange(type, date, 0);
        DateRange previousRange = getDateRange(type, date, -1);
        DateRange chartRange = getChartDateRange(type, date); // 天 / 10 周 / 12 月
        // 查询当前周期数据
        TrendDataVO currentData = liveDataMapper.getCompanyCurrentData(currentRange.getStart(), currentRange.getEnd(),companyId);
        if (currentData == null) {
            currentData = new TrendDataVO();
        }
        // 查询上一周期数据
        TrendDataVO prevData = liveDataMapper.getCompanyPreviousData(previousRange.getStart(), previousRange.getEnd(),companyId);
        if (prevData == null) {
            prevData = new TrendDataVO();
        }
        List<Map<String, Object>> chartRawData = liveDataMapper.getCompanyChartData(chartRange.getStart(), chartRange.getEnd(), type,category.trim(),companyId);
        List<String> dates = new ArrayList<>();
        List<Integer> data = new ArrayList<>();

        for (Map<String, Object> row : chartRawData) {
            String dateRange = (String) row.get("date_range");
            Integer views = ((Number) row.get("views")).intValue();

            dates.add(dateRange);
            data.add(views);
        }

        currentData.setDates(dates);
        currentData.setData(data);
        //计算和上一个周期相比的变化百分比
        currentData.setViewsChange(calcChange(
                currentData.getViews() != null ? currentData.getViews() : 0,
                prevData.getPrevViews() != null ? prevData.getPrevViews() : 0));

        currentData.setVisitorsChange(calcChange(
                currentData.getVisitors() != null ? currentData.getVisitors() : 0,
                prevData.getPrevVisitors() != null ? prevData.getPrevVisitors() : 0));

        currentData.setStreamsChange(calcChange(
                currentData.getStreams() != null ? currentData.getStreams() : 0,
                prevData.getPrevStreams() != null ? prevData.getPrevStreams() : 0));

        currentData.setPvChange(calcChange(
                currentData.getPv() != null ? currentData.getPv() : 0,
                prevData.getPrevPv() != null ? prevData.getPrevPv() : 0));

        currentData.setUvChange(calcChange(
                currentData.getUv() != null ? currentData.getUv() : 0,
                prevData.getPrevUv() != null ? prevData.getPrevUv() : 0));

        return currentData;
    }

    @Override
    public List<RecentLiveDataVo> getLiveTop(String rankType) {
        return liveDataMapper.getLiveTop(rankType);
    }
    /**
     * 查询直播趋势数据
     * @param type
     * @param selectedDate
     * @return
     */
    @Override
    public TrendDataVO getTrendData(String type, String selectedDate,String category) {
        //DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate date = LocalDate.parse(selectedDate, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        DateRange currentRange = getDateRange(type, date, 0);
        DateRange previousRange = getDateRange(type, date, -1);
        DateRange chartRange = getChartDateRange(type, date); // 天 / 10 周 / 12 月
        // 查询当前周期数据
        TrendDataVO currentData = liveDataMapper.getCurrentData(currentRange.getStart(), currentRange.getEnd());
        if (currentData == null) {
            currentData = new TrendDataVO();
        }
        // 查询上一周期数据
        TrendDataVO prevData = liveDataMapper.getPreviousData(previousRange.getStart(), previousRange.getEnd());
        if (prevData == null) {
            prevData = new TrendDataVO();
        }
        List<Map<String, Object>> chartRawData = liveDataMapper.getChartData(chartRange.getStart(), chartRange.getEnd(), type,category.trim());
        List<String> dates = new ArrayList<>();
        List<Integer> data = new ArrayList<>();

        for (Map<String, Object> row : chartRawData) {
            String dateRange = (String) row.get("date_range");
            Integer views = ((Number) row.get("views")).intValue();

            dates.add(dateRange);
            data.add(views);
        }

        currentData.setDates(dates);
        currentData.setData(data);
        //计算和上一个周期相比的变化百分比
        currentData.setViewsChange(calcChange(
                currentData.getViews() != null ? currentData.getViews() : 0,
                prevData.getPrevViews() != null ? prevData.getPrevViews() : 0));

        currentData.setVisitorsChange(calcChange(
                currentData.getVisitors() != null ? currentData.getVisitors() : 0,
                prevData.getPrevVisitors() != null ? prevData.getPrevVisitors() : 0));

        currentData.setStreamsChange(calcChange(
                currentData.getStreams() != null ? currentData.getStreams() : 0,
                prevData.getPrevStreams() != null ? prevData.getPrevStreams() : 0));

        currentData.setPvChange(calcChange(
                currentData.getPv() != null ? currentData.getPv() : 0,
                prevData.getPrevPv() != null ? prevData.getPrevPv() : 0));

        currentData.setUvChange(calcChange(
                currentData.getUv() != null ? currentData.getUv() : 0,
                prevData.getPrevUv() != null ? prevData.getPrevUv() : 0));

        return currentData;
    }



    /**
     *
     * @param current 当前周期
     * @param previous 上一周期
     * @return
     */
    private double calcChange(Integer current, Integer previous) {
        if (current==previous){return 0.0;}
        if (previous == null || previous == 0) {return 100.0;}
        double change = ((double) (current - previous) / previous) * 100;
        BigDecimal bd = new BigDecimal(change).setScale(2, RoundingMode.HALF_UP);
        return bd.doubleValue();
    }
    /**
     * 获取当前/上个周期的时间范围
     */
    private DateRange getDateRange(String type, LocalDate date, int offset) {
        LocalDate start, end;
        switch (type) {
            case "week":
                start = date.minusWeeks(-offset).with(DayOfWeek.MONDAY); // 该周的周一
                end = start.plusDays(6); // 该周的周日
                break;
            case "month":
                start = date.minusMonths(-offset).withDayOfMonth(1); // 该月第一天
                end = start.plusMonths(1).minusDays(1); // 该月最后一天
                break;
            default: // "day"
                start = date.minusDays(Math.abs(offset)); // 计算 start
                end = date;
                break;
        }
        return new DateRange(start.toString(), end.toString());
    }


    /**
     * 获取折线图查询范围
     */
    private DateRange getChartDateRange(String type, LocalDate date) {
        LocalDate start, end;
        switch (type) {
            case "week":
                start = date.minusWeeks(9).with(DayOfWeek.MONDAY);
                end = date.with(DayOfWeek.SUNDAY);
                break;
            case "month":
                start = date.minusMonths(11).withDayOfMonth(1);
                end = date.withDayOfMonth(date.lengthOfMonth());
                break;
            default: // day
                start = date.minusDays(30);
                end = date;
                break;
        }
        return new DateRange(start.format(FORMATTER), end.format(FORMATTER));
    }
    /**
     * @param  userId 当前登录用户id
     * 查询表格字段配置
     * @return
     */
    /*@Override
    public List<ColumnsConfigVo> getColumnsConfig(String userId) {
        List<Object> cacheList = redisCache.getCacheObject(COLUMNS_CONFIG + userId + ":");
        if (cacheList == null){
            List<ColumnsConfigVo> columns = new ArrayList<>();
            *//*columns.add(new ColumnsConfigVo("customer_name", "客户名", "ENABLE"));
            columns.add(new ColumnsConfigVo("live_room", "直播间", "ENABLE"));
            columns.add(new ColumnsConfigVo("follower", "跟进人", "ENABLE"));*//*
            columns.add(new ColumnsConfigVo("department", "归属部门", "ENABLE"));
            columns.add(new ColumnsConfigVo("created_time", "客户创建时间", "ENABLE"));
            columns.add(new ColumnsConfigVo("contact_method", "联系方式", "ENABLE"));
            columns.add(new ColumnsConfigVo("order_goods", "去下单实物商品", "ENABLE"));
            columns.add(new ColumnsConfigVo("share_live_count", "分享直播间次数", "ENABLE"));
            columns.add(new ColumnsConfigVo("reply_count", "答题次数", "ENABLE"));
            columns.add(new ColumnsConfigVo("correct_reply_count", "答题正确次数", "ENABLE"));
            columns.add(new ColumnsConfigVo("reply_accuracy", "答题正确率", "ENABLE"));
            columns.add(new ColumnsConfigVo("first_visit_time", "首次访问时间", "ENABLE"));
            columns.add(new ColumnsConfigVo("first_visit_type", "首次访问类型", "ENABLE"));
            columns.add(new ColumnsConfigVo("max_live_stay_time", "直播最长停留时间", "ENABLE"));
            columns.add(new ColumnsConfigVo("total_live_watch_time", "直播累计观看时长", "ENABLE"));
            columns.add(new ColumnsConfigVo("max_replay_stay_time", "回放最长停留时间", "ENABLE"));
            columns.add(new ColumnsConfigVo("total_replay_watch_time", "回放累计观看时长", "ENABLE"));
            columns.add(new ColumnsConfigVo("total_watch_time", "总累计观看时长", "ENABLE"));
            columns.add(new ColumnsConfigVo("last_exit_time", "最后一次退出时间", "ENABLE"));
            columns.add(new ColumnsConfigVo("speak_count", "发言次数", "ENABLE"));
            columns.add(new ColumnsConfigVo("visit_form_name", "访问表单名称", "ENABLE"));
            columns.add(new ColumnsConfigVo("submit_form_name", "提交表单名称", "ENABLE"));
            columns.add(new ColumnsConfigVo("pending_payment_goods", "待支付商品", "ENABLE"));
            columns.add(new ColumnsConfigVo("purchased_goods", "购买商品名称", "ENABLE"));
            columns.add(new ColumnsConfigVo("last_purchase_time", "最近商品购买时间", "ENABLE"));
            columns.add(new ColumnsConfigVo("spending_amount", "消费金额", "ENABLE"));
            columns.add(new ColumnsConfigVo("coupon_name", "优惠券名称", "ENABLE"));
            columns.add(new ColumnsConfigVo("is_participate_lottery", "是否参与抽奖", "ENABLE"));
            columns.add(new ColumnsConfigVo("is_winner", "是否中奖", "ENABLE"));
            columns.add(new ColumnsConfigVo("claimed_watch_reward", "领取观看奖励", "ENABLE"));
            columns.add(new ColumnsConfigVo("reward_withdrawal_amount", "奖励提现金额", "ENABLE"));
            columns.add(new ColumnsConfigVo("reward_type", "奖励类型", "ENABLE"));
            columns.add(new ColumnsConfigVo("red_envelope_count", "红包领取次数", "ENABLE"));
            columns.add(new ColumnsConfigVo("click_external_goods", "点击外链商品次数", "ENABLE"));
            columns.add(new ColumnsConfigVo("is_request_mic", "是否申请连麦", "ENABLE"));
            columns.add(new ColumnsConfigVo("is_on_mic", "是否连麦", "ENABLE"));
            columns.add(new ColumnsConfigVo("advertiser", "广告商", "ENABLE"));
            columns.add(new ColumnsConfigVo("promotion_account", "推广账户", "ENABLE"));
            columns.add(new ColumnsConfigVo("promotion_level_1", "推广一级", "ENABLE"));
            columns.add(new ColumnsConfigVo("promotion_level_2", "推广二级", "ENABLE"));
            columns.add(new ColumnsConfigVo("site_placement", "站点投放", "ENABLE"));
            columns.add(new ColumnsConfigVo("channel", "渠道", "ENABLE"));
            columns.add(new ColumnsConfigVo("tags", "标签", "ENABLE"));
            columns.add(new ColumnsConfigVo("follow_status", "跟进状态", "ENABLE"));
            columns.add(new ColumnsConfigVo("sharer_name", "分享人名称", "ENABLE"));
            columns.add(new ColumnsConfigVo("customer_id", "客户ID", "ENABLE"));
            columns.add(new ColumnsConfigVo("union_id", "unionId", "ENABLE"));
            columns.add(new ColumnsConfigVo("source", "来源", "ENABLE"));
            columns.add(new ColumnsConfigVo("landing_page", "着陆页", "ENABLE"));
            columns.add(new ColumnsConfigVo("live_room_url", "直播间访问地址", "ENABLE"));
            columns.add(new ColumnsConfigVo("collaborator", "协作人", "ENABLE"));
            columns.add(new ColumnsConfigVo("wechat_note", "微信备注", "ENABLE"));
            redisCache.setCacheList(COLUMNS_CONFIG + userId + ":",columns);
            return columns;
        }
        // 如果缓存中有数据，将其转换为 ColumnsConfigVo 对象并返回
        List<ColumnsConfigVo> columnsConfigList = new ArrayList<>();
        for (Object obj : cacheList) {
            if (obj instanceof ColumnsConfigVo) {
                columnsConfigList.add((ColumnsConfigVo) obj);
            }
        }
        return columnsConfigList;
    }
*/
    @Override
    public void saveColumnsConfig(String userId, List<ColumnsConfigVo> columns) {
        redisCache.deleteObject(COLUMNS_CONFIG + userId + ":");
        redisCache.setCacheObject(COLUMNS_CONFIG + userId + ":", columns);
    }

    @Override
    @Transactional
    public R updateLikeByLiveId(Long liveId, Long userId) {
        String key = "live:like:" + liveId + ":user:" + userId+":date:"+ DateUtils.getDate();
        LiveUserLike liveUserLike;
        boolean firstLike = redisCache.setIfAbsent(key, 1, 1, TimeUnit.DAYS);
        //用户直播间第一次点赞
        if(firstLike) {
            liveUserLike = liveUserLikeService.selectLiveUserLikeByIds(liveId, userId);
            if (liveUserLike == null) {
                liveUserLike = new LiveUserLike();
                liveUserLike.setUserId(userId);
                liveUserLike.setLiveId(liveId);
                liveUserLike.setCreateTime(new Date());
                liveUserLikeService.insertLiveUserLike(liveUserLike);
                return R.ok().put("like",redisCache.getCacheObject(key));
            }
        }else{
            //用户直播间点赞数
            redisCache.increment(key,1);
        }
        try {
            //直播间总点赞数
            redisCache.increment("live:like:" + liveId,1);
        } catch (Exception e) {
            log.error(e.getMessage());
            redisCache.setCacheObject("live:like:" + liveId, 1);
        }

        return R.ok().put("like",redisCache.getCacheObject("live:like:" + liveId));
    }

    @Override
    public String collect(Long liveId, Long userId) {
        //查询用户是否收藏过该直播间
        LiveUserFavorite liveUserFavorite = liveUserFavoriteService.selectLiveUserFavoriteByLiveIdAndUserId(liveId, userId);
        if (liveUserFavorite != null) {
            liveUserFavoriteService.deleteLiveUserFavoriteByLiveIdAndUserId(liveId, userId);
            return "取消收藏成功";
        }
        liveUserFavorite = new LiveUserFavorite();
        liveUserFavorite.setUserId(userId);
        liveUserFavorite.setLiveId(liveId);
        liveUserFavorite.setCreateTime(new Date());
        liveUserFavoriteService.insertLiveUserFavorite(liveUserFavorite);
        return "收藏成功";
    }

    @Override
    public String follow(Long liveId, Long userId) {
        LiveUserFollow liveUserFollow = liveUserFollowService.selectLiveUserFollowByLiveIdAndUserId(liveId, userId);
        if (liveUserFollow != null) {
            liveUserFollowService.deleteLiveUserFollowByLiveIdAndUserId(liveId, userId);
            return "取消关注成功";
        }
        liveUserFollow = new LiveUserFollow();
        liveUserFollow.setUserId(userId);
        liveUserFollow.setLiveId(liveId);
        liveUserFollow.setCreateTime(new Date());
        liveUserFollowService.insertLiveUserFollow(liveUserFollow);
        return "关注成功";
    }

    /**
     * 收藏/取消收藏店铺
     */
    @Override
    public String collectStore(Long userId, Long storeId) {
        return toggleFavorite(userId, storeId, null);
    }

    /**
     * 通用收藏切换方法
     */
    private String toggleFavorite(Long userId, Long storeId, Long productId) {


        long count = liveUserFavoriteService.count(userId,storeId,productId);
        if (count > 0) {
            liveUserFavoriteService.removeBy(userId,storeId,productId);
            return "取消收藏成功";
        }

        LiveUserFavorite favorite = new LiveUserFavorite();
        favorite.setUserId(userId);
        if (storeId != null) {
            favorite.setStoreId(storeId);
        }
        if (productId != null) {
            favorite.setProductId(productId);
        }

        liveUserFavoriteService.insertLiveUserFavorite(favorite);
        return "收藏成功";
    }

    /**
     * 收藏/取消收藏商品
     */
    @Override
    public String collectProduct(Long userId, Long productId) {
        return toggleFavorite(userId, null, productId);
    }

    @Override
    public Map<String, Object> getLiveViewData(Long liveId) {
        Map<String, Object> liveViewData = new HashMap<>();
        //在线人数
        liveViewData.put("online", redisCache.getCacheObject(ONLINE_USERS_KEY+liveId));
        //关注数
        liveViewData.put("follow", 0);
        //点赞数
        liveViewData.put("like", redisCache.getCacheObject("live:like:"+liveId));
        return liveViewData;
    }

    private Map<String, String> createColumn(String dataIndex, String status, String title) {
        Map<String, String> column = new HashMap<>();
        column.put("dataIndex", dataIndex);
        column.put("status", status);
        column.put("title", title);
        return column;
    }

    @Override
    public R getLiveDataDetailBySql(Long liveId) {
        LiveDataDetailVo detailVo = liveDataMapper.selectLiveDataDetailBySql(liveId);
        if (detailVo == null) {
            detailVo = new LiveDataDetailVo();
        }
        // 查询单品销量统计
        List<ProductSalesVo> productSalesList = getProductSalesList(liveId);
        detailVo.setProductSalesList(productSalesList);
        return R.ok().put("data", detailVo);
    }

    @Override
    public R getLiveUserDetailListBySql(Long liveId, Long companyId, Long companyUserId ) {
        List<LiveUserDetailVo> userDetailList = liveDataMapper.selectLiveUserDetailListBySql(liveId, companyId, companyUserId);
        return R.ok().put("data", userDetailList);
    }

    @Override
    public R getLiveDataDetailByServer(Long liveId) {
        // 查询数据服务器处理方式：通过查询各个表的数据，在内存中计算统计
        LiveDataDetailVo detailVo = calculateLiveDataDetailByServer(liveId);
        // 查询单品销量统计
        List<ProductSalesVo> productSalesList = getProductSalesList(liveId);
        detailVo.setProductSalesList(productSalesList);
        return R.ok().put("data", detailVo);
    }

    @Override
    public R getLiveUserDetailListByServer(Long liveId) {
        // 查询数据服务器处理方式：通过查询各个表的数据，在内存中计算
        List<LiveUserDetailVo> userDetailList = calculateLiveUserDetailListByServer(liveId);
        return R.ok().put("data", userDetailList);
    }

    /**
     * 通过查询数据服务器处理方式计算直播间详情数据
     */
    private LiveDataDetailVo calculateLiveDataDetailByServer(Long liveId) {
        LiveDataDetailVo detailVo = new LiveDataDetailVo();

        // 查询视频时长
        LiveVideoMapper liveVideoMapper = SpringUtils.getBean(LiveVideoMapper.class);
        List<LiveVideo> videos = liveVideoMapper.selectByLiveId(liveId);
        Long videoDuration = videos.stream()
                .filter(v -> v.getVideoType() != null && (v.getVideoType() == 1 || v.getVideoType() == 2))
                .mapToLong(v -> v.getDuration() != null ? v.getDuration() : 0L)
                .sum();
        detailVo.setVideoDuration(videoDuration);

        // 查询观看用户数据
        LiveWatchUser queryParam = new LiveWatchUser();
        queryParam.setLiveId(liveId);
        List<LiveWatchUser> watchUsers = liveWatchUserMapper.selectLiveWatchUserList(queryParam);

        // 累计观看人数
        long totalViewers = watchUsers.stream().map(LiveWatchUser::getUserId).distinct().count();
        detailVo.setTotalViewers(totalViewers);

        // 直播观看人数
        long liveViewers = watchUsers.stream()
                .filter(w -> w.getLiveFlag() != null && w.getLiveFlag() == 1 && (w.getReplayFlag() == null || w.getReplayFlag() == 0))
                .map(LiveWatchUser::getUserId)
                .distinct()
                .count();
        detailVo.setLiveViewers(liveViewers);

        // 回放观看人数
        long playbackViewers = watchUsers.stream()
                .filter(w -> w.getReplayFlag() != null && w.getReplayFlag() == 1 && (w.getLiveFlag() == null || w.getLiveFlag() == 0))
                .map(LiveWatchUser::getUserId)
                .distinct()
                .count();
        detailVo.setPlaybackViewers(playbackViewers);

        // 累计完课人数（观看时长 >= 视频时长）
        long totalCompletedCourses = watchUsers.stream()
                .filter(w -> w.getOnlineSeconds() != null && videoDuration > 0 && w.getOnlineSeconds() >= videoDuration)
                .map(LiveWatchUser::getUserId)
                .distinct()
                .count();
        detailVo.setTotalCompletedCourses(totalCompletedCourses);

        // 计算到课完课率
        if (totalViewers > 0) {
            detailVo.setTotalCompletionRate(BigDecimal.valueOf(totalCompletedCourses * 100.0 / totalViewers).setScale(2, RoundingMode.HALF_UP));
        }

        // 直播相关统计
        List<LiveWatchUser> liveWatchUsers = watchUsers.stream()
                .filter(w -> w.getLiveFlag() != null && w.getLiveFlag() == 1 && (w.getReplayFlag() == null || w.getReplayFlag() == 0))
                .collect(Collectors.toList());

        long liveOver20Minutes = liveWatchUsers.stream()
                .filter(w -> w.getOnlineSeconds() != null && w.getOnlineSeconds() >= 1200)
                .map(LiveWatchUser::getUserId)
                .distinct()
                .count();
        detailVo.setLiveOver20Minutes(liveOver20Minutes);

        long liveOver30Minutes = liveWatchUsers.stream()
                .filter(w -> w.getOnlineSeconds() != null && w.getOnlineSeconds() >= 1800)
                .map(LiveWatchUser::getUserId)
                .distinct()
                .count();
        detailVo.setLiveOver30Minutes(liveOver30Minutes);

        if (liveViewers > 0) {
            detailVo.setLiveCompletionRate20(BigDecimal.valueOf(liveOver20Minutes * 100.0 / liveViewers).setScale(2, RoundingMode.HALF_UP));
            detailVo.setLiveCompletionRate30(BigDecimal.valueOf(liveOver30Minutes * 100.0 / liveViewers).setScale(2, RoundingMode.HALF_UP));
        }

        // 直播平均时长
        double liveAvgDuration = liveWatchUsers.stream()
                .filter(w -> w.getOnlineSeconds() != null)
                .mapToLong(LiveWatchUser::getOnlineSeconds)
                .average()
                .orElse(0.0);
        detailVo.setLiveAvgDuration((long) liveAvgDuration);

        // 回放相关统计
        List<LiveWatchUser> playbackWatchUsers = watchUsers.stream()
                .filter(w -> w.getReplayFlag() != null && w.getReplayFlag() == 1 && (w.getLiveFlag() == null || w.getLiveFlag() == 0))
                .collect(Collectors.toList());

        long playbackOver20Minutes = playbackWatchUsers.stream()
                .filter(w -> w.getOnlineSeconds() != null && w.getOnlineSeconds() >= 1200)
                .map(LiveWatchUser::getUserId)
                .distinct()
                .count();
        detailVo.setPlaybackOver20Minutes(playbackOver20Minutes);

        long playbackOver30Minutes = playbackWatchUsers.stream()
                .filter(w -> w.getOnlineSeconds() != null && w.getOnlineSeconds() >= 1800)
                .map(LiveWatchUser::getUserId)
                .distinct()
                .count();
        detailVo.setPlaybackOver30Minutes(playbackOver30Minutes);

        if (playbackViewers > 0) {
            detailVo.setPlaybackCompletionRate20(BigDecimal.valueOf(playbackOver20Minutes * 100.0 / playbackViewers).setScale(2, RoundingMode.HALF_UP));
            detailVo.setPlaybackCompletionRate30(BigDecimal.valueOf(playbackOver30Minutes * 100.0 / playbackViewers).setScale(2, RoundingMode.HALF_UP));
        }

        // 回放平均时长
        double playbackAvgDuration = playbackWatchUsers.stream()
                .filter(w -> w.getOnlineSeconds() != null)
                .mapToLong(LiveWatchUser::getOnlineSeconds)
                .average()
                .orElse(0.0);
        detailVo.setPlaybackAvgDuration((long) playbackAvgDuration);

        // 回放完播率
        if (videoDuration > 0) {
            detailVo.setPlaybackFinishRate(BigDecimal.valueOf(playbackAvgDuration * 100.0 / videoDuration).setScale(2, RoundingMode.HALF_UP));
        }

        // 查询直播峰值
        LiveData liveData = liveDataMapper.selectLiveDataByLiveId(liveId);
        if (liveData != null && liveData.getPeakConcurrentViewers() != null) {
            detailVo.setLivePeak(liveData.getPeakConcurrentViewers());
        }

        // 查询订单数据
        LiveOrderMapper liveOrderMapper = SpringUtils.getBean(LiveOrderMapper.class);
        LiveOrderQueryVO orderQuery = new LiveOrderQueryVO();
        orderQuery.setLiveId(liveId);
        List<LiveOrder> orders = liveOrderMapper.selectLiveOrderList(orderQuery);

        BigDecimal gmv = orders.stream()
                .filter(o -> "1".equals(o.getIsPay()))
                .map(LiveOrder::getPayPrice)
                .filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        detailVo.setGmv(gmv);

        long paidUsers = orders.stream()
                .filter(o -> "1".equals(o.getIsPay()))
                .filter(o -> o.getUserId() != null && !o.getUserId().isEmpty())
                .map(o -> {
                    try {
                        return Long.parseLong(o.getUserId());
                    } catch (NumberFormatException e) {
                        return null;
                    }
                })
                .filter(Objects::nonNull)
                .distinct()
                .count();
        detailVo.setPaidUsers(paidUsers);

        long paidOrders = orders.stream()
                .filter(o -> "1".equals(o.getIsPay()))
                .count();
        detailVo.setPaidOrders(paidOrders);

        // 计算转化率
        if (detailVo.getLivePeak() > 0) {
            detailVo.setPeakConversionRate(BigDecimal.valueOf(paidUsers * 100.0 / detailVo.getLivePeak()).setScale(2, RoundingMode.HALF_UP));
            detailVo.setPeakRValue(gmv.divide(BigDecimal.valueOf(detailVo.getLivePeak()), 2, RoundingMode.HALF_UP));
        }

        if (totalViewers > 0) {
            detailVo.setTotalViewerConversionRate(BigDecimal.valueOf(paidUsers * 100.0 / totalViewers).setScale(2, RoundingMode.HALF_UP));
        }

        if (liveOver30Minutes > 0) {
            detailVo.setCompletion30MinConversionRate(BigDecimal.valueOf(paidUsers * 100.0 / liveOver30Minutes).setScale(2, RoundingMode.HALF_UP));
        }

        if (totalCompletedCourses > 0) {
            detailVo.setCompletionRValue(gmv.divide(BigDecimal.valueOf(totalCompletedCourses), 2, RoundingMode.HALF_UP));
        }

        return detailVo;
    }

    /**
     * 通过查询数据服务器处理方式计算用户详情列表
     */
    private List<LiveUserDetailVo> calculateLiveUserDetailListByServer(Long liveId) {
        // 查询观看用户
        List<LiveWatchUser> watchUsers = liveWatchUserMapper.selectLiveWatchUserListByLiveId(liveId);

        LiveOrderQueryVO orderQuery = new LiveOrderQueryVO();
        orderQuery.setLiveId(liveId);
        List<LiveOrder> orders = liveOrderMapper.selectLiveOrderList(orderQuery);


        // 按用户ID分组统计
        Map<Long, LiveUserDetailVo> userDetailMap = new HashMap<>();

        for (LiveWatchUser watchUser : watchUsers) {
            Long userId = watchUser.getUserId();
            if (userId == null) continue;

            LiveUserDetailVo userDetail = userDetailMap.computeIfAbsent(userId, k -> {
                LiveUserDetailVo vo = new LiveUserDetailVo();
                vo.setUserId(userId);
                // 查询用户信息
                FsUser user = fsUserMapper.selectFsUserByUserId(userId);
                if (user != null) {
                    vo.setUserName(user.getNickname() != null ? user.getNickname() : (user.getNickname() != null ? user.getNickname() : "未知用户"));
                } else {
                    vo.setUserName("未知用户");
                }
                return vo;
            });

            // 累加观看时长
            if (watchUser.getOnlineSeconds() != null) {
                if (watchUser.getLiveFlag() != null && watchUser.getLiveFlag() == 1 && (watchUser.getReplayFlag() == null || watchUser.getReplayFlag() == 0)) {
                    userDetail.setLiveWatchDuration(userDetail.getLiveWatchDuration() + watchUser.getOnlineSeconds());
                } else if (watchUser.getReplayFlag() != null && watchUser.getReplayFlag() == 1 && (watchUser.getLiveFlag() == null || watchUser.getLiveFlag() == 0)) {
                    userDetail.setPlaybackWatchDuration(userDetail.getPlaybackWatchDuration() + watchUser.getOnlineSeconds());
                }
            }
        }

        // 统计订单数据
        Map<Long, List<LiveOrder>> userOrdersMap = orders.stream()
                .filter(o -> o.getUserId() != null && !o.getUserId().isEmpty())
                .filter(o -> {
                    try {
                        Long.parseLong(o.getUserId());
                        return true;
                    } catch (NumberFormatException e) {
                        return false;
                    }
                })
                .collect(Collectors.groupingBy(o -> {
                    try {
                        return Long.parseLong(o.getUserId());
                    } catch (NumberFormatException e) {
                        return 0L;
                    }
                }));

        for (Map.Entry<Long, List<LiveOrder>> entry : userOrdersMap.entrySet()) {
            Long userId = entry.getKey();
            List<LiveOrder> userOrders = entry.getValue();

            LiveUserDetailVo userDetail = userDetailMap.computeIfAbsent(userId, k -> {
                LiveUserDetailVo vo = new LiveUserDetailVo();
                vo.setUserId(userId);
                FsUser user = fsUserMapper.selectFsUserByUserId(userId);
                if (user != null) {
                    vo.setUserName(user.getNickname() != null ? user.getNickname() : (user.getNickname() != null ? user.getNickname() : "未知用户"));
                } else {
                    vo.setUserName("未知用户");
                }
                return vo;
            });

            userDetail.setOrderCount((long) userOrders.size());
            BigDecimal orderAmount = userOrders.stream()
                    .filter(o -> "1".equals(o.getIsPay()))
                    .map(LiveOrder::getPayPrice)
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            userDetail.setOrderAmount(orderAmount);
        }

        // 转换为列表并排序
        List<LiveUserDetailVo> result = new ArrayList<>(userDetailMap.values());
        result.sort((a, b) -> {
            int compare = b.getOrderAmount().compareTo(a.getOrderAmount());
            if (compare != 0) return compare;
            return Long.compare(b.getLiveWatchDuration(), a.getLiveWatchDuration());
        });

        return result;
    }

    /**
     * 查询单品销量统计
     */
    private List<ProductSalesVo> getProductSalesList(Long liveId) {

        List<LiveOrder> orders = liveOrderMapper.selectOrderByLiveId(liveId);

        // 按商品ID分组统计
        Map<Long, ProductSalesVo> productSalesMap = new HashMap<>();

        for (LiveOrder order : orders) {
            if (!"1".equals(order.getIsPay()) || order.getProductId() == null) {
                continue;
            }

            ProductSalesVo productSales = productSalesMap.computeIfAbsent(order.getProductId(), k -> {
                ProductSalesVo vo = new ProductSalesVo();
                vo.setProductId(order.getProductId());
                // 查询商品名称
                FsStoreProductMapper productMapper = SpringUtils.getBean(FsStoreProductMapper.class);
                FsStoreProduct product = productMapper.selectFsStoreProductById(order.getProductId());
                if (product != null) {
                    vo.setProductName(product.getProductName());
                } else {
                    vo.setProductName("未知商品");
                }
                return vo;
            });

            productSales.setSalesCount(productSales.getSalesCount() + 1);
            if (order.getPayPrice() != null) {
                productSales.setSalesAmount(productSales.getSalesAmount().add(order.getPayPrice()));
            }
        }

        List<ProductSalesVo> result = new ArrayList<>(productSalesMap.values());
        result.sort((a, b) -> b.getSalesAmount().compareTo(a.getSalesAmount()));

        return result;
    }
    /**
     * 导出直播间用户详情数据
     * @param liveId 直播间ID
     * @return 导出VO列表
     */
    @Override
    public List<LiveUserDetailExportVO> exportLiveUserDetail(Long liveId, Long companyId, Long companyUserId) {
        // 查询用户详情列表
        List<LiveUserDetailVo> userDetailList = liveDataMapper.selectLiveUserDetailListBySql(liveId, companyId, companyUserId);
        if (userDetailList == null || userDetailList.isEmpty()) {
            return new ArrayList<>();
        }

        // 转换为导出VO列表
        List<LiveUserDetailExportVO> exportList = new ArrayList<>();
        for (LiveUserDetailVo userDetail : userDetailList) {
            LiveUserDetailExportVO exportVO = new LiveUserDetailExportVO();

            // 用户基本信息
            exportVO.setUserId(userDetail.getUserId());
            exportVO.setUserName(userDetail.getUserName());

            // 观看时长（秒转分钟）
            exportVO.setLiveWatchDuration(formatSecondsToMinutes(userDetail.getLiveWatchDuration()));
            exportVO.setPlaybackWatchDuration(formatSecondsToMinutes(userDetail.getPlaybackWatchDuration()));

            // 计算总观看时长
            Long totalSeconds = (userDetail.getLiveWatchDuration() != null ? userDetail.getLiveWatchDuration() : 0L) +
                    (userDetail.getPlaybackWatchDuration() != null ? userDetail.getPlaybackWatchDuration() : 0L);
//            exportVO.setTotalWatchDuration(formatSecondsToMinutes(totalSeconds));

            // 订单信息
            exportVO.setOrderCount(Math.toIntExact(userDetail.getOrderCount()));
            exportVO.setOrderAmount(formatMoney(userDetail.getOrderAmount()));

            // 公司和销售信息
            exportVO.setCompanyName(userDetail.getCompanyName());
            exportVO.setSalesName(userDetail.getSalesName());

            // 是否完课（根据观看时长判断，假设30分钟以上为完课）
            if (totalSeconds >= 1800) {
                exportVO.setIsCompleted("是");
            } else {
                exportVO.setIsCompleted("否");
            }

            exportList.add(exportVO);
        }

        return exportList;
    }

    @Override
    public R listLiveData(LiveDataParam param) {
        // 第一步：查询当前公司的直播间数据
        // 直播类型 只展示已结束和直播回放的数据 录播展示直播中和已结束的直播数据
        List<Live> lives = liveMapper.listLiveData(param);
        int total = liveMapper.listLiveDataCount(param);

        if (lives == null || lives.isEmpty()) {
            LiveDataStatisticsVo statistics = new LiveDataStatisticsVo();
            return R.ok().put("list", Collections.emptyList()).put("data", statistics);
        }

        // 获取直播间ID列表
        List<Long> liveIds = lives.stream()
                .map(Live::getLiveId)
                .collect(Collectors.toList());

        // 查询统计数据（根据live_watch_user表查询用户的在线时长，计算平均时长
        // 根据live_video的文件时长，判断用户的完课情况
        // 根据live_order查询直播间的销量额和订单数）
        LiveDataStatisticsVo statistics = baseMapper.selectLiveDataStatistics(liveIds);
        if (statistics == null) {
            statistics = new LiveDataStatisticsVo();
        }

        // 查询列表数据（每个直播间的详细统计数据）
        List<LiveDataListVo> liveDataList = baseMapper.selectLiveDataListByLiveIds(liveIds);
        if (liveDataList == null) {
            liveDataList = Collections.emptyList();
        }

        return R.ok().put("list", liveDataList).put("data", statistics).put("total", total);
    }

    /**
     * 格式化秒数为分钟（保留2位小数）
     */
    private String formatSecondsToMinutes(Long seconds) {
        if (seconds == null || seconds == 0) {
            return "0.00";
        }
        BigDecimal minutes = new BigDecimal(seconds).divide(new BigDecimal(60), 2, RoundingMode.HALF_UP);
        return minutes.toString();
    }

    /**
     * 格式化金额
     */
    private String formatMoney(BigDecimal value) {
        if (value == null) {
            return "0.00";
        }
        return value.setScale(2, RoundingMode.HALF_UP).toString();
    }


}
