package com.freemud.sdk.api.assortment.shoppingcart.service.impl;

import cn.freemud.base.entity.BaseResponse;
import com.freemud.application.sdk.api.log.ErrorLog;
import com.freemud.sdk.api.assortment.shoppingcart.adapter.CollageOrderSdkAdapter;
import com.freemud.sdk.api.assortment.shoppingcart.constant.*;
import com.freemud.sdk.api.assortment.shoppingcart.domain.CollageMemberState;
import com.freemud.sdk.api.assortment.shoppingcart.domain.CollageOrder;
import com.freemud.sdk.api.assortment.shoppingcart.domain.CollageOrderDto;
import com.freemud.sdk.api.assortment.shoppingcart.domain.CollagePartnerMember;
import com.freemud.sdk.api.assortment.shoppingcart.service.CollageOrderBaseService;
import com.freemud.sdk.api.assortment.shoppingcart.util.CartResponseUtil;
import com.freemud.sdk.api.assortment.shoppingcart.util.DateTimeUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.text.MessageFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * All rights Reserved, Designed By www.freemud.com
 *
 * @version V1.0
 * @Title:
 * @Package: com.freemud.sdk.api.assortment.shoppingcart.service.impl
 * @Descripttion:
 * @author: pengfei.liu
 * @date: 2020/9/24
 * @Copyright: 2020 www.freemud.cn Inc. All rights reserved.
 * 注意：本内容仅限于上海非码科技内部传阅，禁止外泄以及用于其他的商业目.
 */
@Service("collageOrderBaseService")
public class CollageOrderBaseServiceImpl implements CollageOrderBaseService {
    @Autowired
    private CollageCartBaseServiceImpl collageCartBaseService;

    @Autowired
    private CollageOrderSdkAdapter collageOrderSdkAdapter;

    @Autowired
    private RedisTemplate redisTemplate;

    @Value("${collage.complete.delay.minute}")
    private int completeDelayMinute = 1;

    @Value("${collage.cancel.delay.minute}")
    private int cancelDelayMinute = 1;

    /**
     * 查询拼单订单
     * 根据createCollageUserId查询，先根据key查询，若不存在去商户旗下拼单列表查询，若存在则返回
     * @param collageOrderDto
     * @return
     */
    @Override
    public BaseResponse<CollageOrder> queryCollageOrder(CollageOrderDto collageOrderDto) {
        CollageOrder collageOrder = null;
        try {
            // 仅支持两种查询场景
            // 1、createCollageUserId存在，则只根据当前三要素查询，若无直接返回不存在
            if (StringUtils.isNotBlank(collageOrderDto.getCreateCollageUserId())) {
                // 通过商户ID、门店ID、用户ID组装拼单订单Redis缓存基本信息Key
                String collageBaseHashKey = this.genCollageBaseHashKey(collageOrderDto.getPartnerId(), collageOrderDto.getStoreId(), collageOrderDto.getCreateCollageUserId());
                // 查询Redis缓存中拼单订单基础信息
                collageOrder = this.getCollageBaseHash(collageBaseHashKey);
            }
            // 2、createCollageUserId不存在，则只从当前商户拼单参与人信息列表中查询并返回，若商户级别拼单不存在，则提示拼单不存在
            else {
                String collagePartnerMemberHashKey = this.genCollagePartnerMemberHashKey(collageOrderDto.getPartnerId());
                CollagePartnerMember collagePartnerMember = null;
                if(StringUtils.isNotEmpty(collageOrderDto.getCurrentUserId())){
                    //java.lang.IllegalArgumentException: non null hash key required
                    collagePartnerMember = this.getCollagePartnerMember(collagePartnerMemberHashKey, collageOrderDto.getCurrentUserId());
                }
                // 若商户拼单参与人列表信息不存在或已过期
                if (null == collagePartnerMember || collagePartnerMember.getExpire() < System.currentTimeMillis()) {
                    if (null != collagePartnerMember) {
                        // 门店下拼单参与人列表数据过期清理
                        this.deleteCollagePartnerMember(collagePartnerMemberHashKey, new String[]{collageOrderDto.getCurrentUserId()});
                    }
                    return CartResponseUtil.error(CollageOrderConstant.COLLAGE_ORDER_NOT_EXIST);
                } else {
                    // 从商户拼单参与人列表中获取信息再次查询拼单信息
                    String collageBaseHashKey = this.genCollageBaseHashKey(collagePartnerMember.getPartnerId(), collagePartnerMember.getStoreId(), collagePartnerMember.getCreateCollageUserId());
                    collageOrder = this.getCollageBaseHash(collageBaseHashKey);
                }
            }
            if (ObjectUtils.isEmpty(collageOrder)) {
                return CartResponseUtil.error(CollageOrderConstant.COLLAGE_ORDER_NOT_EXIST);
            }
            // 若拼单订单信息存在，则构造订单拼单对象并返回成功提示
            return CartResponseUtil.success(collageOrder);
        } catch (Exception e) {
            ErrorLog.printErrorLog("获取拼单订单基础信息异常", "CollageOrderBaseServiceImpl/queryCollageOrder", this.collageOrderRequest(collageOrderDto),  e);
            return CartResponseUtil.error(CollageOrderConstant.COLLAGE_ORDER_NOT_EXIST);
        }
    }

