package com.fs.live.service.impl;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.thread.ThreadUtil;
import com.alibaba.fastjson.JSON;
import com.fs.common.constant.LiveKeysConstant;
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.StringUtils;
import com.fs.his.domain.FsUser;
import com.fs.his.service.IFsUserService;
import com.fs.hisStore.domain.FsUserScrm;
import com.fs.hisStore.service.IFsUserScrmService;
import com.fs.live.domain.Live;
import com.fs.live.domain.LiveVideo;
import com.fs.live.domain.LiveWatchUser;
import com.fs.live.mapper.LiveWatchUserMapper;
import com.fs.live.mapper.LiveMapper;
import com.fs.live.mapper.LiveVideoMapper;
import com.fs.live.service.ILiveWatchUserService;
import com.fs.live.vo.LiveWatchUserStatistics;
import com.fs.live.vo.LiveWatchUserVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 直播间观看用户Service业务层处理
 *
 * @author fs
 * @date 2025-01-18
 */
@Service
@Slf4j
public class LiveWatchUserServiceImpl implements ILiveWatchUserService {

    @Autowired
    private RedisCache redisCache;
    @Autowired
    private IFsUserScrmService fsUserService;
    @Autowired
    private LiveWatchUserMapper baseMapper;
    @Autowired
    private LiveMapper liveMapper;
    @Autowired
    private LiveVideoMapper liveVideoMapper;


    /**
     * 查询直播间观看用户
     *
     * @param id 直播间观看用户主键
     * @return 直播间观看用户
     */
    @Override
    public LiveWatchUser selectLiveWatchUserById(Long id)
    {
        return baseMapper.selectLiveWatchUserById(id);
    }

    /**
     * 查询企业直播间观看用户
     * @param id                直播间用户ID
     * @param companyId         企业ID
     * @param companyUserId     企业用户ID
     * @return LiveWatchUser
     */
    @Override
    public LiveWatchUser selectLiveWatchUserByIdAndCompanyIdAndCompanyUserId(Long id, Long companyId, Long companyUserId)
    {
        return baseMapper.selectLiveWatchUserByIdAndCompanyIdAndCompanyUserId(id, companyId, companyUserId);
    }

    /**
     * 查询直播间观看用户列表
     *
     * @param liveWatchUser 直播间观看用户
     * @return 直播间观看用户
     */
    @Override
    public List<LiveWatchUser> selectLiveWatchUserList(LiveWatchUser liveWatchUser)
    {
        if ("online".equals(liveWatchUser.getTabName())) {
            liveWatchUser.setOnline(0);
        } else if ("offline".equals(liveWatchUser.getTabName())) {
            liveWatchUser.setOnline(1);
        } else if ("silenced".equals(liveWatchUser.getTabName())) {
            liveWatchUser.setMsgStatus(1);
        }
        // 先查缓存，获取liveFlag和replayFlag
        if (liveWatchUser != null && liveWatchUser.getLiveId() != null) {
            Map<String, Integer> flagMap = getLiveFlagWithCache(liveWatchUser.getLiveId());
            liveWatchUser.setLiveFlag(flagMap.get("liveFlag"));
            liveWatchUser.setReplayFlag(flagMap.get("replayFlag"));
        }
        return baseMapper.selectLiveWatchUserList(liveWatchUser);
    }

    /**
     * 新增直播间观看用户
     *
     * @param liveWatchUser 直播间观看用户
     * @return 结果
     */
    @Override
    public int insertLiveWatchUser(LiveWatchUser liveWatchUser)
    {
        liveWatchUser.setCreateTime(DateUtils.getNowDate());
        return baseMapper.insertLiveWatchUser(liveWatchUser);
    }

    /**
     * 修改直播间观看用户
     *
     * @param liveWatchUser 直播间观看用户
     * @return 结果
     */
    @Override
    public int updateLiveWatchUser(LiveWatchUser liveWatchUser)
    {
        liveWatchUser.setUpdateTime(DateUtils.getNowDate());
        return baseMapper.updateLiveWatchUser(liveWatchUser);
    }

