package com.liquidnet.service.goblin.service.impl;

import com.liquidnet.commons.lang.util.CollectionUtil;
import com.liquidnet.commons.lang.util.CurrentUtil;
import com.liquidnet.commons.lang.util.DateUtil;
import com.liquidnet.commons.lang.util.IDGenerator;
import com.liquidnet.service.adam.dto.vo.AdamUserInfoVo;
import com.liquidnet.service.base.ErrorMapping;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.base.SqlMapping;
import com.liquidnet.service.base.constant.MQConst;
import com.liquidnet.service.goblin.dto.manage.vo.GoblinGoodsAnticipateValueVo;
import com.liquidnet.service.goblin.dto.manage.vo.HelpValueVo;
import com.liquidnet.service.goblin.dto.vo.*;
import com.liquidnet.service.goblin.service.IGoblinGoodsAnticipateService;
import com.liquidnet.service.goblin.util.GoblinAnticipateUtils;
import com.liquidnet.service.goblin.util.GoblinMongoUtils;
import com.liquidnet.service.goblin.util.GoblinRedisUtils;
import com.liquidnet.service.goblin.util.QueueUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.unit.DataUnit;

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.LinkedList;
import java.util.List;

import static com.liquidnet.commons.lang.util.DateUtil.DTF_YMD_HMS;

/**
 * <p>
 * 预约表 服务实现类
 * </p>
 *
 * @author liquidnet
 * @since 2022-04-07
 */
@Service
@Slf4j
public class GoblinGoodsAnticipateServiceImpl implements IGoblinGoodsAnticipateService {


    @Autowired
    GoblinRedisUtils goblinRedisUtils;

    @Autowired
    QueueUtils queueUtils;

    @Autowired
    GoblinAnticipateUtils goblinAnticipateUtils;

    @Autowired
    GoblinMongoUtils goblinMongoUtils;

    @Override
    public ResponseDto<Boolean> userAbout(String skuId) {
        //查询该skuId是否能被预约
        GoblinGoodsAnticipateValueVo anticipateValueVo = goblinRedisUtils.getValueBySkuId(skuId);
        if (anticipateValueVo != null) {
            anticipateValueVo.setState(GoblinAnticipateUtils.setState(anticipateValueVo.getAboutStartDate(), anticipateValueVo.getAboutEndDate()));
            if (!anticipateValueVo.getState().equals(1)) {
                return ResponseDto.failure(ErrorMapping.get(150007));
            }
            //查询该用户是否预
            String uid = CurrentUtil.getCurrentUid();
            return getBooleanResponseDto(skuId, uid, anticipateValueVo);
        }
        return ResponseDto.failure(ErrorMapping.get(150005));
    }

    private ResponseDto<Boolean> getBooleanResponseDto(String skuId, String uid, GoblinGoodsAnticipateValueVo anticipateValueVo) {
        GoblinGoodAnticipateUserVo userVo = goblinRedisUtils.getUserAboutAut(skuId, uid);
        if (userVo == null) {
            //接入助力人数判断
            //获取需要多少人助力
//                GoblinGoodsAnticipateHelp sharePeopleBySkuId = goblinRedisUtils.getSharePeopleBySkuId(skuId);
            //判断如果所需助力人数
            if (anticipateValueVo.getPeopleType() != 0) {
                //用户得到助力人数
                String sid = goblinRedisUtils.getShare(skuId, uid);
                if (sid != null) {
                    Integer people = goblinRedisUtils.getHelpSidAddHelp(sid);
                    if (anticipateValueVo.getPeopleType() > people) {
                        log.debug(" skuId：{}，分享sid：{}，预约uid：{}，需要助力人数：{}，助力人数：{}", skuId, sid, uid, anticipateValueVo.getPeopleType(), people);
                        return ResponseDto.failure("预约失败！");
                    }
                } else {
                    log.debug("skuId:{}，需要助力人数：{}，uid:{}，该用户未开启分享助力！", skuId, anticipateValueVo.getPeopleType(), uid);
                    return ResponseDto.failure("预约失败！");
                }
            }
            uidAboutBySkuId(skuId, uid, null);
        }
        return ResponseDto.success();
    }