    /**
     * 仅查询CreateCollageUserId创建的拼单
     * @param collageOrderDto
     * @return
     */
    @Override
    public BaseResponse<CollageOrder> queryCollageOrderByCreateCollageUserId(CollageOrderDto collageOrderDto) {
        try {
            // 通过商户ID、门店ID、用户ID组装拼单订单Redis缓存基本信息Key
            String collageBaseHashKey = this.genCollageBaseHashKey(collageOrderDto.getPartnerId(), collageOrderDto.getStoreId(), collageOrderDto.getCreateCollageUserId());

            // 查询Redis缓存中拼单订单基础信息
            CollageOrder collageOrder = this.getCollageBaseHash(collageBaseHashKey);

            if (ObjectUtils.isEmpty(collageOrder)) {
                return CartResponseUtil.error(CollageOrderConstant.COLLAGE_ORDER_NOT_EXIST);
            }

            // 若拼单订单信息存在，则构造订单拼单对象并返回成功提示
            return CartResponseUtil.success(collageOrder);
        } catch (Exception e) {
            ErrorLog.printErrorLog("获取拼单订单基础信息异常", "CollageOrderBaseServiceImpl/queryCollageOrderByCreateCollageUserId", this.collageOrderRequest(collageOrderDto),  e);
            return CartResponseUtil.error(CollageOrderConstant.COLLAGE_ORDER_NOT_EXIST);
        }
    }

    /**
     * 创建拼单订单
     * @param collageOrderDto
     * @return
     */
    @Override
    public BaseResponse<CollageOrder> createCollageOrder(CollageOrderDto collageOrderDto) {
        try {
            if (!this.isInCollagePartnerMemberList(collageOrderDto)) {
                // 通过商户ID、门店ID、用户ID组装拼单订单Redis缓存基本信息Key
                String collageBaseHashKey = this.genCollageBaseHashKey(collageOrderDto.getPartnerId(), collageOrderDto.getStoreId(), collageOrderDto.getCreateCollageUserId());

                // 根据key查询Redis中拼单订单的基本信息
                CollageOrder collageOrder = this.getCollageBaseHash(collageBaseHashKey);

                if (ObjectUtils.isEmpty(collageOrder)) {
                    // 若拼单信息不存在，则初始化拼单订单对象，放入Redis缓存并设置1小时失效时间，返回拼单订单对象并给出成功提示
                    collageOrder = collageOrderSdkAdapter.toCollageOrder(collageOrderDto);
                    collageOrder.setCollageId(UUID.randomUUID().toString());
                    collageOrder.setCreateTime(DateTimeUtils.currentTimeMillis());
                    collageOrder.setExpireTime(DateTimeUtils.currentTimeMillis(60 * 60L));
                    collageOrder.setStatus(CollageOrderStatus.SHOPPING.getValue());

                    // 创建缓存数据
                    this.putCollageBaseHash(collageBaseHashKey, collageOrder);
                    // 将拼单发起人加入拼单餐位
                    String collageMemberHashKey = this.genCollageMemberHashKey(collageOrderDto.getPartnerId(), collageOrderDto.getStoreId(), collageOrderDto.getCreateCollageUserId());
                    this.initCollageMember(collageMemberHashKey, collageOrderDto.getCurrentUserId());
                    // 设置拼单发起人加购状态
                    String collageMemberStateHashKey = this.genCollageMemberStateHashKey(collageOrderDto.getPartnerId(), collageOrderDto.getStoreId(), collageOrderDto.getCreateCollageUserId());
                    this.initCollageMemberState(collageMemberStateHashKey, collageOrderDto);
                    // 将拼单发起人加入门店拼单客户列表
                    String collagePartnerMemberKey = this.genCollagePartnerMemberHashKey(collageOrderDto.getPartnerId());
                    CollagePartnerMember collagePartnerMember = new CollagePartnerMember(collageOrderDto.getPartnerId(), collageOrderDto.getStoreId(), collageOrderDto.getCreateCollageUserId(), collageOrder.getExpireTime());
                    this.putCollagePartnerMember(collagePartnerMemberKey, collageOrderDto.getCurrentUserId(), collagePartnerMember);
                    return CartResponseUtil.success(collageOrder);
                }
            }
        } catch (Exception e) {
            ErrorLog.printErrorLog("创建拼单订单异常", "CollageOrderBaseServiceImpl/createCollageOrder", this.collageOrderRequest(collageOrderDto),  e);
        }

        // 若拼单发起人正在参与其他拼单 或者 拼单订单信息已存在，则返回错误提示【当前用户存在进行中的拼单订单】
        return CartResponseUtil.error(CollageOrderConstant.COLLAGE_ORDER_ALREADY_EXIST);
    }

