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

import ch.qos.logback.classic.Level;
import cn.freemud.base.entity.BaseResponse;
import cn.freemud.redis.RedisCache;
import com.alibaba.fastjson.JSONObject;
import com.freemud.application.sdk.api.log.ApiLog;
import com.freemud.application.sdk.api.log.ErrorLog;
import com.freemud.sdk.api.assortment.shoppingcart.constant.CartResponseConstant;
import com.freemud.sdk.api.assortment.shoppingcart.constant.RedisKeyConstant;
import com.freemud.sdk.api.assortment.shoppingcart.constant.VersionUtils;
import com.freemud.sdk.api.assortment.shoppingcart.domain.CartAddItem;
import com.freemud.sdk.api.assortment.shoppingcart.domain.CartGoods;
import com.freemud.sdk.api.assortment.shoppingcart.domain.CartParamDto;
import com.freemud.sdk.api.assortment.shoppingcart.exception.ServiceException;
import com.freemud.sdk.api.assortment.shoppingcart.service.ShoppingCartBaseService;
import com.freemud.sdk.api.assortment.shoppingcart.util.CartResponseUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.text.MessageFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 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("collageCartBaseService")
public class CollageCartBaseServiceImpl implements ShoppingCartBaseService {

//    @Value("${coupon.app.id}")
//    private String appId;
//    @Autowired
//    private FMActiveSdkService fmActiveSdkService;

    @Autowired
    private RedisCache redisCache;

/*    @Autowired
    private RedisTemplate redisTemplate;*/

    @Override
    public BaseResponse<List<CartAddItem>> detailCart(CartParamDto cartParamDto, String trackingNo) {
        return null;
    }

    @Override
    public BaseResponse<List<CartGoods>> getCartGoodsList(CartParamDto cartParamDto, String trackingNo) {

        try {
            doCheck(cartParamDto);
            // 构建缓存key
            String collageCartHashKey = genCollageCarHashKey(cartParamDto.getPartnerId(), cartParamDto.getStoreId(), cartParamDto.getUserId());
            BoundHashOperations<String, String, CartGoods> operations = redisCache.getRedisTemplate().boundHashOps(collageCartHashKey);
            List<CartGoods> cartGoodsList = operations.values();
            return CartResponseUtil.success(cartGoodsList);
        } catch (Exception e) {
            ErrorLog.printErrorLog("获取拼单购物车异常", "CollageCartBaseServiceImpl/getCartGoodsList", cartParamDto,  e);
            return CartResponseUtil.error("获取拼单购物车异常");
        }
    }

    private void doCheck(CartParamDto cartParamDto) {
        if (StringUtils.isEmpty(cartParamDto.getStoreId()) || StringUtils.isEmpty(cartParamDto.getUserId())) {
            //门店和发起人不能为空
            throw new ServiceException(CartResponseConstant.FAIL, "门店号和发起人不能为空");
        }
    }

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