    private void uidAboutBySkuId(String skuId, String uid, String avatar) {
        GoblinGoodAnticipateUserVo user = new GoblinGoodAnticipateUserVo();
        user.setUid(uid);
        user.setSkuId(skuId);
        String mobile = StringUtils.defaultString(((String) CurrentUtil.getTokenClaims().get(CurrentUtil.TOKEN_MOBILE)), "");
        user.setPhone(mobile);
        user.setState(0);
        user.setCreatedDate(LocalDateTime.now());
        //mongodb记录
        goblinRedisUtils.setUserAboutSku(user);
        //用户没有预约过
        //发送redis消息修改mysql记录用户预约
        LinkedList<Object[]> sqlValue = CollectionUtil.linkedListObjectArr();
        sqlValue.add(new Object[]{
                user.getUid(),
                skuId,
                user.getPhone(),
                0,
                user.getCreatedDate()
        });
        sendRedis("goblin_goods_anticipate_user", sqlValue);
        goblinRedisUtils.setSkuIdPeople(skuId);
        //获取用户头像个数小于等于2则保存用户头像
        List<String> userAvatar = goblinRedisUtils.getUserAvatar(skuId);
        if (userAvatar != null && userAvatar.size() <= 2) {
            //获取预约人头像
            if (avatar == null) {
                avatar = goblinAnticipateUtils.getUserInfo().getAvatar();
            }
            goblinRedisUtils.setUserAvatar(skuId, avatar);
        }
    }

    @Override
    public ResponseDto<Boolean> selectAnticipate(String skuId) {
        String uid = CurrentUtil.getCurrentUid();
        return ResponseDto.success(goblinRedisUtils.getUserAboutAut(skuId, uid) != null);
    }

    @Override
    public ResponseDto<String> share(String skuId) {
        //查询是否可以预约
        GoblinGoodsAnticipateValueVo valueBySkuId = goblinRedisUtils.getValueBySkuId(skuId);
        if (valueBySkuId == null) {
            return ResponseDto.failure(ErrorMapping.get(150005));
        }
        Integer integer = GoblinAnticipateUtils.setState(valueBySkuId.getAboutStartDate(), valueBySkuId.getAboutEndDate());
        if (integer != null && !integer.equals(1)) {
            return ResponseDto.failure(ErrorMapping.get(150006));
        }

        //获取用户uid
        String uid = CurrentUtil.getCurrentUid();
        //可以创建分享
        //查询redis关联记录
        String sid = goblinRedisUtils.getShare(skuId, uid);
        if (sid != null) {
            return ResponseDto.failure("0", "已开启助力", sid);
        } else {
            //查询sku需要助力人数
            //Integer skuIdPeople = goblinRedisUtils.getSharePeopleBySkuId(skuId);

            sid = IDGenerator.nextTimeId2();
            GoblinGoodsAnticipateShareVo goblinGoodsAnticipateShareVo = GoblinGoodsAnticipateShareVo.getNew();
            goblinGoodsAnticipateShareVo.setSid(sid);
            goblinGoodsAnticipateShareVo.setUid(uid);
            goblinGoodsAnticipateShareVo.setSkuId(skuId);
            goblinGoodsAnticipateShareVo.setType(valueBySkuId.getType());
            goblinGoodsAnticipateShareVo.setPeopleType(valueBySkuId.getPeopleType());
            //存入用户头像
            AdamUserInfoVo userInfo = goblinAnticipateUtils.getUserInfo();
            goblinGoodsAnticipateShareVo.setAvatar(userInfo.getAvatar());
            goblinGoodsAnticipateShareVo.setNickname(userInfo.getNickname());
            goblinGoodsAnticipateShareVo.setCreatedDate(LocalDateTime.now());
            goblinGoodsAnticipateShareVo.setAboutStartDate(valueBySkuId.getAboutStartDate());
            goblinGoodsAnticipateShareVo.setAboutEndDate(valueBySkuId.getAboutEndDate());
            goblinGoodsAnticipateShareVo.setHelpPeople(0);
            goblinGoodsAnticipateShareVo.setAvatarImgList(CollectionUtil.arrayListString());
            //开启助力
            //mongodb缓存
            //goblinMongoUtils.setGoblinGoodsAnticipateShareVo(goblinGoodsAnticipateShareVo);

            //redis缓存
            Duration between = Duration.between(valueBySkuId.getAboutStartDate(), valueBySkuId.getAboutEndDate());
            goblinRedisUtils.setShare(skuId, uid, sid, between.toDays());

            //redis存储用户分享
            goblinRedisUtils.setShareVo(goblinGoodsAnticipateShareVo);


            //redis消息  MySQL
            LinkedList<Object[]> sqlValue = CollectionUtil.linkedListObjectArr();
            sqlValue.add(new Object[]{
                    goblinGoodsAnticipateShareVo.getSid(),
                    goblinGoodsAnticipateShareVo.getUid(),
                    goblinGoodsAnticipateShareVo.getSkuId(),
//                    goblinGoodsAnticipateShareVo.getUrl(),
                    goblinGoodsAnticipateShareVo.getCreatedDate()
            });
            sendRedis("goblin_goods_anticipate_share", sqlValue);
            return ResponseDto.success(sid);
        }
    }