    /**
     * 更新拼单状态
     * @param collageOrderDto
     * @return
     */
    @Override
    public BaseResponse<CollageOrder> updateCollageOrder(CollageOrderDto collageOrderDto) {
        try {
            // 通过商户ID、门店ID、用户ID组装拼单订单Redis缓存基本信息Key
            String collageBaseHashKey = this.genCollageBaseHashKey(collageOrderDto.getPartnerId(), collageOrderDto.getStoreId(), collageOrderDto.getCreateCollageUserId());

            // 查询Redis缓存中拼单订单基础信息
            CollageOrder collageOrder = this.getCollageBaseHash(collageBaseHashKey);

            if (ObjectUtils.isEmpty(collageOrder)) {
                return CartResponseUtil.error(CollageOrderConstant.COLLAGE_ORDER_NOT_EXIST);
            }

            // 拼单状态
            if (null != collageOrderDto.getStatus()) {
                collageOrder.setStatus(collageOrderDto.getStatus());
            }
            // 拼单生产的订单编号
            if (null != collageOrderDto.getOrderCode()) {
                collageOrder.setOrderCode(collageOrderDto.getOrderCode());
            }

            // 获取当前拼单剩余缓存时间
            long expireSeconds = this.getCollageBashHashExpireSeconds(collageBaseHashKey);

            // 若状态更新为已完成 则将失效时间改为N分钟
            if (CollageOrderStatus.COMPLETE.getValue().equals(collageOrderDto.getStatus())) {
                expireSeconds = completeDelayMinute * 60L;
            } else if (CollageOrderStatus.CANCEL.getValue().equals(collageOrderDto.getStatus())) {
                expireSeconds = cancelDelayMinute * 60L;
            } else if (CollageOrderStatus.PAYING.getValue().equals(collageOrderDto.getStatus())) {
                expireSeconds = 5 * 60L;
            }

            // 修改拼单主信息失效时间
            collageOrder.setExpireTime(System.currentTimeMillis() + expireSeconds * 1000);

            // 更新拼单基础信息
            this.putCollageBaseHash(collageBaseHashKey, collageOrder, expireSeconds);

            // 更新其他缓存失效时间
            this.updateCollageOrderExpire(collageOrderDto.getPartnerId(), collageOrderDto.getStoreId(), collageOrderDto.getCreateCollageUserId(), expireSeconds);

            return CartResponseUtil.success();
        } catch (Exception e) {
            ErrorLog.printErrorLog("更新拼单状态异常", "CollageOrderBaseServiceImpl/updateCollageOrderStatus", this.collageOrderRequest(collageOrderDto),  e);
        }

        return CartResponseUtil.error(CollageOrderConstant.COLLAGE_ORDER_FAILED);
    }

    /**
     * 清除拼单缓存
     * @param collageOrderDto
     * @return
     */
    @Override
    public BaseResponse clearCollageOrder(CollageOrderDto collageOrderDto) {
        try {
            // 批量删除上述Key对应的Redis缓存
            this.deleteCollageBaseHash(this.collageOrderSdkAdapter.toCollageOrder(collageOrderDto));
            return CartResponseUtil.success();
        } catch (Exception e) {
            ErrorLog.printErrorLog("清除拼单订单异常", "CollageOrderBaseServiceImpl/clearCollageOrder", this.collageOrderRequest(collageOrderDto),  e);
            return CartResponseUtil.error(CollageOrderConstant.COLLAGE_ORDER_FAILED);
        }
    }

    /**
     * 锁定拼单订单
     * @param collageOrderDto
     * @return
     */
    @Override
    public BaseResponse lockCollageOrder(CollageOrderDto collageOrderDto) {
        try {
            String collageBashHashKey = this.genCollageBaseHashKey(collageOrderDto.getPartnerId(), collageOrderDto.getStoreId(), collageOrderDto.getCreateCollageUserId());
            String collageLockKey = this.genCollageLockKey(collageOrderDto.getPartnerId(), collageOrderDto.getStoreId(), collageOrderDto.getCreateCollageUserId());
            this.setCollageLock(collageLockKey, CollageLockStatus.LOCKED, this.getCollageBashHashExpireSeconds(collageBashHashKey));
            return this.getCollageLock(collageLockKey).getValue() ? CartResponseUtil.success() : CartResponseUtil.error(CollageOrderConstant.COLLAGE_ORDER_FAILED);
        } catch (Exception e) {
            ErrorLog.printErrorLog("锁定拼单订单异常", "CollageOrderBaseServiceImpl/lockCollageOrder", this.collageOrderRequest(collageOrderDto),  e);
            return CartResponseUtil.error(CollageOrderConstant.COLLAGE_ORDER_FAILED);
        }
    }

