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.GoblinGoodsAnticipateParam;
import com.liquidnet.service.goblin.dto.manage.GoblinGoodsAnticipateUpdateParam;
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.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<PageInfo<GoblinGoodsAnticipateVo>> list(GoblinGoodsAnticipateParam goodsAnticipateParam) {
        PageInfo<GoblinGoodsAnticipateVo> pageInfo = new PageInfo<>();
        HashMap<String, Object> map = goblinMongoUtils.getGoblinGoodsAnticipateVos(goodsAnticipateParam);
        List<GoblinGoodsAnticipateVo> data = (List<GoblinGoodsAnticipateVo>) map.get("data");
        for (GoblinGoodsAnticipateVo goblinGoodsAnticipateVo : data) {
            //预约开始时间
            LocalDateTime aboutStartDate = goblinGoodsAnticipateVo.getAboutStartDate();
            LocalDateTime aboutEndDate = goblinGoodsAnticipateVo.getAboutEndDate();
            LocalDateTime now = LocalDateTime.now();
            if (aboutStartDate.isBefore(now)) {
                //未开始  0
                goblinGoodsAnticipateVo.setState(0);
            }
            if (!aboutStartDate.isBefore(now) && aboutEndDate.isAfter(now)) {
                //预约中
                goblinGoodsAnticipateVo.setState(1);
            }
            if (aboutEndDate.isBefore(now)) {
                //已结束
                goblinGoodsAnticipateVo.setState(2);
            }
            Integer autIdPeople = goblinRedisUtils.getAutIdPeople(goblinGoodsAnticipateVo.getAntId());
            //预约人数
            goblinGoodsAnticipateVo.setAboutPeople(goblinGoodsAnticipateVo.getAboutPeople() + (autIdPeople != null ? autIdPeople : 0));
            //获取真实预约人数
            goblinGoodsAnticipateVo.setActualPeople(autIdPeople);
        }
        pageInfo.setList(data);
        pageInfo.setTotal((Long) map.get("total"));
        return ResponseDto.success(pageInfo);
    }

    @Override
    public ResponseDto<Object> add(GoblinGoodsAnticipateAddParam goodsAnticipateAddParam) {
        if (StringUtils.isNotBlank(goodsAnticipateAddParam.getName())
                && StringUtils.isNotBlank(goodsAnticipateAddParam.getRule())
                && StringUtils.isNotBlank(goodsAnticipateAddParam.getAboutStartDate().toString())
                && StringUtils.isNotBlank(goodsAnticipateAddParam.getAboutEndDate().toString())) {
            //生成的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.getName(),
                    goodsAnticipateVo.getRule(),
                    goodsAnticipateVo.getAboutPeople(),
                    goodsAnticipateVo.getAboutStartDate(),
                    goodsAnticipateVo.getAboutEndDate(),
                    goodsAnticipateVo.getCreatedDate(),
                    goodsAnticipateVo.getDelTag()
            });
            sendRedis("goblin_goods_anticipate", sqlAnt);

            //mongodb新增
            goblinMongoUtils.setGoblinGoodsAnticipateVo(goodsAnticipateVo);
            return ResponseDto.success();
        }
        return ResponseDto.failure("参数有误");
    }

    @Override
    public ResponseDto<Object> updatePeople(String antId, Long people) {
        //修改Mongodb
        goblinMongoUtils.updateGoblinGoodsAnticipateVoPeople(antId, people);
        //修改mysql
        LinkedList<Object[]> sqlValue = CollectionUtil.linkedListObjectArr();
        sqlValue.add(new Object[]{
                people,
                antId
        });
        sendRedis("goblin_goods_anticipate_update_proper", sqlValue);

        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> delete(String antId) {
        //mysql删除
        LinkedList<Object[]> sqlValue = CollectionUtil.linkedListObjectArr();
        sqlValue.add(new Object[]{
                antId
        });
        //预约库删除
        sendRedis("goblin_goods_anticipate_delete", sqlValue);
        //预约关联库删除
        sendRedis("goblin_goods_anticipate_value_delete_by_antId", sqlValue);
        //删除mongodb
        if (goblinMongoUtils.delGoodsAnticipateVo(antId)) {
            return ResponseDto.success();
        }
        return ResponseDto.success();
    }

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

        return ResponseDto.success();
    }

    @Override
    public ResponseDto<Object> addAnticipateValues(List<GoblinGoodsAnticipateValueParam> list) {
        if (list != null && list.size() > 0) {
            for (GoblinGoodsAnticipateValueParam vo : list) {
                if (goblinRedisUtils.getAnticipate(vo.getAntId(), vo.getSkuId()))
                    return ResponseDto.failure("该预约已选择该sku");
            }
            list.forEach(item -> {
                GoblinGoodsAnticipateValueVo goodsAnticipateValueVo = new GoblinGoodsAnticipateValueVo();
                BeanUtils.copyProperties(item, goodsAnticipateValueVo);
                goodsAnticipateValueVo.setCreatedDate(LocalDateTime.now());
                goodsAnticipateValueVo.setCreatedDate(LocalDateTime.now());
                goodsAnticipateValueVo.setDelTag(0);
                //redis消息
                //redis标识存入该sku处于预约列表
                goblinRedisUtils.setAnticipateValue(goodsAnticipateValueVo.getAntId(), goodsAnticipateValueVo.getSkuId());

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

                });
                sendRedis("goblin_goods_anticipate_value", sqlValue);

                //存入mongodb中
                goblinMongoUtils.addAnticipateValues(goodsAnticipateValueVo);
            });
        }
        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.getAntId(), 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);
    }

}
