package com.fs.app.facade.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.fs.app.facade.LiveFacadeService;
import com.fs.common.constant.LiveKeysConstant;
import com.fs.common.core.controller.BaseController;
import com.fs.common.core.domain.R;
import com.fs.common.core.page.PageRequest;
import com.fs.common.core.page.TableDataInfo;
import com.fs.common.core.redis.RedisCache;
import com.fs.live.domain.*;
import com.fs.framework.aspectj.lock.DistributeLock;
import com.fs.live.param.CouponPO;
import com.fs.live.param.LotteryPO;
import com.fs.live.param.RedPO;
import com.fs.live.service.*;
import com.fs.live.vo.*;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class LiveFacadeServiceImpl extends BaseController implements LiveFacadeService {

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private ILiveService liveService;

    @Autowired
    private ILiveWatchUserService liveWatchUserService;
    @Autowired
    private ILiveUserRedRecordService liveUserRedRecordService;
    @Autowired
    private ILiveUserLotteryRecordService liveUserLotteryRecordService;

    @Autowired
    private ILiveLotteryRegistrationService liveLotteryRegistrationService;
    @Autowired
    private ILiveRedConfService iLiveRedConfService;
    @Autowired
    private ILiveCouponService iLiveCouponService;

    @Autowired
    private ILiveLotteryConfService liveLotteryConfService;

    @Override
    public R liveList(PageRequest pageRequest) {
        int start = (pageRequest.getCurrentPage() - 1) * pageRequest.getPageSize();
        int end = pageRequest.getCurrentPage() * pageRequest.getPageSize() - 1;

        List<Live> lives = null;
        // 查询缓存中的直播列表数据
        Set<Object> liveList = redisCache.zSetReverseRange(
                LiveKeysConstant.LIVE_HOME_PAGE_LIST,
                start,
                end
        );
        if (CollUtil.isNotEmpty(liveList)) {
            lives = liveList.stream()
                    .map(String.class::cast)
                    .map(json -> JSON.parseObject(json, Live.class))
                    .collect(Collectors.toList());
            PageInfo<Live> result = new PageInfo<>(lives);
            result.setTotal(redisCache.zSetSize(LiveKeysConstant.LIVE_HOME_PAGE_LIST));
            return R.ok().put("data", result);
        } else {
            lives = liveService.asyncToCache();

            // 对结果进行分页处理
            List<Live> pageLives = lives.stream()
                    .skip(start)
                    .limit(pageRequest.getPageSize())
                    .collect(Collectors.toList());

            PageInfo<Live> result = new PageInfo<>(pageLives);
            result.setTotal(lives.size());
            return R.ok().put("data", result);
        }
    }

    @Override
    public TableDataInfo watchUserList(LiveWatchUser param) {
        List<LiveWatchUserVO> liveWatchUserVOS;
        String setKey = String.format(LiveKeysConstant.LIVE_WATCH_USERS, param.getLiveId());
        Map<Object, Object> hashEntries = redisCache.hashEntries(setKey);
        if (CollUtil.isEmpty(hashEntries)) {
            liveWatchUserVOS = liveWatchUserService.asyncToCache(param.getLiveId());
        } else {
            liveWatchUserVOS = hashEntries.values().stream()
                    .map(value -> {
                        try {
                            return JSONUtil.toBean(JSONUtil.parseObj(value), LiveWatchUserVO.class);
                        } catch (Exception e) {
                            log.error("反序列化LiveWatchUserVO失败: {}", value, e);
                            return null;
                        }
                    })
                    .filter(Objects::nonNull)
                    .collect(Collectors.toList());
        }
        return getDataTable(liveWatchUserVOS);
    }

    @Override
    public R liveDetail(Long id) {
        Object o = redisCache.hashGet(LiveKeysConstant.LIVE_HOME_PAGE_DETAIL, String.valueOf(id));
        LiveVo liveVo;
        if (ObjectUtil.isNotEmpty(o)) {
            liveVo = JSON.parseObject(o.toString(), LiveVo.class);
        } else {
            liveVo = liveService.asyncToCacheLiveDetail(id);
        }
        if (ObjectUtil.isEmpty(liveVo)) {
            R.error("未找到直播");
        }
        if(liveVo.getIsShow() == 2) {
            return R.error("直播未开放");
        }
        return R.ok().put("data", liveVo);
    }

    @Override
    public R currentActivities(Long liveId, String userId) {
        // 直播间配置信息
        Object oLiveConfigVo = redisCache.getCacheObject(String.format(LiveKeysConstant.LIVE_HOME_PAGE_CONFIG, liveId, liveId));
        LiveConfigVo liveConfigVo;
        if (ObjectUtil.isNotEmpty(oLiveConfigVo)) {
            liveConfigVo = JSON.parseObject(oLiveConfigVo.toString(), LiveConfigVo.class);
        } else {
            liveConfigVo = liveService.asyncToCacheLiveConfig(liveId);
        }
        List<LiveRedConf> redConfs = liveConfigVo.getLiveRedConfs()
                .stream()
                .filter(item -> ObjectUtil.isEmpty(redisCache.hashGet(String.format(LiveKeysConstant.LIVE_HOME_PAGE_CONFIG_RED, liveId, item.getRedId()), userId)))
                .collect(Collectors.toList());
        List<LiveLotteryConfVo> lotteryConfs = liveConfigVo.getLiveLotteryConfs()
                .stream()
                .filter(item -> ObjectUtil.isEmpty(redisCache.hashGet(String.format(LiveKeysConstant.LIVE_HOME_PAGE_CONFIG_RED, liveId, item.getLotteryId()), userId)))
                .collect(Collectors.toList());
        Object cacheObject = redisCache.getCacheObject(String.format(LiveKeysConstant.LIVE_HOME_PAGE_CONFIG, liveId, LiveKeysConstant.TOP_MSG));
        LiveMsgVo liveMsg;
        if (ObjectUtil.isNotEmpty(cacheObject)) {
            liveMsg = JSON.parseObject(cacheObject.toString(), LiveMsgVo.class);
        } else {
            liveMsg = null;
        }

        return R.ok()
                .put("red", redConfs)
                .put("lottery", lotteryConfs)
                .put("goods", liveConfigVo.getLiveGoodsVo())
                .put("topMsg", liveMsg);
    }

    @Override
    @DistributeLock(keyExpression = "#red.redId +'_'+#red.userId", scene = "red_claim", waitTime = 1000, errorMsg = "红包领取失败")
    public R redClaim(RedPO red) {
        return iLiveRedConfService.claimRedPacket(red);
    }

    @Override
    @DistributeLock(keyExpression = "#coupon.couponIssueId +'_'+#coupon.userId", scene = "coupon_claim", waitTime = 1000, errorMsg = "优惠券领取失败")
    public R couponClaim(CouponPO coupon) {
        return iLiveCouponService.claimCoupon(coupon);
    }

    @Override
    @DistributeLock(keyExpression = "#lottery.liveId +'_'+#lottery.userId", scene = "draw_claim")
    public R drawClaim(LotteryPO lottery) {
        Object o = redisCache.hashGet(String.format(LiveKeysConstant.LIVE_HOME_PAGE_CONFIG_DRAW, lottery.getLiveId(), lottery.getLotteryId()), String.valueOf(lottery.getUserId()));
        if (ObjectUtil.isNotEmpty(o)) {
            return R.ok("您已参加抽奖活动，请等待开奖！");
        }
        LiveLotteryRegistration registration = new LiveLotteryRegistration();
        Date now = new Date();
        registration.setLiveId(lottery.getLiveId());
        registration.setUserId(lottery.getUserId());
        registration.setLotteryId(lottery.getLotteryId());
        registration.setIsWin(0L);
        registration.setRizeLevel(-1L);
        registration.setCreateTime(now);
        registration.setUpdateTime(now);
        redisCache.hashPut(String.format(LiveKeysConstant.LIVE_HOME_PAGE_CONFIG_DRAW, lottery.getLiveId(), lottery.getLotteryId()), String.valueOf(lottery.getUserId()), JSONUtil.toJsonStr(registration));
        // 通过定时任务入库
        // liveLotteryRegistrationService.insertLiveLotteryRegistration(registration);
        return R.ok("参与抽奖成功！请在直播间等待开奖");
    }
}
