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

import com.github.pagehelper.PageInfo;
import com.liquidnet.commons.lang.util.CollectionUtil;
import com.liquidnet.commons.lang.util.IDGenerator;
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.GoblinGoodsAnticipateAddParam;
import com.liquidnet.service.goblin.dto.manage.GoblinGoodsAnticipateUpdateParam;
import com.liquidnet.service.goblin.dto.manage.GoblinGoodsAnticipateValueAddParam;
import com.liquidnet.service.goblin.dto.manage.GoblinGoodsAnticipateValueParam;
import com.liquidnet.service.goblin.dto.manage.vo.GoblinGoodsAnticipateValueVo;
import com.liquidnet.service.goblin.dto.vo.GoblinGoodAnticipateUserVo;
import com.liquidnet.service.goblin.dto.vo.GoblinGoodsAnticipateVo;
import com.liquidnet.service.goblin.service.IGoblinGoodsAnticipateService;
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.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigInteger;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

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

    @Autowired
    GoblinMongoUtils goblinMongoUtils;

    @Autowired
    GoblinRedisUtils goblinRedisUtils;

    @Autowired
    QueueUtils queueUtils;

    @Override
    public ResponseDto<Object> add(GoblinGoodsAnticipateAddParam goodsAnticipateAddParam) {
        if (StringUtils.isNotBlank(goodsAnticipateAddParam.getRule())&&goodsAnticipateAddParam.getList()!=null&&goodsAnticipateAddParam.getList().size()>0) {
            for (GoblinGoodsAnticipateValueAddParam vo : goodsAnticipateAddParam.getList()) {
                if (goblinRedisUtils.getSkuId(vo.getSkuId())) {
                    return ResponseDto.failure(vo.getSkuName().concat("该sku已存在预约"));
                }
            }
            //生成的antId
            String antId = IDGenerator.nextTimeId2();
            GoblinGoodsAnticipateVo goodsAnticipateVo = new GoblinGoodsAnticipateVo();
            BeanUtils.copyProperties(goodsAnticipateAddParam, goodsAnticipateVo);
            goodsAnticipateVo.setAntId(antId);
            goodsAnticipateVo.setCreatedDate(LocalDateTime.now());
            goodsAnticipateVo.setDelTag(0);

            //redis消息预约消息表
            LinkedList<Object[]> sqlAnt = CollectionUtil.linkedListObjectArr();
            sqlAnt.add(new Object[]{
                    antId,
                    goodsAnticipateVo.getRule(),
                    goodsAnticipateVo.getCreatedDate(),
                    goodsAnticipateVo.getDelTag()
            });
            sendRedis("goblin_goods_anticipate", sqlAnt);

            //mongodb新增
            goblinMongoUtils.setGoblinGoodsAnticipateVo(goodsAnticipateVo);

            addAnticipateValues(antId,goodsAnticipateAddParam.getRule(),goodsAnticipateAddParam.getList());

            //返回预约id
            return ResponseDto.success(antId);
        }
        return ResponseDto.failure("参数有误");
    }

    public void addAnticipateValues(String antId,String rule,List<GoblinGoodsAnticipateValueAddParam> list) {
        if (list != null && list.size() > 0) {
            list.forEach(item -> {
                GoblinGoodsAnticipateValueVo goodsAnticipateValueVo = new GoblinGoodsAnticipateValueVo();
                BeanUtils.copyProperties(item, goodsAnticipateValueVo);
                goodsAnticipateValueVo.setAntId(antId);
                goodsAnticipateValueVo.setRule(rule);
                goodsAnticipateValueVo.setCreatedDate(LocalDateTime.now());
                goodsAnticipateValueVo.setDelTag(0);
                goodsAnticipateValueVo.setAboutPeople(BigInteger.valueOf(0));
                goodsAnticipateValueVo.setActualPeople(BigInteger.valueOf(0));
                //redis消息
                //redis标识存入该sku处于预约列表
                goblinRedisUtils.setSkuId(goodsAnticipateValueVo.getSkuId());

                //保存mysql中间表
                LinkedList<Object[]> sqlValue = CollectionUtil.linkedListObjectArr();
                sqlValue.add(new Object[]{
                        goodsAnticipateValueVo.getAntId(),
                        goodsAnticipateValueVo.getSkuName(),
                        goodsAnticipateValueVo.getSkuId(),
                        goodsAnticipateValueVo.getSpuId(),
                        goodsAnticipateValueVo.getAboutPeople(),
                        goodsAnticipateValueVo.getActualPeople(),
                        goodsAnticipateValueVo.getRule(),
                        goodsAnticipateValueVo.getAboutStartDate(),
                        goodsAnticipateValueVo.getAboutEndDate(),
                        goodsAnticipateValueVo.getCreatedDate(),
                        goodsAnticipateValueVo.getDelTag()
                });
                sendRedis("goblin_goods_anticipate_value", sqlValue);

                //存入mongodb中
                goblinMongoUtils.addAnticipateValues(goodsAnticipateValueVo);
            });
        }
    }

    @Override
    public ResponseDto<PageInfo<GoblinGoodsAnticipateValueVo>> list(GoblinGoodsAnticipateValueParam goodsAnticipateValueParam) {
        PageInfo<GoblinGoodsAnticipateValueVo> pageInfo = new PageInfo<>();

        HashMap<String, Object> map = goblinMongoUtils.getGoblinGoodsAnticipateValueVos(goodsAnticipateValueParam);
        List<GoblinGoodsAnticipateValueVo> data = (List<GoblinGoodsAnticipateValueVo>) map.get("data");
        for (GoblinGoodsAnticipateValueVo anticipateValueVo : data) {
            //查询真实预约人数
            BigInteger autIdPeople = goblinRedisUtils.getSkuIdPeople(anticipateValueVo.getSkuId());
            //预约人数   设置预约数+实际预约数
            anticipateValueVo.setAboutPeople(anticipateValueVo.getAboutPeople().add(autIdPeople));
            //实际预约人数
            anticipateValueVo.setActualPeople(autIdPeople);
            //设置预约状态
            //预约开始时间
            LocalDateTime aboutStartDate = anticipateValueVo.getAboutStartDate();
            //预约结束时间
            LocalDateTime aboutEndDate = anticipateValueVo.getAboutEndDate();

            LocalDateTime now = LocalDateTime.now();
            if (aboutStartDate.isBefore(now)) {
                //未开始  0
                anticipateValueVo.setState(0);
            }
            if (!aboutStartDate.isBefore(now) && aboutEndDate.isAfter(now)) {
                //预约中
                anticipateValueVo.setState(1);
            }
            if (aboutEndDate.isBefore(now)) {
                //已结束
                anticipateValueVo.setState(2);
            }
        }
        pageInfo.setList(data);
        pageInfo.setTotal((Long) map.get("total"));
        return ResponseDto.success(pageInfo);
    }

    @Override
    public ResponseDto<Object> updatePeople(String skuId, BigInteger people) {
        //修改Mongodb
        goblinMongoUtils.updateGoblinGoodsAnticipateValueVoPeople(skuId, people);
        //修改mysql
        LinkedList<Object[]> sqlValue = CollectionUtil.linkedListObjectArr();
        sqlValue.add(new Object[]{
                people,
                skuId
        });
        sendRedis("goblin_goods_anticipate_value_update_proper", sqlValue);
        return ResponseDto.success();
    }

    @Override
    public ResponseDto<Object> delete(String skuId) {
        //mysql删除
        LinkedList<Object[]> sqlValue = CollectionUtil.linkedListObjectArr();
        sqlValue.add(new Object[]{
                skuId
        });
        //预约库删除
        sendRedis("goblin_goods_anticipate_value_delete", sqlValue);
        //删除mongodb
        goblinMongoUtils.delGoodsAnticipateValueVo(skuId);
        return ResponseDto.success();
    }

    @Override
    public ResponseDto<Object> userAbout(String skuId, String uid, String phone, Integer state) {
        //查询该用户是否预
        GoblinGoodAnticipateUserVo userVo = goblinRedisUtils.getUserAboutAut(skuId, uid);
        LinkedList<Object[]> sqlValue = CollectionUtil.linkedListObjectArr();
        if (state.equals(GoblinGoodAnticipateUserVo.STATE_VALID) && userVo == null) {
            GoblinGoodAnticipateUserVo user = new GoblinGoodAnticipateUserVo(uid, skuId, phone, state);
            //mongodb记录
            goblinRedisUtils.setUserAboutSku(user);
            //用户没有预约过
            //发送redis消息修改mysql记录用户预约
            sqlValue.add(new Object[]{
                    uid,
                    skuId,
                    phone,
                    state
            });
            sendRedis("goblin_goods_anticipate_user", sqlValue);
        } else {
            //mysql删除用户记录
            sqlValue.add(new Object[]{
                    uid,
                    skuId
            });
            sendRedis("goblin_goods_anticipate_user_update", sqlValue);
            //删除缓存  redis和mongodb
            goblinRedisUtils.delUserAboutSku(skuId, uid);
        }
        goblinRedisUtils.setSkuIdPeople(skuId, state);

        return ResponseDto.success();
    }