    /**
     * 批量删除直播间观看用户
     *
     * @param ids 需要删除的直播间观看用户主键
     * @return 结果
     */
    @Override
    public int deleteLiveWatchUserByIds(Long[] ids)
    {
        return baseMapper.deleteLiveWatchUserByIds(ids);
    }

    /**
     * 删除直播间观看用户信息
     *
     * @param id 直播间观看用户主键
     * @return 结果
     */
    @Override
    public int deleteLiveWatchUserById(Long id)
    {
        return baseMapper.deleteLiveWatchUserById(id);
    }

    @Override
    public List<LiveWatchUser> getByLiveIdAndUserId(long liveId, long userId) {
        // 先查缓存，获取liveFlag和replayFlag
        Map<String, Integer> flagMap = getLiveFlagWithCache(liveId);
        Map<String, Object> params = new HashMap<>();
        params.put("liveId", liveId);
        params.put("userId", userId);
        params.put("liveFlag", flagMap.get("liveFlag"));
        params.put("replayFlag", flagMap.get("replayFlag"));
        return baseMapper.selectUserByLiveIdAndUserId(params);
    }

    /**
     * 获取直播间的直播/回放状态（带缓存）
     * @param liveId 直播间ID
     * @return Map包含liveFlag和replayFlag
     */
    @Override
    public Map<String, Integer> getLiveFlagWithCache(Long liveId) {
        String cacheKey = String.format(LiveKeysConstant.LIVE_FLAG_CACHE, liveId);

        // 先查缓存
        Map<String, Integer> cached = redisCache.getCacheObject(cacheKey);
        if (cached != null && cached.containsKey("liveFlag") && cached.containsKey("replayFlag")) {
            return cached;
        }

        // 缓存不存在，查询数据库
        Integer liveFlag = liveMapper.selectLiveFlagByLiveId(liveId);
        if (liveFlag == null) {
            liveFlag = 0;
        }
        Integer replayFlag = 1 - liveFlag; // 反数

        // 构建结果
        Map<String, Integer> result = new HashMap<>();
        result.put("liveFlag", liveFlag);
        result.put("replayFlag", replayFlag);

        // 缓存结果，过期时间1分钟
        redisCache.setCacheObject(cacheKey, result, LiveKeysConstant.LIVE_FLAG_CACHE_EXPIRE, TimeUnit.SECONDS);

        return result;
    }

    @Override
    public LiveWatchUser join(long liveId, long userId, String location) {
        FsUserScrm fsUserVO = fsUserService.selectFsUserByUserId(userId);
        Date now = DateUtils.getNowDate();

        // 查询直播间信息
        Live live = liveMapper.selectLiveByLiveId(liveId);
        if (live == null) {
            throw new RuntimeException("直播间不存在");
        }

        // 获取直播/回放状态（带缓存）
        Map<String, Integer> flagMap = getLiveFlagWithCache(liveId);
        Integer liveFlag = flagMap.get("liveFlag");
        Integer replayFlag = flagMap.get("replayFlag");

        // 使用唯一索引查询：live_id, user_id, live_flag, replay_flag
        LiveWatchUser liveWatchUser = baseMapper.selectByUniqueIndex(liveId, userId, liveFlag, replayFlag);

        if (liveWatchUser != null) {
            // 存在则更新
            liveWatchUser.setUpdateTime(now);
            liveWatchUser.setOnline(0);
            if (StringUtils.isNotEmpty(location)) {
                liveWatchUser.setLocation(location);
            }
            baseMapper.updateLiveWatchUser(liveWatchUser);
        } else {
            // 不存在则插入
            liveWatchUser = new LiveWatchUser();
            liveWatchUser.setLiveId(liveId);
            liveWatchUser.setUserId(userId);
            liveWatchUser.setAvatar(fsUserVO.getAvatar());
            liveWatchUser.setMsgStatus(0);
            liveWatchUser.setOnline(0);
            liveWatchUser.setLocation(location);
            liveWatchUser.setLiveFlag(liveFlag);
            liveWatchUser.setReplayFlag(replayFlag);
            liveWatchUser.setCreateTime(now);
            liveWatchUser.setUpdateTime(now);
            baseMapper.insertLiveWatchUser(liveWatchUser);
        }

        liveWatchUser.setAvatar(fsUserVO.getAvatar());
        liveWatchUser.setNickName(fsUserVO.getNickname());
        String hashKey = String.format(LiveKeysConstant.LIVE_WATCH_USERS, liveId);
        redisCache.hashPut(hashKey, String.valueOf(userId), JSON.toJSONString(liveWatchUser));
        return liveWatchUser;
    }