    /**
     * 解锁拼单订单
     * @param collageOrderDto
     * @return
     */
    @Override
    public BaseResponse unlockCollageOrder(CollageOrderDto collageOrderDto) {
        try {
            String collageBashHashKey = this.genCollageBaseHashKey(collageOrderDto.getPartnerId(), collageOrderDto.getStoreId(), collageOrderDto.getCreateCollageUserId());
            String collageLockKey = this.genCollageLockKey(collageOrderDto.getPartnerId(), collageOrderDto.getStoreId(), collageOrderDto.getCreateCollageUserId());
            this.setCollageLock(collageLockKey, CollageLockStatus.RELEASE, this.getCollageBashHashExpireSeconds(collageBashHashKey));
            return !this.getCollageLock(collageLockKey).getValue() ? CartResponseUtil.success() : CartResponseUtil.error(CollageOrderConstant.COLLAGE_ORDER_FAILED);
        } catch (Exception e) {
            ErrorLog.printErrorLog("解锁拼单订单异常", "CollageOrderBaseServiceImpl/unlockCollageOrder", this.collageOrderRequest(collageOrderDto),  e);
            return CartResponseUtil.error(CollageOrderConstant.COLLAGE_ORDER_FAILED);
        }
    }

    /**
     * 获取拼单订单锁状态
     * @param collageOrderDto
     * @return
     */
    @Override
    public BaseResponse<Boolean> isLockedCollageOrder(CollageOrderDto collageOrderDto) {
        try {
            String collageLockKey = this.genCollageLockKey(collageOrderDto.getPartnerId(), collageOrderDto.getStoreId(), collageOrderDto.getCreateCollageUserId());
            return CartResponseUtil.success(this.getCollageLock(collageLockKey).getValue());
        } catch (Exception e) {
            ErrorLog.printErrorLog("获取拼单订单锁状态异常", "CollageOrderBaseServiceImpl/isLockedCollageOrder", this.collageOrderRequest(collageOrderDto),  e);
            return CartResponseUtil.success(false);
        }
    }

    @Override
    public BaseResponse<List<CollageMemberState>> getCollageMemberState(CollageOrderDto collageOrderDto) {
        try {
            String collageMemberStateKey = this.genCollageMemberStateHashKey(collageOrderDto.getPartnerId(), collageOrderDto.getStoreId(), collageOrderDto.getCreateCollageUserId());
            return CartResponseUtil.success(this.getCollageMemberStateHash(collageMemberStateKey));
        } catch (Exception e) {
            ErrorLog.printErrorLog("获取拼单用户状态异常", "CollageOrderBaseServiceImpl/getCollageMemberState", this.collageOrderRequest(collageOrderDto),  e);
            return CartResponseUtil.success(Collections.EMPTY_LIST);
        }
    }

    @Override
    public BaseResponse readyCollageMemberState(CollageOrderDto collageOrderDto) {
        try {
            String collageMemberStateKey = this.genCollageMemberStateHashKey(collageOrderDto.getPartnerId(), collageOrderDto.getStoreId(), collageOrderDto.getCreateCollageUserId());
            CollageMemberState collageMemberState = this.getCollageMemberState(collageMemberStateKey, collageOrderDto.getCurrentUserId());
            if (null == collageMemberState) return CartResponseUtil.error("当前用户未参与此拼单");
            collageMemberState.setState(CollageMemberStateType.READY.getValue());
            this.setCollageMemberState(collageMemberStateKey, collageMemberState);
            return CartResponseUtil.success();
        } catch (Exception e) {
            ErrorLog.printErrorLog("修改拼单用户加购状态为加购完毕异常", "CollageOrderBaseServiceImpl/readyCollageMemberState", this.collageOrderRequest(collageOrderDto),  e);
            return CartResponseUtil.error("修改拼单用户加购状态为加购完毕异常");
        }
    }

    @Override
    public BaseResponse shoppingCollageMemberState(CollageOrderDto collageOrderDto) {
        try {
            String collageMemberStateKey = this.genCollageMemberStateHashKey(collageOrderDto.getPartnerId(), collageOrderDto.getStoreId(), collageOrderDto.getCreateCollageUserId());
            CollageMemberState collageMemberState = this.getCollageMemberState(collageMemberStateKey, collageOrderDto.getCurrentUserId());
            if (null == collageMemberState) return CartResponseUtil.error("当前用户未参与此拼单");
            collageMemberState.setState(CollageMemberStateType.SHOPPING.getValue());
            this.setCollageMemberState(collageMemberStateKey, collageMemberState);
            return CartResponseUtil.success();
        } catch (Exception e) {
            ErrorLog.printErrorLog("修改拼单用户加购状态为继续选购异常", "CollageOrderBaseServiceImpl/shoppingCollageMemberState", this.collageOrderRequest(collageOrderDto),  e);
            return CartResponseUtil.error("修改拼单用户加购状态为继续选购异常");
        }
    }