    @Override
    public BaseResponse<List<CartGoods>> setCartGoodsList(CartParamDto cartParamDto, String trackingNo) {
        try {
            RedisTemplate redisTemplate = redisCache.getRedisTemplate();

            String redisKey = genCollageCarHashKey(cartParamDto.getPartnerId(), cartParamDto.getStoreId(), cartParamDto.getUserId());
            BoundHashOperations<String, String, CartGoods> operations = redisTemplate.boundHashOps(redisKey);
            // 获取拼单购物车的有效期
            // 如果购物车已经存在则获取剩余的时间，如果不存在，则判断拼单是否失效
            // 获取拼单的剩余时间作为有效期
            Long expire =0L;
            if(redisTemplate.hasKey(redisKey)){
                expire = operations.getExpire();
            }else{
                // 如果不存在则使用拼单基础信息的剩余时间作为有效期
                // 如果拼单基础信息也过期了，直接返回不做操作
                expire = redisTemplate.boundHashOps(genCollageBaseHashKey(cartParamDto.getPartnerId(), cartParamDto.getStoreId(), cartParamDto.getUserId())).getExpire();
                if(expire < -1){
                    ApiLog.info("设置拼单购物车，拼单已经失效，param："+ JSONObject.toJSONString(cartParamDto));
                    return null;
                }
            }

            this.clear(cartParamDto, trackingNo);
            Map<String, CartGoods> cartGoodsMap = cartParamDto.getCartGoodsList().parallelStream()
                    .filter(k -> org.apache.commons.lang.StringUtils.isNotEmpty(k.getCartGoodsUid()))
                    .collect(Collectors.toMap(CartGoods::getCartGoodsUid, Function.identity(), (k1, k2) -> k1));
            operations.putAll(cartGoodsMap);
            operations.expire(expire,TimeUnit.SECONDS);

            return CartResponseUtil.success(cartParamDto.getCartGoodsList());
        } catch (Exception e) {
            ErrorLog.printErrorLog("设置拼单购物车异常", "CollageCartBaseServiceImpl/setCartGoodsList", cartParamDto,  e);
            return null;
        }
    }

    @Override
    public BaseResponse clear(CartParamDto cartParamDto, String trackingNo) {
        try {
            // 构建缓存key
            String collageCartHashKey = genCollageCarHashKey(cartParamDto.getPartnerId(), cartParamDto.getStoreId(), cartParamDto.getUserId());
            redisCache.delete(collageCartHashKey);
            return new BaseResponse(VersionUtils.VER_1, CartResponseConstant.SUCCESS.getCode(), CartResponseConstant.SUCCESS.getMessage());
        } catch (Exception e) {
            ErrorLog.printErrorLog("清空拼单购物车异常", "CollageCartBaseServiceImpl/clear", cartParamDto,  e);
            return null;
        }
    }

    @Override
    public String getCouponAppId() {
        return null;
    }

    @Override
    public Map<String, Boolean> getCouponOrderWay(String partnerId, List<String> activityCodes, Integer orderTye, String trackingNo) {
        return null;
    }

    @Override
    public BaseResponse<CartGoods> getCartGoods(CartParamDto cartParamDto, String trackingNo) {
        try {

            RedisTemplate redisTemplate = redisCache.getRedisTemplate();

            String redisKey = genCollageCarHashKey(cartParamDto.getPartnerId(),cartParamDto.getStoreId(),cartParamDto.getUserId());
            BoundHashOperations<String, String, CartGoods> operations = redisTemplate.boundHashOps(redisKey);
            CartGoods cartGoods = operations.get(cartParamDto.getCartGoodsUid());
            return CartResponseUtil.success(cartGoods);
        } catch (Exception e) {
            ErrorLog.printErrorLog("collageCartBaseServiceImpl", trackingNo, e.getMessage(), "getCartGoods", cartParamDto, e, Level.ERROR);
            return null;
        }
    }

    @Override
    public BaseResponse<List<CartGoods>> updateGoodsQty(CartParamDto cartParamDto, String trackingNo) {
        try {

            RedisTemplate redisTemplate = redisCache.getRedisTemplate();

            String redisKey = genCollageCarHashKey(cartParamDto.getPartnerId(),cartParamDto.getStoreId(),cartParamDto.getUserId());
            BoundHashOperations<String, String, CartGoods> operations = redisTemplate.boundHashOps(redisKey);
            CartGoods cartGoods = operations.get(cartParamDto.getCartGoodsUid());
            if (cartGoods != null) {
                // 当数量为0时,移除
                if (Objects.equals(cartParamDto.getQty(), 0)) {
                    operations.delete(cartParamDto.getCartGoodsUid());
                } else {
                    cartGoods.setQty(cartParamDto.getQty());
                    operations.put(cartParamDto.getCartGoodsUid(), cartGoods);
                }
            }
            return this.getCartGoodsList(cartParamDto, trackingNo);
        } catch (Exception e) {
            ErrorLog.printErrorLog("更新拼单购物车商品数量异常", "CollageCartBaseServiceImpl/updateGoodsQty", cartParamDto,  e);
            return null;
        }
    }