    @Override
    public LiveWatchUser joinWithoutLocation(long liveId, long userId) {
        FsUserScrm fsUserVO = fsUserService.selectFsUserByUserId(userId);
        Date now = DateUtils.getNowDate();

        // 查询直播间信息
        Live live = liveMapper.selectLiveByLiveId(liveId);
        if (live == null) {
            throw new RuntimeException("直播间不存在");
        }

        // 获取直播/回放状态（带缓存）
        Map<String, Integer> flagMap = getLiveFlagWithCache(liveId);
        Integer liveFlag = flagMap.get("liveFlag");
        Integer replayFlag = flagMap.get("replayFlag");

        // 使用唯一索引查询：live_id, user_id, live_flag, replay_flag
        LiveWatchUser liveWatchUser = baseMapper.selectByUniqueIndex(liveId, userId, liveFlag, replayFlag);

        if (liveWatchUser != null) {
            // 存在则更新
            liveWatchUser.setUpdateTime(now);
            liveWatchUser.setOnline(0);
            baseMapper.updateLiveWatchUser(liveWatchUser);
        } else {
            // 不存在则插入
            liveWatchUser = new LiveWatchUser();
            liveWatchUser.setLiveId(liveId);
            liveWatchUser.setUserId(userId);
            liveWatchUser.setAvatar(fsUserVO.getAvatar());
            liveWatchUser.setMsgStatus(0);
            liveWatchUser.setOnline(0);
            liveWatchUser.setLiveFlag(liveFlag);
            liveWatchUser.setReplayFlag(replayFlag);
            liveWatchUser.setCreateTime(now);
            liveWatchUser.setUpdateTime(now);
            baseMapper.insertLiveWatchUser(liveWatchUser);
        }

        liveWatchUser.setAvatar(fsUserVO.getAvatar());
        liveWatchUser.setNickName(fsUserVO.getNickname());
        String hashKey = String.format(LiveKeysConstant.LIVE_WATCH_USERS, liveId);
        redisCache.hashPut(hashKey, String.valueOf(userId), JSON.toJSONString(liveWatchUser));
        return liveWatchUser;
    }
    @Override
    public LiveWatchUser close(long liveId, long userId) {

        // 查询直播间信息
        Live live = liveMapper.selectLiveByLiveId(liveId);
        if (live == null) {
            throw new RuntimeException("直播间不存在");
        }

        // 获取直播/回放状态（带缓存）
        Map<String, Integer> flagMap = getLiveFlagWithCache(liveId);
        Integer liveFlag = flagMap.get("liveFlag");
        Integer replayFlag = flagMap.get("replayFlag");

        // 使用唯一索引查询：live_id, user_id, live_flag, replay_flag
        LiveWatchUser liveWatchUser = baseMapper.selectByUniqueIndex(liveId, userId, liveFlag, replayFlag);
        // 设置在线时长
        try {
            Long onlineSeconds = liveWatchUser.getOnlineSeconds();
            if(onlineSeconds == null) onlineSeconds = 0L;
            liveWatchUser.setOnlineSeconds(onlineSeconds + (System.currentTimeMillis() - liveWatchUser.getUpdateTime().getTime()));
        } catch (Exception e) {
            log.error("设置在线时长异常：{}", e.getMessage());
        }
        liveWatchUser.setUpdateTime(DateUtils.getNowDate());
        liveWatchUser.setOnline(1);
        baseMapper.updateLiveWatchUser(liveWatchUser);
        String hashKey  = String.format(LiveKeysConstant.LIVE_WATCH_USERS, liveId);
        redisCache.hashDelete(hashKey, String.valueOf(userId));
        return liveWatchUser;
    }