    @Override
    public ResponseDto<String> help(String sid) {

        //查询是否可以预约
        GoblinGoodsAnticipateShareVo shareVo = goblinRedisUtils.getShareVo(sid);
        if (shareVo == null) {
            return ResponseDto.failure(ErrorMapping.get(150001));
        }
        Integer integer = GoblinAnticipateUtils.setState(shareVo.getAboutStartDate(), shareVo.getAboutEndDate());
        if (integer != null && !integer.equals(1)) {
            return ResponseDto.failure(ErrorMapping.get(150002));
        }

        //获取uid
        String uid = CurrentUtil.getCurrentUid();

        if (shareVo.getUid().equals(uid)) {
            return ResponseDto.failure(ErrorMapping.get(150003));
        }
        //查询mongodb 是否助力过该分享
//        GoblinGoodsAnticipateHelpVo goodsAnticipateHelpVo = goblinMongoUtils.getHelpVo(sid, uid);

        //redis缓存
        Integer help = goblinRedisUtils.getHelpByUidAndSid(uid, sid);

        if (help == null) {
            GoblinGoodsAnticipateHelpVo helpVo = GoblinGoodsAnticipateHelpVo.getNew();
            helpVo.setHelpUid(uid);
            helpVo.setSid(sid);
            helpVo.setCreateDate(LocalDateTime.now());
            //mongodb缓存
//            goblinMongoUtils.setHelpVo(helpVo);

            //记录助力人数头像（前六个）
            List<String> helpUserAvatar = goblinRedisUtils.getHelpUserAvatar(sid);
            if (helpUserAvatar.size() <= 6) {
                //获取用户头像保存
                AdamUserInfoVo userInfo = goblinAnticipateUtils.getUserInfo();
                if (userInfo != null) {
                    //新增助力头像
                    goblinRedisUtils.setHelpUserAvatar(sid, userInfo.getAvatar());
                } else {
                    return ResponseDto.failure(ErrorMapping.get(150008));
                }
            }

            //加入redis缓存
            Duration between = Duration.between(shareVo.getAboutStartDate(), shareVo.getAboutEndDate());
            goblinRedisUtils.setHelpByUidAndSid(uid, sid, between.toDays());

            //此助力sid人数+1
            goblinRedisUtils.setHelpSidAddHelp(sid);

            //redis消息   MySQL插入
            LinkedList<Object[]> sqlValue = CollectionUtil.linkedListObjectArr();
            sqlValue.add(new Object[]{
                    helpVo.getSid(),
                    helpVo.getHelpUid(),
                    helpVo.getCreateDate()
            });
            sendRedis("goblin_goods_anticipate_help", sqlValue);

            //判断主力人数是否达标，达标则自动预约
            if (shareVo.getPeopleType().equals(goblinRedisUtils.getHelpSidAddHelp(sid))) {
                //主力人数达到可预约条件
                uidAboutBySkuId(shareVo.getSkuId(), shareVo.getUid(), shareVo.getAvatar());
            }
            return ResponseDto.success();
        } else {
            log.debug("help()  false ------> sid:{}", sid);
            return ResponseDto.failure(ErrorMapping.get(150004));
        }
    }