    /**
     * 获取当前购物车版本
     * 默认0
     * @param key
     * @return
     */
    public Integer getCartVersion(String key) {
        Integer value = null;
        try {
            value = redisCache.getValue(key);
        } catch (Exception e) {
            Map<String,String> request = new HashMap<>();
            request.put("key",key);
            ErrorLog.printErrorLog("获取当前购物车版本信息异常", "CollageCartBaseServiceImpl/getCartVersion", request,  e);
        }
        return value == null ? 0 : value;
    }

    /**
     * 构建拼单基础缓存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);
    }

    /**
     * 获取拼单基础
     * @param partnerId
     * @param storeId
     * @param userId
     * @return
     */
    public Map<String, String> getCollageBase(String partnerId, String storeId, String userId) {
        try {
            String collageBaseKey = genCollageBaseHashKey(partnerId, storeId, userId);
            return redisCache.hashGetAll(collageBaseKey);
        } catch (Exception e) {
            Map<String,String> request = new HashMap<>();
            request.put("partnerId",partnerId);
            request.put("storeId",storeId);
            request.put("userId",userId);
            ErrorLog.printErrorLog("获取拼单基础信息异常", "CollageCartBaseServiceImpl/getCollageBase", request,  e);
            return null;
        }
    }

    /**
     * 构建拼单锁定状态缓存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);
    }

    /**
     * 获取拼单的锁定状态
     * @param partnerId
     * @param storeId
     * @param userId
     * @return
     */
    public Boolean getCollageLock(String partnerId, String storeId, String userId) {
        try {
            String collageLockKey = genCollageLockKey(partnerId, storeId, userId);
            return redisCache.getValue(collageLockKey);
        } catch (Exception e) {
            Map<String,String> request = new HashMap<>();
            request.put("partnerId",partnerId);
            request.put("storeId",storeId);
            request.put("userId",userId);
            ErrorLog.printErrorLog("获取拼单锁定状态异常", "CollageCartBaseServiceImpl/getCollageLock", request,  e);
            return null;
        }
    }

    /**
     * 构建拼单点餐位置缓存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);
    }

    /**
     * 获取拼单点餐位
     * @param partnerId
     * @param storeId
     * @param userId
     * @return
     */
    public List<String> getCollageMemberHashKey(String partnerId, String storeId, String userId,String sessionId) {
        try {
            String collageMemberHashKey = genCollageMemberHashKey(partnerId, storeId, userId);
            return redisCache.hashGet(collageMemberHashKey,sessionId);
        } catch (Exception e) {
            Map<String,String> request = new HashMap<>();
            request.put("partnerId",partnerId);
            request.put("storeId",storeId);
            request.put("userId",userId);
            request.put("sessionId",sessionId);
            ErrorLog.printErrorLog("获取获取拼单点餐位异常", "CollageCartBaseServiceImpl/getCollageMemberHashKey", request,  e);
            return null;
        }
    }

    /**
     * 获取拼单点餐位人员信息
     * @param partnerId
     * @param storeId
     * @param userId
     * @return
     */
    public Set<String> getCollageMember(String partnerId, String storeId, String userId) {
        try {
            String collageMemberHashKey = genCollageMemberHashKey(partnerId, storeId, userId);
            return redisCache.getRedisTemplate().boundHashOps(collageMemberHashKey).keys();
        } catch (Exception e) {
            Map<String,String> request = new HashMap<>();
            request.put("partnerId",partnerId);
            request.put("storeId",storeId);
            request.put("userId",userId);
            ErrorLog.printErrorLog("获取拼单点餐位人员信息异常", "CollageCartBaseServiceImpl/getCollageMember", request,  e);
            return null;
        }
    }