    @Override
    public BaseResponse setCollageMember(CollageOrderDto collageOrderDto){
        String key = genCollageMemberHashKey(collageOrderDto.getPartnerId(),collageOrderDto.getStoreId(),collageOrderDto.getCreateCollageUserId());
        // 拼单人数不能超过100，非业务限制
        if (redisTemplate.boundHashOps(key).values() != null && redisTemplate.boundHashOps(key).values().size() > 100) {
            return CartResponseUtil.error("拼单人数超过上限（100），加入失败");
        }
        redisTemplate.boundHashOps(key).put(collageOrderDto.getCurrentUserId(),new ArrayList<>());
        return CartResponseUtil.success();
    }

    @Override
    public BaseResponse setCollagePartnerMember(CollageOrderDto collageOrderDto){
        try {
            String collagePartnerMemberKey = this.genCollagePartnerMemberHashKey(collageOrderDto.getPartnerId());
            String collageBaseHashKey = this.genCollageBaseHashKey(collageOrderDto.getPartnerId(), collageOrderDto.getStoreId(), collageOrderDto.getCreateCollageUserId());
            CollageOrder collageBaseHash = this.getCollageBaseHash(collageBaseHashKey);
            CollagePartnerMember collagePartnerMember = new CollagePartnerMember(collageOrderDto.getPartnerId(), collageOrderDto.getStoreId(), collageOrderDto.getCreateCollageUserId(), collageBaseHash.getExpireTime());
            this.putCollagePartnerMember(collagePartnerMemberKey, collageOrderDto.getCurrentUserId(), collagePartnerMember);
        } catch (Exception e) {
            ErrorLog.printErrorLog("设置用户在该商户下拼单参与列表记录异常", "CollageOrderBaseServiceImpl/setCollagePartnerMember", this.collageOrderRequest(collageOrderDto),  e);
            CartResponseUtil.error("设置用户在该商户下拼单参与列表记录失败");
        }
        return CartResponseUtil.success();
    }

    /**
     * 判断用户是否参加了某一个拼单
     * @param collageOrderDto
     * @return
     */
    @Override
    public BaseResponse judgeMemberAddOneCollage(CollageOrderDto collageOrderDto){
        String key = genCollageMemberHashKey(collageOrderDto.getPartnerId(),collageOrderDto.getStoreId(),collageOrderDto.getCreateCollageUserId());
        Boolean judge = redisTemplate.boundHashOps(key).hasKey(collageOrderDto.getCurrentUserId());
        return judge ? CartResponseUtil.success() : CartResponseUtil.error("当前用户未参与拼单");
    }

    @Override
    public BaseResponse cleanMemberSeat(CollageOrderDto collageOrderDto){
        String key = genCollageMemberHashKey(collageOrderDto.getPartnerId(),collageOrderDto.getStoreId(),collageOrderDto.getCreateCollageUserId());
        redisTemplate.boundHashOps(key).delete(collageOrderDto.getCurrentUserId());
        return CartResponseUtil.success();
    }

    @Override
    public List<String> getMemCarLine(CollageOrderDto collageOrderDto){
        String key = genCollageMemberHashKey(collageOrderDto.getPartnerId(),collageOrderDto.getStoreId(),collageOrderDto.getCreateCollageUserId());
        List<String> cartLineIds = (List<String>)redisTemplate.boundHashOps(key).get(collageOrderDto.getCurrentUserId());
        return cartLineIds;
    }

    @Override
    public BaseResponse cleanMemberCartLine(CollageOrderDto collageOrderDto){
        String key = genCollageCarHashKey(collageOrderDto.getPartnerId(),collageOrderDto.getStoreId(),collageOrderDto.getCreateCollageUserId());
        if (null != collageOrderDto.getCartLines() && collageOrderDto.getCartLines().size() > 0) {
            collageOrderDto.getCartLines().forEach(cartLine -> {
                redisTemplate.boundHashOps(key).delete(String.valueOf(cartLine));
            });
        }

        return CartResponseUtil.success();
    }

    @Override
    public BaseResponse cleanMemberStates(CollageOrderDto collageOrderDto){
        String key = genCollageMemberStateHashKey(collageOrderDto.getPartnerId(),collageOrderDto.getStoreId(),collageOrderDto.getCreateCollageUserId());
        redisTemplate.boundHashOps(key).delete(collageOrderDto.getCurrentUserId());
        return CartResponseUtil.success();
    }

    @Override
    public BaseResponse cleanCollagePartnerMember(CollageOrderDto collageOrderDto){
        String key = genCollagePartnerMemberHashKey(collageOrderDto.getPartnerId());
        redisTemplate.boundHashOps(key).delete(collageOrderDto.getCurrentUserId());
        return CartResponseUtil.success();
    }

    @Override
    public BaseResponse<CollageMemberState> getOneCollageMemberState(CollageOrderDto collageOrderDto) {
        try {
            String collageMemberStateKey = this.genCollageMemberStateHashKey(collageOrderDto.getPartnerId(), collageOrderDto.getStoreId(), collageOrderDto.getCreateCollageUserId());
            return CartResponseUtil.success(this.getCollageMemberState(collageMemberStateKey,collageOrderDto.getCurrentUserId()));
        } catch (Exception e) {
            ErrorLog.printErrorLog("获取拼单用户状态异常", "CollageOrderBaseServiceImpl/getOneCollageMemberState", this.collageOrderRequest(collageOrderDto),  e);
            return CartResponseUtil.error("获取拼单用户状态异常");
        }
    }