    @Override
    public ResponseDto<HelpValueVo> getHelpValue(String sid) {
        //获取分享助力信息
        GoblinGoodsAnticipateShareVo shareVo = goblinRedisUtils.getShareVo(sid);
        if (shareVo != null) {
            HelpValueVo helpValueVo = HelpValueVo.getNew();
            helpValueVo.copy(shareVo);
            return ResponseDto.success(helpValueVo);
        }
        return ResponseDto.failure(ErrorMapping.get(150001));
    }

    @Override
    public ResponseDto<String> getTurnOnHelp(String skuId) {
        String uid = CurrentUtil.getCurrentUid();
        return ResponseDto.success(goblinRedisUtils.getShare(skuId, uid));
    }

    @Override
    public ResponseDto<Boolean> helpSid(String sid) {
        String uid = CurrentUtil.getCurrentUid();
        Integer help = goblinRedisUtils.getHelpByUidAndSid(uid, sid);
        if (help == null) {
            return ResponseDto.success(false);
        }
        return ResponseDto.success(true);
    }

    public void sendRedis(String sqlKey, LinkedList<Object[]> sqlData) {
        LinkedList<String> sql = CollectionUtil.linkedListString();
        sql.add(SqlMapping.get(sqlKey));
        String sqlStr = SqlMapping.gets(sql, sqlData);
        queueUtils.sendMsgByRedis(
                MQConst.GoblinQueue.GOBLIN_STORE_MARKET.getKey(),
                sqlStr);
    }

    @Override
    public ResponseDto<Boolean> reserveByMix(String mixId) {
        //获取udi
        String uid = CurrentUtil.getCurrentUid();
        String nowTime = DateUtil.getNowTime();
        //redis查询用户预约组合购记录
        if (goblinRedisUtils.getReserveMixByUid(uid, mixId) == null) {
            //该混合狗能否被预约
            GoblinMixDetailsVo mixDetails = goblinRedisUtils.getMixDetails(mixId);
            //组合购开启预约且当前时间大于预约购开始时间或者上架时间才可预约
            if (mixDetails.getReserve() != 0 && DateUtil.compareStrDay(nowTime, mixDetails.getTimeStart()) <= 0) {
                String mid = IDGenerator.nextTimeId2();
                GoblinMixReserveVo goblinMixReserveVo = GoblinMixReserveVo.getNew();
                goblinMixReserveVo.setMid(mid);
                goblinMixReserveVo.setMixId(mixId);
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DateUtil.DATE_FULL_STR);
                goblinMixReserveVo.setCreatedDate(LocalDateTime.parse(nowTime,formatter));
                goblinMixReserveVo.setUid(uid);
                String mobile = StringUtils.defaultString(((String) CurrentUtil.getTokenClaims().get(CurrentUtil.TOKEN_MOBILE)), "");
                goblinMixReserveVo.setPhone(mobile);
                //redis保存用户预约组合购记录
                goblinRedisUtils.setReserveMixByUid(goblinMixReserveVo);
                //发送redis消息修改mysql记录用户预约
                LinkedList<Object[]> sqlValue = CollectionUtil.linkedListObjectArr();
                sqlValue.add(new Object[]{
                        mid,
                        uid,
                        mobile,
                        mixId
                });
                sendRedis("goblin_goods_anticipate_mix", sqlValue);
            }
        }
        return ResponseDto.success(true);
    }

    @Override
    public ResponseDto<Boolean> reserveMixByUid(String mixId) {
        //获取udi
        String uid = CurrentUtil.getCurrentUid();
        return ResponseDto.success(goblinRedisUtils.getReserveMixByUid(uid, mixId) != null);
    }

}