    /**
     * 查询直播间在线用户列表
     * @param params 参数
     * @return list
     */
    @Override
    public List<LiveWatchUserVO> selectWatchUserList(Map<String, Object> params) {
        // 先查缓存，获取liveFlag和replayFlag
        if (params != null && params.containsKey("liveId")) {
            Long liveId = Long.valueOf(params.get("liveId").toString());
            Map<String, Integer> flagMap = getLiveFlagWithCache(liveId);
            params.put("liveFlag", flagMap.get("liveFlag"));
            params.put("replayFlag", flagMap.get("replayFlag"));
        }
        return baseMapper.selectWatchUserListByLiveId(params);
    }

    /**
     * 修改直播间用户禁言状态
     * @param liveId    直播间ID
     * @param userId    用户ID
     * @return  受影响条数
     */
    @Override
    public int changeUserState(Long liveId, Long userId) {
        List<LiveWatchUser> liveWatchUser = getByLiveIdAndUserId(liveId, userId);
        if (!liveWatchUser.isEmpty()) {
            for (LiveWatchUser watchUser : liveWatchUser) {
                watchUser.setMsgStatus(Math.abs(1 - watchUser.getMsgStatus()));
                watchUser.setUpdateTime(DateUtils.getNowDate());
                baseMapper.updateLiveWatchUser(watchUser);
            }
            return 1;
        }
        return 0;
    }

    /**
     * 根据直播间ID和用户ID查询观看用户信息
     * @param liveId    直播间ID
     * @param userId    观看用户ID
     * @return LiveWatchUserVO
     */
    @Override
    public LiveWatchUserVO selectWatchUserByLiveIdAndUserId(Long liveId, Long userId) {
        // 先查缓存，获取liveFlag和replayFlag
        Map<String, Integer> flagMap = getLiveFlagWithCache(liveId);
        Map<String, Object> params = new HashMap<>();
        params.put("liveId", liveId);
        params.put("userId", userId);
        params.put("liveFlag", flagMap.get("liveFlag"));
        params.put("replayFlag", flagMap.get("replayFlag"));
        return baseMapper.selectWatchUserByLiveIdAndUserId(params);
    }

    @Override
    public List<LiveWatchUserVO> selectOnlineUserList(LiveWatchUser param) {
        // 先查缓存，获取liveFlag和replayFlag
        if (param != null && param.getLiveId() != null) {
            Map<String, Integer> flagMap = getLiveFlagWithCache(param.getLiveId());
            param.setLiveFlag(flagMap.get("liveFlag"));
            param.setReplayFlag(flagMap.get("replayFlag"));
        }
        return baseMapper.selectOnlineUserList(param);
    }

    @Override
    public List<LiveWatchUser> checkOnlineNoRewardUser(Long liveId, Date now) {
        // 先查缓存，获取liveFlag和replayFlag
        Map<String, Integer> flagMap = getLiveFlagWithCache(liveId);
        Map<String, Object> params = new HashMap<>();
        params.put("liveId", liveId);
        params.put("now", now);
        params.put("liveFlag", flagMap.get("liveFlag"));
        params.put("replayFlag", flagMap.get("replayFlag"));
        return baseMapper.checkOnlineNoRewardUser(params);
    }

    @Override
    public int blockUser(Long userId) {
        FsUserScrm fsUser = new FsUserScrm();
        fsUser.setUserId(userId);
        fsUser.setStatus(0);
        return fsUserService.updateFsUser(fsUser);
    }

    @Override
    public List<LiveWatchUser> selectLiveWatchAndRegisterUser(Long liveId, Long lotteryId) {
        // 先查缓存，获取liveFlag和replayFlag
        Map<String, Integer> flagMap = getLiveFlagWithCache(liveId);
        Map<String, Object> params = new HashMap<>();
        params.put("liveId", liveId);
        params.put("lotteryId", lotteryId);
        params.put("liveFlag", flagMap.get("liveFlag"));
        params.put("replayFlag", flagMap.get("replayFlag"));
        return baseMapper.selectLiveWatchAndRegisterUser(params);
    }