    /**
     * 构建门店下拼单人员hashKey
     * 20201127 产品确认同一商户下所有门店只允许同时存在一个拼单
     * Hash<userId, {partnerId, storeId, createCollageUserId, expireTime}>
     * @param partnerId
     */
    private String genCollagePartnerMemberHashKey(String partnerId) {
        return MessageFormat.format(RedisKeyConstant.COLLAGE_PARTNER_MEMBER_KEY, partnerId);
    }

    /**
     * Redis获取拼单订单信息
     * @param collageBaseHashKey
     * @return
     */
    private CollageOrder getCollageBaseHash(String collageBaseHashKey) throws Exception {
        return collageOrderSdkAdapter.toCollageOrder(redisTemplate.boundHashOps(collageBaseHashKey).entries());
    }

    /**
     * 获取拼单订单剩余过期时间（秒）
     * @param collageBaseHashKey
     * @return
     */
    private Long getCollageBashHashExpireSeconds(String collageBaseHashKey) throws Exception {
        return redisTemplate.boundHashOps(collageBaseHashKey).getExpire();
    }

    /**
     * Redis写入拼单订单信息
     * @param collageBaseHashKey
     * @param collageOrder
     */
    private void putCollageBaseHash(String collageBaseHashKey, CollageOrder collageOrder) throws Exception {
        this.putCollageBaseHash(collageBaseHashKey, collageOrder, 60 * 60L);
    }

    private void putCollageBaseHash(String collageBaseHashKey, CollageOrder collageOrder, Long expireSeconds) throws Exception {
        redisTemplate.boundHashOps(collageBaseHashKey).putAll(this.collageOrderSdkAdapter.toRedisMap(collageOrder));
        redisTemplate.boundHashOps(collageBaseHashKey).expire(expireSeconds == null ? 60 * 60L : expireSeconds, TimeUnit.SECONDS);
    }

    /**
     * Redis删除拼单订单信息以及相关购物车信息
     * @param collageOrder
     */
    private void deleteCollageBaseHash(CollageOrder collageOrder) throws Exception {
        // 删除商品门店拼单客户列表中该拼单订单下参与人
        Set<String> collageMember = this.collageCartBaseService.getCollageMember(collageOrder.getPartnerId(), collageOrder.getStoreId(), collageOrder.getCreateCollageUserId());
        String collagePartnerMemberKey = this.genCollagePartnerMemberHashKey(collageOrder.getPartnerId());
        this.deleteCollagePartnerMember(collagePartnerMemberKey, collageMember.toArray());

        // 删除拼单订单相关缓存
        Set<String> redisKeySet = new HashSet<>();
        redisKeySet.add(this.genCollageBaseHashKey(collageOrder.getPartnerId(), collageOrder.getStoreId(), collageOrder.getCreateCollageUserId()));
        redisKeySet.add(this.genCollageMemberHashKey(collageOrder.getPartnerId(), collageOrder.getStoreId(), collageOrder.getCreateCollageUserId()));
        redisKeySet.add(this.genCollageCarHashKey(collageOrder.getPartnerId(), collageOrder.getStoreId(), collageOrder.getCreateCollageUserId()));
        redisKeySet.add(this.genCollageCarVerKey(collageOrder.getPartnerId(), collageOrder.getStoreId(), collageOrder.getCreateCollageUserId()));
        redisKeySet.add(this.genCollageLockKey(collageOrder.getPartnerId(), collageOrder.getStoreId(), collageOrder.getCreateCollageUserId()));
        redisKeySet.add(this.genCollageMemberStateHashKey(collageOrder.getPartnerId(), collageOrder.getStoreId(), collageOrder.getCreateCollageUserId()));
        redisTemplate.delete(redisKeySet);
    }

