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

import cn.freemud.base.entity.BaseResponse;
import com.freemud.sdk.api.assortment.shoppingcart.adapter.CollageOrderSdkAdapter;
import com.freemud.sdk.api.assortment.shoppingcart.constant.CollageLockStatus;
import com.freemud.sdk.api.assortment.shoppingcart.constant.RedisKeyConstant;
import com.freemud.sdk.api.assortment.shoppingcart.constant.ShoppingCartConstant;
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.service.CollageOrderBaseService;
import com.freemud.sdk.api.assortment.shoppingcart.util.CartResponseUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.text.MessageFormat;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
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 CollageOrderSdkAdapter collageOrderSdkAdapter;

    @Autowired
    private RedisTemplate redisTemplate;

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

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

        // 若拼单订单信息不存在，则返回错误提示【拼单订单信息不存在】，由前端根据场景处理（静默、提示拼单已取消）
        if (ObjectUtils.isEmpty(collageOrder)) {
            return CartResponseUtil.error(ShoppingCartConstant.COLLAGE_ORDER_NOT_EXIST);
        }

        // 若拼单订单信息存在，则构造订单拼单对象并返回成功提示
        return CartResponseUtil.success(collageOrder);
    }

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

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

        if (ObjectUtils.isEmpty(collageOrder)) {
            // 若拼单信息不存在，则初始化拼单订单对象，放入Redis缓存并设置1小时失效时间，返回拼单订单对象并给出成功提示
            collageOrder = collageOrderSdkAdapter.toCollageOrder(collageOrderDto);
            collageOrder.setCollageId(UUID.randomUUID().toString());
            collageOrder.setCreateTime(LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli());
            collageOrder.setExpireTime(LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli() + 60 * 60 * 1000);
            // 创建缓存数据
            this.putCollageBaseHash(redisKey, collageOrder);
            return CartResponseUtil.success(collageOrder);
        }
        else {
            // 若拼单订单信息已存在，则返回错误提示【当前用户存在进行中的拼单订单】
            return CartResponseUtil.error(ShoppingCartConstant.COLLAGE_ORDER_ALREADY_EXIST);
        }
    }

    /**
     * 取消拼单订单
     * @param collageOrderDto
     * @return
     */
    @Override
    public BaseResponse cancelCollageOrder(CollageOrderDto collageOrderDto) {
        // 批量删除上述Key对应的Redis缓存
        this.deleteCollageBaseHash(this.collageOrderSdkAdapter.toCollageOrder(collageOrderDto));

        return CartResponseUtil.success();
    }

    /**
     * 锁定拼单订单
     * @param collageOrderDto
     * @return
     */
    @Override
    public BaseResponse lockCollageOrder(CollageOrderDto collageOrderDto) {
        this.setCollageLock(collageOrderDto.getPartnerId(), collageOrderDto.getStoreId(), collageOrderDto.getCreateCollageUserId(), CollageLockStatus.LOCKED);
        return this.getCollageLock(collageOrderDto.getPartnerId(), collageOrderDto.getStoreId(), collageOrderDto.getCreateCollageUserId()).getValue() ? CartResponseUtil.success() : CartResponseUtil.error("操作失败");
    }

    /**
     * 解锁拼单订单
     * @param collageOrderDto
     * @return
     */
    @Override
    public BaseResponse unlockCollageOrder(CollageOrderDto collageOrderDto) {
        this.setCollageLock(collageOrderDto.getPartnerId(), collageOrderDto.getStoreId(), collageOrderDto.getCreateCollageUserId(), CollageLockStatus.RELEASE);
        return !this.getCollageLock(collageOrderDto.getPartnerId(), collageOrderDto.getStoreId(), collageOrderDto.getCreateCollageUserId()).getValue() ? CartResponseUtil.success() : CartResponseUtil.error("操作失败");
    }

    /**
     * 获取拼单订单锁状态
     * @param collageOrderDto
     * @return
     */
    @Override
    public BaseResponse<Boolean> isLockedCollageOrder(CollageOrderDto collageOrderDto) {
        return CartResponseUtil.success(this.getCollageLock(collageOrderDto.getPartnerId(), collageOrderDto.getStoreId(), collageOrderDto.getCreateCollageUserId()).getValue());
    }

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

    /**
     * Redis写入拼单订单信息
     * @param redisKey
     * @param collageOrder
     */
    private void putCollageBaseHash(String redisKey, CollageOrder collageOrder) {
        redisTemplate.boundHashOps(redisKey).putAll(this.collageOrderSdkAdapter.toRedisMap(collageOrder));
        redisTemplate.boundHashOps(redisKey).expire(1L, TimeUnit.HOURS);
    }

    /**
     * Redis删除拼单订单信息以及相关购物车信息
     * @param collageOrder
     */
    private void deleteCollageBaseHash(CollageOrder collageOrder) {
        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);
    }

    /**
     * 拼单订单锁设定
     * @param partnerId
     * @param storeId
     * @param userId
     * @param status
     */
    private void setCollageLock(String partnerId, String storeId, String userId, CollageLockStatus status) {
        String collageLockKey = genCollageLockKey(partnerId, storeId, userId);
        redisTemplate.boundValueOps(collageLockKey).set(status.getValue(), 1L, TimeUnit.HOURS);
    }

    /**
     * 获取拼单的锁定状态
     * @param partnerId
     * @param storeId
     * @param userId
     * @return
     */
    private CollageLockStatus getCollageLock(String partnerId, String storeId, String userId) {
        String collageLockKey = genCollageLockKey(partnerId, storeId, userId);
        return CollageLockStatus.getByValue(redisTemplate.boundValueOps(collageLockKey).get());
    }

    /**
     * 构建拼单购物车缓存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
     */
    private 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);
    }
}