/*    @Override
    public ResponseDto<Object> update(GoblinGoodsAnticipateUpdateParam goodsAnticipateUpdateParam) {
        //跟新mongodb
        goblinMongoUtils.updateGoblinGoodsAnticipateVo(goodsAnticipateUpdateParam);
        //修改mysql
        LinkedList<Object[]> sqlValue = CollectionUtil.linkedListObjectArr();
        sqlValue.add(new Object[]{
                goodsAnticipateUpdateParam.getName(),
                goodsAnticipateUpdateParam.getRule(),
                goodsAnticipateUpdateParam.getAntId()
        });
        sendRedis("goblin_goods_anticipate_update", sqlValue);
        return ResponseDto.success();
    }

    @Override
    public ResponseDto<Object> updateAnticipateValues(List<GoblinGoodsAnticipateValueParam> list) {
        if (list != null && list.size() > 0) {
            list.forEach(item -> {
                GoblinGoodsAnticipateValueVo goodsAnticipateValueVo = new GoblinGoodsAnticipateValueVo();
                BeanUtils.copyProperties(item, goodsAnticipateValueVo);

                LinkedList<Object[]> sqlValue = CollectionUtil.linkedListObjectArr();
                if (goodsAnticipateValueVo.getDelTag() == 1) {
                    //删除该sku关联
                    goblinMongoUtils.delAnticipateValueVo(goodsAnticipateValueVo);
                    //删除redis
                    goblinRedisUtils.delAnticipateValue(goodsAnticipateValueVo.getSkuId());
                    //删除mysql中的关联数据
                    sqlValue.add(new Object[]{
                            goodsAnticipateValueVo.getAntId(),
                            goodsAnticipateValueVo.getSkuId()
                    });
                    sendRedis("goblin_goods_anticipate_value_delete_by_antId_and_skuId", sqlValue);
                } else {
                    //保存mysql中间表
                    sqlValue.add(new Object[]{
                            goodsAnticipateValueVo.getAboutStartDate(),
                            goodsAnticipateValueVo.getAboutEndDate(),
                            goodsAnticipateValueVo.getAntId(),
                            goodsAnticipateValueVo.getSkuId(),
                            goodsAnticipateValueVo.getSpuId(),
                    });
                    sendRedis("goblin_goods_anticipate_value_update", sqlValue);

                    //修改mongodb
                    goblinMongoUtils.updateAnticipateValueVo(goodsAnticipateValueVo);
                }
            });
        }
        return ResponseDto.success();
    }

    @Override
    public ResponseDto<Object> getAnticipateValues(String antId) {
        return ResponseDto.success(goblinMongoUtils.getGoodsAnticipateValues(antId));
    }*/


    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);
    }

}