    /**
     * 构建拼单用户选好的状态缓存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);
    }

    /**
     * 更新拼单人员缓存购物车行
     * @param cartGoodsUids
     * @param partnerId
     * @param storeId
     * @param crateUserId
     * @param userId
     */
    public void updateCollageCartGoodsUids(List<String> cartGoodsUids,String partnerId,String storeId,String crateUserId,String userId){
        String collageMemberKey = genCollageMemberHashKey(partnerId, storeId, crateUserId);
        redisCache.hashPut(collageMemberKey,userId,cartGoodsUids);
    }

    /**
     * 获取拼单人员缓存购物车行
     * @param partnerId
     * @param storeId
     * @param crateUserId
     * @param userId
     * @return
     */
    public List<String> getCollageCartGoodsUids(String partnerId,String storeId,String crateUserId,String userId){
        try {

            RedisTemplate redisTemplate = redisCache.getRedisTemplate();

            String collageMemberKey = genCollageMemberHashKey(partnerId, storeId, crateUserId);
            BoundHashOperations<String, String, List<String>> operations = redisTemplate.boundHashOps(collageMemberKey);
            List<String> goodsUids = operations.get(userId);
            return goodsUids;
        } catch (Exception e) {
            Map<String,String> request = new HashMap<>();
            request.put("partnerId",partnerId);
            request.put("storeId",storeId);
            request.put("crateUserId",crateUserId);
            request.put("userId",crateUserId);
            ErrorLog.printErrorLog("获取拼单人员缓存购物车行异常", "CollageCartBaseServiceImpl/getCollageCartGoodsUids", request, e);
            return null;
        }

    }

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

    /**
     * 构建拼单购物车加锁使用的key
     * @param partnerId
     * @param storeId
     * @param userId
     * @return
     */
    public String genCollageCarLockKey(String partnerId, String storeId, String userId) {
        return MessageFormat.format(RedisKeyConstant.COLLAGE_CART_LOCK_KEY, partnerId, storeId, userId);
    }

    /**
     * 增加购物车版本
     *
     * @param partnerId   商户号
     * @param storeId     门店号
     * @param userId 用户id
     * @return
     */
    public Integer incrementCartVersion(String partnerId, String storeId, String userId) {

        // 版本号加1
        Integer num = redisCache.opsForValue().increment(genCollageCarVerKey(partnerId, storeId, userId), 1).intValue();
        // 版本号设置有效期为拼单的有效期
        BoundHashOperations<String, String, String> operations = redisCache.getRedisTemplate().boundHashOps(genCollageBaseHashKey(partnerId, storeId, userId));
        Long expire = operations.getExpire();
        if(expire < -1){
            Map<String,String> request = new HashMap<>();
            request.put("partnerId",partnerId);
            request.put("storeId",storeId);
            request.put("userId",userId);
            ApiLog.info("增加购物车版本，拼单已经失效，param："+ JSONObject.toJSONString(request));
            return null;
        }

        redisCache.getRedisTemplate().expire(genCollageCarVerKey(partnerId, storeId, userId),expire,TimeUnit.SECONDS);
        return num;
    }

    public List<CartGoods> removeGoodsUids(String partnerId, String storeId, String userId,List<String> goodsUids) {

        RedisTemplate redisTemplate = redisCache.getRedisTemplate();

        String redisKey = genCollageCarHashKey(partnerId,storeId,userId);
        BoundHashOperations<String, String, CartGoods> operations = redisTemplate.boundHashOps(redisKey);
        if(null != goodsUids && !goodsUids.isEmpty()){
            operations.delete(goodsUids.toArray());
        }

        List<CartGoods> cartGoodsList = operations.values();
        //对创建时间进行排序
        cartGoodsList.sort(Comparator.comparingLong(CartGoods::getCreateTimeMili));
        return cartGoodsList;
    }

































}
