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

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.GoblinGoodsAnticipateValueAddParam;
import com.liquidnet.service.goblin.dto.manage.GoblinGoodsAnticipateValueParam;
import com.liquidnet.service.goblin.dto.manage.vo.AnticipateValueVo;
import com.liquidnet.service.goblin.dto.manage.vo.GoblinGoodsAnticipateValueVo;
import com.liquidnet.service.goblin.dto.vo.GoblinGoodsAnticipateVo;
import com.liquidnet.service.goblin.service.manage.IGoblinGoodsAnticipateMgService;
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 GoblinGoodsAnticipateMgServiceImpl implements IGoblinGoodsAnticipateMgService {

    @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("该商品已创建预约！"));
                }
               if (vo.getAboutStartDate().isAfter(vo.getAboutEndDate())){
                   return ResponseDto.failure(vo.getSkuName().concat("该商品预约时间在结束时间之后，不可创建！"));
               }
            }
            //生成的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.setValue(goodsAnticipateValueVo);

                //保存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());
            autIdPeople = autIdPeople != null ? autIdPeople : BigInteger.valueOf(0);
            //预约人数   设置预约数+实际预约数
            anticipateValueVo.setAboutPeople(anticipateValueVo.getAboutPeople().add(autIdPeople));
            //实际预约人数
            anticipateValueVo.setActualPeople(autIdPeople);
            //设置预约状态
            anticipateValueVo.setState(setState(anticipateValueVo.getAboutStartDate(), anticipateValueVo.getAboutEndDate()));

        }
        pageInfo.setPageNum(goodsAnticipateValueParam.getPageNum());
        pageInfo.setPageSize(20);
        pageInfo.setList(data);
        pageInfo.setTotal((Long) map.get("total"));
        return ResponseDto.success(pageInfo);
    }

    private Integer setState(LocalDateTime startDate, LocalDateTime endDate) {

        LocalDateTime now = LocalDateTime.now();
        if (startDate.isAfter(now)) {
            //未开始  0
            return 0;
        }
        if (startDate.isBefore(now) && endDate.isAfter(now)) {
            //预约中 1
            return 1;
        }
        if (endDate.isBefore(now)) {
            //已结束 2
            return 2;
        }
        //其他
        return null;
    }

    @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) {
        //更具skuId查询
        GoblinGoodsAnticipateValueVo goodsAnticipateValueVo = goblinRedisUtils.getValueBySkuId(skuId);

        if (goodsAnticipateValueVo != null) {
            goodsAnticipateValueVo.setState(setState(goodsAnticipateValueVo.getAboutStartDate(), goodsAnticipateValueVo.getAboutEndDate()));
            //没有开启则可以删除预约
            if (!goodsAnticipateValueVo.getState().equals(0)) {
                return ResponseDto.failure("预约状态为已开启或已结束，不可删除！");
            }
            //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();
        }
        return ResponseDto.failure("该预约不存在");
    }

    private void delUserBySkuId(String skuId) {
        //删除redis 和mongodb
        goblinMongoUtils.delUserBySkuId(skuId);
        //数据库修改  用户预约过该skuId的表字段全部修改未 1
        LinkedList<Object[]> sqlValue = CollectionUtil.linkedListObjectArr();
        sqlValue.add(new Object[]{
                skuId
        });
        sendRedis("goblin_goods_anticipate_user_update_sku", sqlValue);
    }

    @Override
    public AnticipateValueVo getAnticipateValueBySkuId(String skuId, int hasHead) {
        GoblinGoodsAnticipateValueVo anticipateValueVo = goblinRedisUtils.getValueBySkuId(skuId);
        AnticipateValueVo valueVo = AnticipateValueVo.getNew();
        if (anticipateValueVo != null) {
            valueVo = valueVo.copy(anticipateValueVo);
            valueVo.setState(setState(valueVo.getAboutStartDate(), valueVo.getAboutEndDate()));
        } else {
            valueVo.setState(null);
            valueVo.setAboutEndDate(null);
            valueVo.setAboutStartDate(null);
            valueVo.setAboutPeople(BigInteger.ZERO);
            valueVo.setRule("");
        }
        if(hasHead==1){
            valueVo.setAboutAvatarList(goblinRedisUtils.getUserAvatar(skuId));
        }else{
            valueVo.setAboutAvatarList(CollectionUtil.linkedListString());
        }
        return valueVo;
    }

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

}