    /**
     * 更新整个拼单所有key的expire
     * @param partnerId
     * @param storeId
     * @param createCollageUserId
     * @param expireSeconds
     */
    private void updateCollageOrderExpire(String partnerId, String storeId, String createCollageUserId, Long expireSeconds) {
        if (expireSeconds == null) return;
        redisTemplate.expire(this.genCollageBaseHashKey(partnerId, storeId, createCollageUserId), expireSeconds, TimeUnit.SECONDS);
        redisTemplate.expire(this.genCollageMemberHashKey(partnerId, storeId, createCollageUserId), expireSeconds, TimeUnit.SECONDS);
        redisTemplate.expire(this.genCollageCarHashKey(partnerId, storeId, createCollageUserId), expireSeconds, TimeUnit.SECONDS);
        redisTemplate.expire(this.genCollageCarVerKey(partnerId, storeId, createCollageUserId), expireSeconds, TimeUnit.SECONDS);
        redisTemplate.expire(this.genCollageLockKey(partnerId, storeId, createCollageUserId), expireSeconds, TimeUnit.SECONDS);
        redisTemplate.expire(this.genCollageMemberStateHashKey(partnerId, storeId, createCollageUserId), expireSeconds, TimeUnit.SECONDS);

        String collagePartnerMemberKey = this.genCollagePartnerMemberHashKey(partnerId);
        Set<String> collageMember = this.collageCartBaseService.getCollageMember(partnerId, storeId, createCollageUserId);
        if (null != collageMember) {
            for (String userId : collageMember) {
                CollagePartnerMember collagePartnerMember = this.getCollagePartnerMember(collagePartnerMemberKey, userId);
                collagePartnerMember.setExpire(System.currentTimeMillis() + expireSeconds * 1000);
                this.putCollagePartnerMember(collagePartnerMemberKey, userId, collagePartnerMember);
            }
        }
    }

    /**
     * 拼单订单锁设定
     * @param collageLockKey
     * @param status
     * @param expireTime seconds
     */
    private void setCollageLock(String collageLockKey, CollageLockStatus status, Long expireTime) throws Exception {
        redisTemplate.boundValueOps(collageLockKey).set(status.getValue(), expireTime, TimeUnit.SECONDS);
    }

    /**
     * 获取拼单的锁定状态
     * @param collageLockKey
     * @return
     */
    private CollageLockStatus getCollageLock(String collageLockKey) throws Exception {
        return CollageLockStatus.getByValue(redisTemplate.boundValueOps(collageLockKey).get());
    }

    /**
     * 商户门店拼单参与用户名单设置
     * @param collagePartnerMemberKey
     * @param userId
     */
    private void putCollagePartnerMember(String collagePartnerMemberKey, String userId,  CollagePartnerMember collagePartnerMember) {
        redisTemplate.boundHashOps(collagePartnerMemberKey).put(userId, collagePartnerMember);
    }

    /**
     * 商户拼单参与用户名单删除拼单参与人
     * @param collagePartnerMemberKey
     * @param userIds
     */
    private void deleteCollagePartnerMember(String collagePartnerMemberKey, Object[] userIds) throws Exception {
        if (userIds == null || userIds.length == 0) return;
        redisTemplate.boundHashOps(collagePartnerMemberKey).delete(userIds);
    }

    /**
     * 获取当前商户门店下全部拼单参与用户列表
     * @param collagePartnerMemberKey
     * @return
     */
    private Map<String, CollagePartnerMember> getCollagePartnerMemberAll(String collagePartnerMemberKey) throws Exception {
        return Optional.ofNullable(redisTemplate.boundHashOps(collagePartnerMemberKey).entries()).orElseGet(() -> new HashMap());
    }

    /**
     * 获取商户下拼单参与人信息
     * @param collagePartnerMemberKey
     * @param userId
     * @return
     * @throws Exception
     */
    private CollagePartnerMember getCollagePartnerMember(String collagePartnerMemberKey, String userId) {
        Object obj = redisTemplate.boundHashOps(collagePartnerMemberKey).get(userId);
        return null != obj ? (CollagePartnerMember) obj : null;
    }

    /**
     * 查询当前用户是否存在进行中的拼单
     * @param collageOrderDto
     * @return
     */
    public boolean isInCollagePartnerMemberList(CollageOrderDto collageOrderDto) {
        String collagePartnerMemberKey = this.genCollagePartnerMemberHashKey(collageOrderDto.getPartnerId());
        // 获取当前用户在商户下的拼单信息
        CollagePartnerMember collagePartnerMember = this.getCollagePartnerMember(collagePartnerMemberKey, collageOrderDto.getCurrentUserId());

        // 当前登录用户ID存在且未超过过期时间
        if (collagePartnerMember != null && DateTimeUtils.currentTimeMillis() < collagePartnerMember.getExpire()) {
            return true;
        }
        return false;
    }

    /**
     * 拼单创建加购人列表初始化
     * @param collageMemberHashKey
     * @param currentUserId
     */
    private void initCollageMember(String collageMemberHashKey, String currentUserId) {
        redisTemplate.boundHashOps(collageMemberHashKey).put(currentUserId, Collections.EMPTY_LIST);
        redisTemplate.boundHashOps(collageMemberHashKey).expire(60 * 60L, TimeUnit.SECONDS);
    }

    /**
     * 拼单创建加购人状态初始化
     * 拼单发起人始终为加购完毕状态
     * @param collageMemberStateHashKey
     * @param collageOrderDto
     */
    public void initCollageMemberState(String collageMemberStateHashKey, CollageOrderDto collageOrderDto) {
        CollageMemberState collageMemberState = new CollageMemberState();
        collageMemberState.setUserId(collageOrderDto.getCurrentUserId());
        collageMemberState.setOpenId(collageOrderDto.getOpenId());
        collageMemberState.setNickName(collageOrderDto.getNickName());
        collageMemberState.setPhotoUrl(collageOrderDto.getPhotoUrl());
        collageMemberState.setState(CollageMemberStateType.SHOPPING.getValue());
        redisTemplate.boundHashOps(collageMemberStateHashKey).put(collageOrderDto.getCurrentUserId(), collageMemberState);
        redisTemplate.boundHashOps(collageMemberStateHashKey).expire(60 * 60L, TimeUnit.SECONDS);
    }