    @Override
    public List<LiveWatchUserVO> asyncToCache(Long liveId) {
        LiveWatchUser liveWatchUser = new LiveWatchUser();
        liveWatchUser.setLiveId(liveId);
        List<LiveWatchUserVO> liveWatchUserVOS = selectOnlineUserList(liveWatchUser);

        log.info("开始同步直播在线人数到缓存，共{}条数据", liveWatchUserVOS.size());
        if (CollUtil.isNotEmpty(liveWatchUserVOS)){
            ThreadUtil.execute(()->{
                String hashKey  = String.format(LiveKeysConstant.LIVE_WATCH_USERS, liveId);
                // 清空数据
                redisCache.deleteObject(hashKey);
                Map<String, String> collect = liveWatchUserVOS.stream()
                        .collect(Collectors.toMap(
                                watchUserVO -> String.valueOf(watchUserVO.getUserId()),
                                JSON::toJSONString
                        ));
                redisCache.hashPut(hashKey,collect);
                log.info("同步直播在线人数到缓存完成");
            });
        }
        return liveWatchUserVOS;
    }

    @Override
    public R liveUserTotals(LiveWatchUser liveWatchUser) {
        LiveWatchUserStatistics liveWatchUserStatistics = baseMapper.liveUserTotals(liveWatchUser);
        if(liveWatchUserStatistics == null)
        {
            liveWatchUserStatistics = new LiveWatchUserStatistics();
            liveWatchUserStatistics.setOnline(0);
            liveWatchUserStatistics.setOffline(0);
            liveWatchUserStatistics.setSilenced(0);
            liveWatchUserStatistics.setAl(0);
            return R.ok().put("data", liveWatchUserStatistics);
        }
        if(liveWatchUserStatistics.getOnline() == null)
        {
            liveWatchUserStatistics.setOnline(0);
        }
        if (liveWatchUserStatistics.getOffline() == null) {
            liveWatchUserStatistics.setOffline(0);
        }
        if (liveWatchUserStatistics.getSilenced() == null) {
            liveWatchUserStatistics.setSilenced(0);
        }
        if (liveWatchUserStatistics.getAl() == null) {
            liveWatchUserStatistics.setAl(0);
        }
        return R.ok().put("data", liveWatchUserStatistics);
    }

    @Override
    public List<LiveWatchUserVO> dashBoardWatchUserList(Map<String, Object> param) {
        // 先查缓存，获取liveFlag和replayFlag
        if (param != null && param.containsKey("liveId")) {
            Long liveId = Long.valueOf(param.get("liveId").toString());
            Map<String, Integer> flagMap = getLiveFlagWithCache(liveId);
            param.put("liveFlag", flagMap.get("liveFlag"));
            param.put("replayFlag", flagMap.get("replayFlag"));
        }
        if (param != null && param.containsKey("all") && "1".equals(param.get("all"))) {
            return baseMapper.selectWatchUserListAllByLiveId(param);
        } else {
            if(param != null && param.containsKey("msgStatus") && "1".equals(param.get("msgStatus")) && param.containsKey("online") ){
                param.remove("online");
            }
            return baseMapper.selectWatchUserListByLiveId(param);
        }
    }

    @Override
    public void updateGlobalVisible(long liveId, int status) {
        baseMapper.updateGlobalVisible(liveId, status);
    }

    @Override
    public void updateSingleVisible(long liveId, Integer status, long userId) {
        baseMapper.updateSingleVisible(liveId, status,userId);
    }

    @Override
    public LiveWatchUser selectLiveWatchUserByFlag(Long liveId, Long userId, Integer liveFlag, Integer replayFlag) {
        return baseMapper.selectByUniqueIndex(liveId, userId, liveFlag, replayFlag);
    }

}