    /**
     * 拼单参与人加购状态
     * @param collageMemberStateHashKey
     * @param collageOrderDto
     */
    public void addCollageMemberState(String collageMemberStateHashKey, CollageOrderDto collageOrderDto) {
        CollageMemberState collageMemberState = new CollageMemberState();
        collageMemberState.setUserId(collageOrderDto.getCurrentUserId());
        collageMemberState.setOpenId(collageOrderDto.getOpenId());
        collageMemberState.setNickName(collageOrderDto.getNickName());
        collageMemberState.setPhotoUrl(collageOrderDto.getPhotoUrl());
        collageMemberState.setState(CollageMemberStateType.SHOPPING.getValue());
        redisTemplate.boundHashOps(collageMemberStateHashKey).put(collageOrderDto.getCurrentUserId(), collageMemberState);
    }

    /**
     * 获取拼单下全部加购人状态信息
     * @param collageMemberStateHashKey
     * @return
     */
    private List<CollageMemberState> getCollageMemberStateHash(String collageMemberStateHashKey) {
        return redisTemplate.boundHashOps(collageMemberStateHashKey).values();
    }

    /**
     * 获取加购人状态信息
     * @param collageMemberStateHashKey
     * @param userId
     * @return
     */
    public CollageMemberState getCollageMemberState(String collageMemberStateHashKey, String userId) {
        return (CollageMemberState) redisTemplate.boundHashOps(collageMemberStateHashKey).get(userId);
    }

    /**
     * 设置或更新加购人状态信息
     * @param collageMemberStateHashKey
     * @param collageMemberState
     */
    public void setCollageMemberState(String collageMemberStateHashKey, CollageMemberState collageMemberState) {
        redisTemplate.boundHashOps(collageMemberStateHashKey).put(collageMemberState.getUserId(), collageMemberState);
    }

    /**
     * 构建拼单购物车缓存key
     * @param partnerId
     * @param storeId
     * @param userId
     * @return
     */
    private String genCollageCarHashKey(String partnerId, String storeId, String userId) {
        return MessageFormat.format(RedisKeyConstant.COLLAGE_CART_HASH_KEY, partnerId, storeId, userId);
    }

    /**
     * 构建拼单基础缓存key
     * @param partnerId
     * @param storeId
     * @param userId
     * @return
     */
    private String genCollageBaseHashKey(String partnerId, String storeId, String userId) {
        return MessageFormat.format(RedisKeyConstant.COLLAGE_BASE_HASH_KEY, partnerId, storeId, userId);
    }

    /**
     * 构建拼单锁定状态缓存key
     * @param partnerId
     * @param storeId
     * @param userId
     * @return
     */
    private String genCollageLockKey(String partnerId, String storeId, String userId) {
        return MessageFormat.format(RedisKeyConstant.COLLAGE_LOCK_HASH_KEY, partnerId, storeId, userId);
    }

    /**
     * 构建拼单点餐位置缓存key
     * @param partnerId
     * @param storeId
     * @param userId
     * @return
     */
    private String genCollageMemberHashKey(String partnerId, String storeId, String userId) {
        return MessageFormat.format(RedisKeyConstant.COLLAGE_MEMBER_KEY, partnerId, storeId, userId);
    }

    /**
     * 构建拼单用户选好的状态缓存key
     * @param partnerId
     * @param storeId
     * @param userId
     * @return
     */
    public String genCollageMemberStateHashKey(String partnerId, String storeId, String userId) {
        return MessageFormat.format(RedisKeyConstant.COLLAGE_MEMBER_STATE_KEY, partnerId, storeId, userId);
    }

    /**
     * 构建拼单购物车版本号缓存key
     * @param partnerId
     * @param storeId
     * @param userId
     * @return
     */
    private String genCollageCarVerKey(String partnerId, String storeId, String userId) {
        return MessageFormat.format(RedisKeyConstant.COLLAGE_CART_VER_KEY, partnerId, storeId, userId);
    }

    /**
     * 拼单订单请求参数构造
     * @param collageOrderDto
     * @return
     */
    private Map<String, String> collageOrderRequest(CollageOrderDto collageOrderDto) {
        Map<String, String> request = new HashMap<>();
        request.put("partnerId", collageOrderDto.getPartnerId());
        request.put("storeId", collageOrderDto.getStoreId());
        request.put("createCollageUserId", collageOrderDto.getCreateCollageUserId());
        request.put("currentUserId", collageOrderDto.getCurrentUserId());
        return request;
    }
}
