/**
 * All rights Reserved, Designed By www.freemud.cn
 *
 * @Title: CouponServiceImpl
 * @Package cn.freemud.service.impl
 * @Description:
 * @author: song.cai
 * @date: 2018/12/24 18:40
 * @version V1.0
 * @Copyright: 2018 www.freemud.cn Inc. All rights reserved.
 * 注意：本内容仅限于上海非码科技内部传阅，禁止外泄以及用于其他的商业目
 */

package cn.freemud.service.impl;

import cn.freemud.adapter.CouponAdapter;
import cn.freemud.adapter.StoreAdapter;
import cn.freemud.adapter.StoreItemAdapter;
import cn.freemud.base.constant.Version;
import cn.freemud.base.entity.BaseResponse;
import cn.freemud.base.util.DateUtil;
import cn.freemud.constant.ResponseCodeConstant;
import cn.freemud.entities.dto.*;
import cn.freemud.entities.dto.activity.ActivityQueryResponseDto;
import cn.freemud.entities.dto.coupon.CouponAvailableRespDto;
import cn.freemud.entities.dto.openplatform.AddWeixinCardCodeRequestDto;
import cn.freemud.entities.dto.openplatform.AddWeixinCardCodeResponseDto;
import cn.freemud.entities.dto.openplatform.AddWeixinCardJudgeRequestDto;
import cn.freemud.entities.dto.openplatform.AddWeixinCardJudgeResponseDto;
import cn.freemud.entities.vo.*;
import cn.freemud.entities.vo.coupon.CouponAvailableReqVo;
import cn.freemud.entities.vo.coupon.CouponStateVo;
import cn.freemud.entities.vo.coupon.Product;
import cn.freemud.enums.*;
import cn.freemud.interceptor.ServiceException;
import cn.freemud.redis.RedisCache;
import cn.freemud.service.CommonService;
import cn.freemud.service.CouponService;
import cn.freemud.service.ItemService;
import cn.freemud.service.UserService;
import cn.freemud.service.thirdparty.*;
import cn.freemud.utils.*;
import com.alibaba.fastjson.JSON;
import com.freemud.application.sdk.api.productcenter.constant.ResponseConstant;
import com.freemud.application.sdk.api.productcenter.request.product.valid.ValidateShopProductRequest;
import com.freemud.application.sdk.api.productcenter.request.product.valid.ValidateShopProductType;
import com.freemud.application.sdk.api.productcenter.response.ProductResponseDTO;
import com.freemud.application.sdk.api.productcenter.response.valid.ValiadShopProductResponse;
import com.freemud.card.sdk.comm.Finals;
import com.freemud.card.sdk.comm.SignUtil;
import com.freemud.card.sdk.service.CouponAvailableService;
import com.freemud.card.sdk.service.GetCouponService;
import com.freemud.card.sdk.service.MemberProductService;
import com.freemud.card.sdk.vo.comm.GetCodeRespVo;
import com.freemud.card.sdk.vo.comm.GetCouponVo;
//import com.freemud.card.sdk.vo.coupon.CouponStateVo;
//import com.freemud.card.sdk.vo.coupon.Product;
//import com.freemud.card.sdk.vo.coupon.request.CouponAvailableReqVo;
import com.freemud.card.sdk.vo.coupon.CreateCouponVo;
import com.freemud.card.sdk.vo.coupon.request.MemberAddCouponVo;
import com.freemud.card.sdk.vo.coupon.response.MemberBaseRespVo;
import com.freemud.sdk.api.assortment.shoppingcart.constant.CartResponseConstant;
import com.freemud.sdk.api.assortment.shoppingcart.enums.BusinessTypeEnum;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalTime;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

@Service
@Slf4j
public class CouponServiceImpl implements CouponService {

    private final Gson gson = new Gson();
    //@Autowired

    //private MemberProductClient memberProductClient;
    @Autowired
    private CustomerExtendClient customerExtendClient;
    @Autowired
    private UserService userService;
    @Autowired
    private MemberProductService memberProductService;
    @Autowired
    private CouponAdapter couponAdapter;
    @Autowired
    private StoreAdapter storeAdapter;
    @Autowired
    private CouponOnlineClient couponOnlineClient;
    @Autowired
    private CouponOnlineMCCafeClient couponOnlineMCCafeClient;
    @Autowired
    private CouponAvailableService couponAvailableService;
    @Value("${coupon.app.id}")
    private String appid;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private CardBinClient cardBinClient;
    @Autowired
    private CardBinMCCafeClient cardBinMCCafeClient;
    @Autowired
    private StoreItemClient storeItemClient;
    @Autowired
    private StoreItemAdapter storeItemAdapter;
    @Autowired
    private CouponServiceImpl couponService;
    @Autowired
    private GetCouponService getCouponService;
    @Autowired
    private OpenPlatformClient openPlatformClient;
    @Autowired
    private ItemService itemService;
    @Autowired
    private CommonService commonService;
    @Value("${coupon.partner.id}")
    private String couponPartnerId;
    @Autowired
    private CouponAdapterClient couponAdaptClient;

    /**
     * 获取优惠券列表
     *
     * @param getMemberCouponListRequestVo
     * @return
     */
    @Override
    public BaseResponse<GetMemberCouponListResponseVo> getCouponList(GetMemberCouponListRequestVo getMemberCouponListRequestVo) {
        log.info("getMemberCouponListRequestVo" + gson.toJson(getMemberCouponListRequestVo));
        UserLoginInfoDto userLoginInfoDto = userService.getUserLoginInfoBySessionId(getMemberCouponListRequestVo.getSessionId());

        List<Integer> statusFlags = getMemberCouponListRequestVo.getStatusFlags();
        if (CollectionUtils.isNotEmpty(statusFlags) && statusFlags.size() == 1 && statusFlags.contains(0)) {
            statusFlags.add(-2);
        }
        String partnerId = getMemberCouponListRequestVo.getPartnerId();
        String memberId = userLoginInfoDto.getMemberId();
        Integer pageNumber = getMemberCouponListRequestVo.getPageNumber() == null ? 1 : getMemberCouponListRequestVo.getPageNumber();
        Integer pageSize = getMemberCouponListRequestVo.getPageSize() == null ? 10 : getMemberCouponListRequestVo.getPageSize();
        Integer pageCount = null;
        Integer totalRecord = null;
        // 会员服务的优惠券列表
        List<GetMemberCouponListResponseDto.Result.MemberCoupon> couponList = null;
        GetMemberCouponListRequestDto getMemberCouponListRequestDto = new GetMemberCouponListRequestDto(partnerId, memberId);
        getMemberCouponListRequestDto.setStatusFlags(statusFlags);
        getMemberCouponListRequestDto.setPageNum(pageNumber);
        getMemberCouponListRequestDto.setPageSize(pageSize);
        GetMemberCouponListResponseDto.Result result = this.getMemberCouponList(getMemberCouponListRequestDto);
        if (result != null) {
            couponList = result.getMemberCoupons();
            pageCount = result.getTotalPages();
            totalRecord = result.getTotalCount();
        }

        //查询有效优化券是否可以加入微信卡包状态
        AddWeixinCardJudgeResponseDto responseDto = null;
        if (CollectionUtils.isNotEmpty(couponList) && statusFlags.contains(0)) {
            AddWeixinCardJudgeRequestDto requestDto = couponAdapter.convert2AddWeixinCardJudgeRequestDto(couponList, partnerId, userLoginInfoDto.getUnionId());
            responseDto = openPlatformClient.addWeixinCardJudge(requestDto);
            LogUtil.info("openPlatformClient.addWeixinCardJudge**", gson.toJson(requestDto), gson.toJson(responseDto));
        }
        //获取券条形码
        Map<String, String> couponBarCodeMap = getCouponBarCodeMap(couponList);
        // 复制优惠券到Vo
        List<GetMemberCouponListResponseVo.MemberCoupon> memberCouponList = couponAdapter.convert2MemberCouponList(couponList, responseDto, couponBarCodeMap);
        //TODO 根据到期日期先后排序
        if (statusFlags.contains(0)) {
            //有效券
            memberCouponList.sort(Comparator.comparing(GetMemberCouponListResponseVo.MemberCoupon::getEndTime));
        } else {
            //无效券
            memberCouponList.sort(Comparator.comparing(GetMemberCouponListResponseVo.MemberCoupon::getEndTime).reversed());
        }

        GetMemberCouponListResponseVo getMemberCouponListResponseVo = new GetMemberCouponListResponseVo();
        getMemberCouponListResponseVo.setPageCount(pageCount == null ? 0 : pageCount);
        getMemberCouponListResponseVo.setTotalRecord(totalRecord == null ? 0 : totalRecord);
        getMemberCouponListResponseVo.setCoupons(memberCouponList);
        return ResponseUtil.success(getMemberCouponListResponseVo);
    }

    @Override
    public AddWeiXinCardResponseVo addWeiXinCard(AddWeiXinCardRequestVo requestVo) {
        UserLoginInfoDto userLoginInfoDto = userService.getUserLoginInfoBySessionId(requestVo.getSessionId());
        String appId = userLoginInfoDto.getWxAppid();
        String partnerId = userLoginInfoDto.getPartnerId();
        AddWeiXinCardResponseVo responseVo = new AddWeiXinCardResponseVo();
        //TODO 组装请求参数
        AddWeixinCardCodeRequestDto requestDto = new AddWeixinCardCodeRequestDto();
        requestDto.setWxAppid(appId);
        requestDto.setPartnerId(partnerId);
        List<AddWeixinCardCodeRequestDto.WeixinCardCodeAdd> list = Lists.newArrayList();
        AddWeixinCardCodeRequestDto.WeixinCardCodeAdd cardCodeAdd = new AddWeixinCardCodeRequestDto.WeixinCardCodeAdd();
        cardCodeAdd.setActivityCode(requestVo.getActivityCode());
        cardCodeAdd.setCouponCode(requestVo.getCouponCode());
        list.add(cardCodeAdd);
        requestDto.setWeixinCardCodeAddsList(list);
        AddWeixinCardCodeResponseDto responseDto = openPlatformClient.addWeiXinCardCode(requestDto);
        LogUtil.info("openPlatformClient.addWeiXinCardCode**", gson.toJson(requestDto), gson.toJson(responseDto));
        if (!responseDto.getCode().equals(ResponseCodeConstant.RESPONSE_SUCCESS_STR)) {
            throw new ServiceException(ResponseResult.COUPON_NOT_ADD_WEIXIN_CARD);
        }
        BeanUtil.convertBean(responseDto.getResult(), responseVo);
        return responseVo;
    }

    /**
     * 获取会员服务的优惠券列表
     *
     * @param getMemberCouponListRequestDto
     * @return
     */
    public GetMemberCouponListResponseDto.Result getMemberCouponList(GetMemberCouponListRequestDto getMemberCouponListRequestDto) {
        GetMemberCouponListResponseDto getMemberCouponListResponseDto = null;
        try {
            getMemberCouponListResponseDto = customerExtendClient.getMemberCouponListRequestDto(getMemberCouponListRequestDto);
        } catch (Exception ex) {
            log.error("会员服务优惠券接口调用失败", ex);
        }
        if (getMemberCouponListResponseDto != null && Objects.equals(getMemberCouponListResponseDto.getCode(), ResponseResult.SUCCESS.getCode())) {
            return getMemberCouponListResponseDto.getData();
        }
        return null;
    }

    @Override
    public BaseResponse receiveMemberCoupon(ReceiveMemberCouponRequestVo requestVo) {
        MemberAddCouponVo memberAddCouponVo = couponAdapter.convert2MemberAddCouponVo(requestVo);
        MemberBaseRespVo memberBaseRespVo = memberProductService.receiveMemberCoupon(memberAddCouponVo);
        LogUtil.info("memberProductService.receiveMemberCoupon***", memberAddCouponVo, memberBaseRespVo);
        return ResponseUtil.success(memberBaseRespVo);
    }

    @Override
    public GetCouponDetailResponseDto getMemberCoupon(GetMemberCouponRequestVo requestVo) {
        log.info("getMemberCoupon:" + gson.toJson(requestVo));
        //TODO 券详情查券服务
        Map<String, String> map = new TreeMap<String, String>();
        if (StringUtils.isBlank(requestVo.getPartnerId()) || StringUtils.isBlank(requestVo.getCouponCode())) {
            return null;
        }
        map.put(Finals.CODES, requestVo.getCouponCode());
        map.put(Finals.PARTNER_ID, requestVo.getPartnerId());
        map.put(Finals.MERCHANT_ID, requestVo.getPartnerId());
        map.put(Finals.ACTION, "code.allDetails");
        // 券码接口新增参数：组织机构（多个用英文逗号分离）
        String channelIds = commonService.getOrgIdsAsString(requestVo.getPartnerId(), requestVo.getStoreId());
        map.put(Finals.CHANNEL_CODE_LIST, channelIds);
        String appSecret = getAppSecret(requestVo.getPartnerId());
        String sign = SignUtil.createMD5Sign(map, appSecret);
        map.put(Finals.SIGN, sign);
        GetCouponDetailResponseDto responseDto = couponOnlineClient.getCouponDetails(map);
        LogUtil.info("couponOnlineClient.getCouponDetails****", map, gson.toJson(responseDto));
        if (ResponseCodeConstant.RESPONSE_SUCCESS_1.equals(responseDto.getResult())) {
            return responseDto;
        }
        return null;
    }

    @Override
    public GetCouponDetailResponseDto getMCCafeMemberCoupon(GetMemberCouponRequestVo requestVo) {
        log.info("getMemberCoupon:" + gson.toJson(requestVo));
        //TODO 券详情查券服务
        Map<String, String> map = new TreeMap<String, String>();
        if (StringUtils.isBlank(requestVo.getPartnerId()) || StringUtils.isBlank(requestVo.getCouponCode())) {
            return null;
        }
        map.put(Finals.CODES, requestVo.getCouponCode());
        map.put(Finals.PARTNER_ID, requestVo.getPartnerId());
        map.put(Finals.MERCHANT_ID, requestVo.getPartnerId());
        map.put(Finals.ACTION, "code.allDetails");
        // 券码接口新增参数：组织机构（多个用英文逗号分离）
        String channelIds = commonService.getOrgIdsAsString(requestVo.getPartnerId(), requestVo.getStoreId());
        map.put(Finals.CHANNEL_CODE_LIST, channelIds);
        String appSecret = getMCCafeAppSecret(requestVo.getPartnerId());
        String sign = SignUtil.createMD5Sign(map, appSecret);
        map.put(Finals.SIGN, sign);
        GetCouponDetailResponseDto responseDto = couponOnlineMCCafeClient.getMCCafeCouponDetails(map);
        LogUtil.info("couponOnlineClient.getCouponDetails****", map, gson.toJson(responseDto));
        if (ResponseCodeConstant.RESPONSE_SUCCESS_1.equals(responseDto.getResult())) {
            return responseDto;
        }
        return null;
    }

    /**
     * 批次查询
     */
    @Override
    public List<GetCouponDetailResponseDto.Details> getMemberCoupons(String partnerId, String storeId, List<String> codes) {
        String appSecret = getAppSecret(partnerId);
        // 最大15一提交
        int maxNum = 15;
        int count = codes.size() / maxNum;
        List<GetCouponDetailResponseDto.Details> details = Lists.newArrayList();
        //TODO 券详情查券服务
        for (int j = 0; j <= count; j++) {
            List calCouponCodes = null;
            if (j == count) {
                calCouponCodes = codes.subList(maxNum * j, codes.size());
            } else {
                calCouponCodes = codes.subList(maxNum * j, maxNum * j + maxNum);
            }
            Map<String, String> map = new TreeMap<String, String>();
            String couponCodes = calCouponCodes.toString();
            if (StringUtils.isBlank(couponCodes)) {
                return Collections.emptyList();
            }
            map.put(Finals.CODES, couponCodes.substring(1, couponCodes.length() - 1).replace(" ", ""));
            map.put(Finals.PARTNER_ID, partnerId);
            map.put(Finals.MERCHANT_ID, partnerId);
            map.put(Finals.ACTION, "code.allDetails");
            map.put(Finals.CHANNEL_ID_LIST, commonService.getOrgIdsAsString(partnerId, storeId));
            String sign = SignUtil.createMD5Sign(map, appSecret);
            map.put(Finals.SIGN, sign);
            GetCouponDetailResponseDto responseDto = couponOnlineClient.getCouponDetails(map);
            LogUtil.info("couponOnlineClient.getCouponDetails****", map, gson.toJson(responseDto));
            if (ResponseCodeConstant.RESPONSE_SUCCESS_1.equals(responseDto.getResult())) {
                details.addAll(responseDto.getDetails());
            }
        }
        return details;
    }

    @Override
    public String getAppSecret(String partnerId) {
        // 获取券服务的密钥
        String couponAppSecret = RedisUtil.getCouponAppSecret(partnerId);
        String appSecret = redisCache.getValue(couponAppSecret);
        if (StringUtils.isBlank(appSecret)) {
            GetAppKeyResponseDto getAppKeyResponseDto = cardBinClient.getAppKey(GetAppKeyRequestDto.builder().partnerId(partnerId).appId(appid).build());
            if (Objects.equals(String.valueOf(getAppKeyResponseDto.getStatusCode()), ResponseResult.SUCCESS.getCode())
                    && getAppKeyResponseDto.getData() != null) {
                redisCache.save(couponAppSecret, getAppKeyResponseDto.getData().getAppKey());
                appSecret = getAppKeyResponseDto.getData().getAppKey();
            }
        }
        return appSecret;
    }

    @Override
    public String getMCCafeAppSecret(String partnerId) {
        // 获取券服务的密钥
        String couponAppSecret = RedisUtil.getCouponAppSecret(partnerId);
        String appSecret = redisCache.getValue(couponAppSecret);
        if (StringUtils.isBlank(appSecret)) {
            GetAppKeyResponseDto getAppKeyResponseDto = cardBinMCCafeClient.getMCCafeAppKey(GetAppKeyRequestDto.builder().partnerId(partnerId).appId(appid).build());
            if (Objects.equals(String.valueOf(getAppKeyResponseDto.getStatusCode()), ResponseResult.SUCCESS.getCode())
                    && getAppKeyResponseDto.getData() != null) {
                redisCache.save(couponAppSecret, getAppKeyResponseDto.getData().getAppKey());
                appSecret = getAppKeyResponseDto.getData().getAppKey();
            }
        }
        return appSecret;
    }

    /**
     * key = 活动code , value = 返回是否匹配点餐方式
     */
    @Override
    public Map<String, Boolean> couponOrderWay(String partnerId, List<String> activityCodes, Integer orderTye) {
        // 去重
        List<String> activeCodes = new ArrayList<>(new HashSet(activityCodes));
        String appSecret = couponService.getAppSecret(partnerId);
        // 最大15一提交
        int maxNum = 15;
        int count = activeCodes.size() / maxNum;
        ActivityChannelEnum activityChannelEnum = PropertyConvertUtil.orderTypeConvert2ActivityChannel(orderTye);
        if (activityChannelEnum == null) {
            activityChannelEnum = ActivityChannelEnum.pickup;
        }
        Map<String, Boolean> result = new HashMap<>();
        for (int j = 0; j <= count; j++) {
            List calActiveCodes = null;
            if (j == count) {
                calActiveCodes = activeCodes.subList(maxNum * j, activeCodes.size());
            } else {
                calActiveCodes = activeCodes.subList(maxNum * j, maxNum * j + maxNum);
            }
            BatchQueryActivityInfoRequestDto requestDto = new BatchQueryActivityInfoRequestDto();
            requestDto.setActiveCode(calActiveCodes);
            // 书写逻辑
            requestDto.setPartnerId(Integer.valueOf(partnerId));
            String sign = SignUtil.createMD5Sign(requestDto, appSecret);
            requestDto.setSign(sign);
            BatchQueryActivityInfoResponseDto batchQueryActivityInfoResponseDto = cardBinClient.batchQueryActivityInfo(requestDto);
            if (Objects.equals(batchQueryActivityInfoResponseDto.getStatusCode(), ResponseCodeConstant.RESPONSE_SUCCESS_0_STR)
                    && CollectionUtils.isNotEmpty(batchQueryActivityInfoResponseDto.getActivities())) {
                ActivityChannelEnum finalActivityChannelEnum = activityChannelEnum;
                batchQueryActivityInfoResponseDto.getActivities().forEach(active -> {
                    // 兼容历史数据
                    if (Objects.isNull(active.getRedeemChannel())) {
                        result.put(active.getActiveCode(), true);
                    } else {
                        result.put(active.getActiveCode(), Arrays.stream(active.getRedeemChannel().split(",")).anyMatch(Predicate.isEqual(finalActivityChannelEnum.getCode())));
                    }
                });
            }
        }
        return result;
    }

    @Override
    public ActivityClassifyCouponBean availableCoupon(List<CartGoods> cartGoods
            , String partnerId
            , String userId
            , String storeId
            , String couponCode
            , boolean hasGoodsCoupon
            , Integer orderType
            , int isNew
            , String appId,String menuType, String chooseCouponCode) {
        GetMemberCouponListRequestDto getMemberCouponListRequestDto = new GetMemberCouponListRequestDto(partnerId, userId);
        getMemberCouponListRequestDto.setStatusFlags(Arrays.asList(CouponStatus.STATUS_0.getCode(), CouponStatus.STATUS_2.getCode()));
        getMemberCouponListRequestDto.setPageNum(1);
        getMemberCouponListRequestDto.setPageSize(Integer.MAX_VALUE);
        GetMemberCouponListResponseDto.Result result = getMemberCouponList(getMemberCouponListRequestDto);
        LogUtil.debug("CouponServiceImpl_getMemberCouponList", JSON.toJSONString(getMemberCouponListRequestDto), JSON.toJSONString(result));
        List<GetMemberCouponListResponseDto.Result.MemberCoupon> memberCoupons = Lists.newArrayList();
        // 过滤优惠券得点餐方式
        if (!Objects.isNull(result) && CollectionUtils.isNotEmpty(result.getMemberCoupons())) {
            List<String> activityCodes = result.getMemberCoupons().stream().map(GetMemberCouponListResponseDto.Result.MemberCoupon::getActivityCode).collect(Collectors.toList());
            Map<String, Boolean> activityCodesMap = couponOrderWay(partnerId, activityCodes, orderType);
            result.getMemberCoupons().forEach(memberCoupon -> {
                if (activityCodesMap.get(memberCoupon.getActivityCode()) != null && activityCodesMap.get(memberCoupon.getActivityCode())) {
                    memberCoupons.add(memberCoupon);
                }
            });
        }
        ActivityClassifyCouponBean availableCouponResponseVo = new ActivityClassifyCouponBean();
        // 可用优惠券信息
        List<ActivityCouponBean> usableCoupons = Lists.newArrayList();
        // 不可用优惠券信息
        List<ActivityCouponBean> disableCoupons = Lists.newArrayList();
        if (result == null || CollectionUtils.isEmpty(memberCoupons)) {
            return returnEmptyAvailableCoupon(availableCouponResponseVo, usableCoupons, disableCoupons);
        }
        // 对象转map
        Map<String, GetMemberCouponListResponseDto.Result.MemberCoupon> memberCouponMap = memberCoupons.stream().collect(
                Collectors.toMap(GetMemberCouponListResponseDto.Result.MemberCoupon::getCouponCode, a -> a, (k1, k2) -> k1));
        List<String> couponCodes = Lists.newArrayList();
        memberCoupons.forEach(memberCoupon -> {
            // 只筛选小于结束时间得券
            if (System.currentTimeMillis() < DateUtil.convert2Date(memberCoupon.getEndTime(), DateUtil.FORMAT_YYYY_MM_DD_HHMMSS).getTime()) {
                couponCodes.add(memberCoupon.getCouponCode());
            }
        });
        List<CouponStateVo> couponStateList = buildAvailiableCoupons(cartGoods, partnerId, storeId, couponCodes, isNew,appId,menuType);
        if (CollectionUtils.isNotEmpty(couponStateList)) {
            return returnSuccessAvailiableCoupons(couponCode, hasGoodsCoupon, availableCouponResponseVo, usableCoupons, disableCoupons, memberCouponMap, couponStateList, chooseCouponCode);
        }
        return null;
    }

    private List<CouponStateVo> buildAvailiableCoupons(List<CartGoods> cartGoods, String partnerId, String storeId, List<String> couponCodes, int isNew,String appId,String menuType) {
        String appSecret = getAppSecret(partnerId);
        // 最大15一提交
        int maxNum = 15;
        int count = couponCodes.size() / maxNum;
        // 计算可用不可用券
        CouponAvailableReqVo couponAvailableReqVo = new CouponAvailableReqVo();
        couponAvailableReqVo.setProviderId(partnerId);
        couponAvailableReqVo.setMerchantId(partnerId);
        couponAvailableReqVo.setStoreId(storeId);
        couponAvailableReqVo.setAppId(appId);
        List<Product> productList = Lists.newArrayList();
        // 优惠券优先级最高，根据商品原价做计算
        // 订单金额
        Long totalAmount = createProductRequest(cartGoods, productList, isNew);
        couponAvailableReqVo.setTotalAmount(Integer.valueOf(totalAmount + ""));
        couponAvailableReqVo.setProductList(productList);
        couponAvailableReqVo.setChannelCodeList(commonService.getOrgCodes(partnerId, storeId));
        if (StringUtils.isNotBlank(menuType)) {
            String code = BusinessTypeEnum.getByType(menuType).getCode();
            String channel = CouponRedeemChannel.getChannelByType(code);
            if (StringUtils.isNotBlank(channel)) {
                couponAvailableReqVo.setRedeemChannel(channel);
            }
        }

        // 构建计算SDK
        List<CouponStateVo> couponStateList = Lists.newArrayList();
        for (int j = 0; j <= count; j++) {
            List calCouponCodes = null;
            if (j == count) {
                calCouponCodes = couponCodes.subList(maxNum * j, couponCodes.size());
            } else {
                calCouponCodes = couponCodes.subList(maxNum * j, maxNum * j + maxNum);
            }
            // 书写逻辑
            couponAvailableReqVo.setCouponCodes(calCouponCodes);
            //CouponAvailableRespVo couponsAvailable = couponAvailableService.getCouponsAvailable(couponAvailableReqVo, appSecret);
            CouponAvailableRespDto couponsAvailable = couponAdaptClient.getCouponsAvailable(couponAvailableReqVo);
            ;
            LogUtil.info("availableCoupon_couponAvailableService.getCouponsAvailable", JSON.toJSONString(couponAvailableReqVo), JSON.toJSONString(couponsAvailable));
            if (Objects.equals(String.valueOf(couponsAvailable.getResult()), ResponseResult.SUCCESS.getCode())
                    && CollectionUtils.isNotEmpty(couponsAvailable.getCouponStateList())) {
                couponStateList.addAll(couponsAvailable.getCouponStateList());
            }
        }
        return couponStateList;
    }

    private ActivityClassifyCouponBean returnSuccessAvailiableCoupons(String couponCode, boolean hasGoodsCoupon, ActivityClassifyCouponBean availableCouponResponseVo, List<ActivityCouponBean> usableCoupons,
                                                                      List<ActivityCouponBean> disableCoupons, Map<String, GetMemberCouponListResponseDto.Result.MemberCoupon> memberCouponMap,
                                                                      List<CouponStateVo> couponStateList, String chooseCouponCode) {
        int disableCouponNum = 0;
        int usableCouponNum = 0;
        for (CouponStateVo couponStateVo : couponStateList) {
            // 过滤0得代金券
            if (Objects.equals(couponStateVo.getType(), CouponTypeEnum.TYPE_1.getCode())
                    && (couponStateVo.getOriginalPrice() == null
                    || couponStateVo.getOriginalPrice() == 0)) {
                continue;
            }

            // 过滤折扣券为0折得
            if (Objects.equals(couponStateVo.getType(), CouponTypeEnum.TYPE_3.getCode())
                    && (couponStateVo.getDiscount() == null
                    || couponStateVo.getDiscount() == 0)) {
                continue;
            }
            ActivityCouponBean activityCouponBean = new ActivityCouponBean();
            activityCouponBean.setCouponCode(couponStateVo.getCouponCode());
            GetMemberCouponListResponseDto.Result.MemberCoupon memberCoupon = memberCouponMap.get(couponStateVo.getCouponCode());
            if (memberCoupon != null) {
                activityCouponBean.setCouponName(memberCoupon.getCouponName());
                activityCouponBean.setEndTime(memberCoupon.getEndTime());
                if (Objects.equals(couponStateVo.getType(), CouponTypeEnum.TYPE_1.getCode())) {
                    activityCouponBean.setDiscountAmount(couponStateVo.getOriginalPrice() + "");
                } else if (Objects.equals(couponStateVo.getType(), CouponTypeEnum.TYPE_3.getCode())) {
                    // TODO 折扣券 百分值10 乘以10   前端统一除以100作为操作依据
                    activityCouponBean.setDiscountAmount(couponStateVo.getDiscount() != null ? couponStateVo.getDiscount() * 10 + "" : "0");
                }
                activityCouponBean.setThresholdDesc("满" + formatAmount((couponStateVo.getMinAmount() == null ? 0 : couponStateVo.getMinAmount()) * 1.00 / 100) + "元可用");
                activityCouponBean.setActivityDesc("不与其他活动优惠同时享受。");
                if (StringUtils.isNotBlank(couponStateVo.getMessage())){
                    String[] split = couponStateVo.getMessage().split(",");
                    if(split != null && split.length > 0){
                        activityCouponBean.setUnusedReason(split[0]);
                    } else {
                        activityCouponBean.setUnusedReason(couponStateVo.getMessage());
                    }
                } else {
                    activityCouponBean.setUnusedReason(couponStateVo.getMessage());
                }
                // 详情
                GetMemberCouponListResponseVo.MemberCouponDetail detail = new GetMemberCouponListResponseVo.MemberCouponDetail();
                detail.setActivityName(memberCoupon.getCouponName());
                String startDate = DateUtil.convert2String(DateUtil.convert2Date(memberCoupon.getStartTime(), DateUtil.FORMAT_yyyyMMdd_date), DateUtil.FORMAT_yyyyMMdd_date).replace("-", ".");
                String endDate = DateUtil.convert2String(DateUtil.convert2Date(memberCoupon.getEndTime(), DateUtil.FORMAT_yyyyMMdd_date), DateUtil.FORMAT_yyyyMMdd_date).replace("-", ".");
                detail.setEndTime(endDate);
                detail.setStartTime(startDate);
                String remark = memberCoupon.getActiveDesc();
                detail.setRemark(couponAdapter.getDescribeText(remark));
                if (Objects.equals(couponStateVo.getType(), CouponTypeEnum.TYPE_1.getCode())) {
                    detail.setAmountDesc("满" + formatAmount((couponStateVo.getMinAmount() == null ? 0 : couponStateVo.getMinAmount()) * 1.00 / 100) + "元减" + formatAmount((couponStateVo.getOriginalPrice() == null ? 0 : couponStateVo.getOriginalPrice()) * 1.00 / 100) + "元");
                } else if (Objects.equals(couponStateVo.getType(), CouponTypeEnum.TYPE_3.getCode())) {
                    detail.setAmountDesc("满" + formatAmount((couponStateVo.getMinAmount() == null ? 0 : couponStateVo.getMinAmount()) * 1.00 / 100) + "元" + formatAmount((couponStateVo.getDiscount() == null ? 0 : couponStateVo.getDiscount()) * 1.00 / 10) + "折");
                }
                // 设置条形码
                GetCouponBarCodeResponseVo responseVo = this.getCouponBarCode(couponStateVo.getCouponCode());
                detail.setCouponBarCode(responseVo.getBase64Image());

                activityCouponBean.setDetail(detail);
                activityCouponBean.setActivityCode(memberCoupon.getActivityCode());
                activityCouponBean.setCouponType(couponStateVo.getType());
                activityCouponBean.setDateDescribe(couponAdapter.getDateDescribe(memberCoupon.getStatus(), memberCoupon.getStartTime(), memberCoupon.getEndTime()));
                if (couponStateVo.getDailyAvailableTimes() == null && couponStateVo.getAvailableTimes() != null){
                    activityCouponBean.setDailyAvailableTimes(couponStateVo.getAvailableTimes());
                } else {
                    activityCouponBean.setDailyAvailableTimes(couponStateVo.getDailyAvailableTimes());
                }
                // 券状态 0 可用 1 不可用 2 限制可用
                if (Objects.equals(activityCouponBean.getCouponCode(), couponCode)) {
                    activityCouponBean.setSelected(YesOrNoEnum.YES.getCode());
                } else {
                    activityCouponBean.setSelected(YesOrNoEnum.NO.getCode());
                }
                if (hasGoodsCoupon) {
                    activityCouponBean.setCouponPic(memberCoupon.getLogo());
                    if (StringUtils.isNotBlank(chooseCouponCode) && chooseCouponCode.equals(activityCouponBean.getCouponCode())){
                        activityCouponBean.setSelected(YesOrNoEnum.YES.getCode());
                        usableCoupons.add(activityCouponBean);
                        usableCouponNum = usableCouponNum + 1;
                    } else {
                        if (Objects.equals(couponStateVo.getType(), CouponTypeEnum.TYPE_0.getCode()) || Objects.equals(couponStateVo.getType(), CouponTypeEnum.TYPE_4.getCode())){
                            activityCouponBean.setUnusedReason("商品券只能在点餐页");
                        }
                        disableCoupons.add(activityCouponBean);
                        disableCouponNum = disableCouponNum + 1;
                    }
                } else {
                    if (Objects.equals(couponStateVo.getState(), CouponStateEnum.STATE_1.getCode()) || (activityCouponBean.getDailyAvailableTimes() != null && activityCouponBean.getDailyAvailableTimes() == 0)) {
                        if (Objects.equals(couponStateVo.getType(), CouponTypeEnum.TYPE_0.getCode()) || Objects.equals(couponStateVo.getType(), CouponTypeEnum.TYPE_4.getCode())){
                            activityCouponBean.setCouponPic(memberCoupon.getLogo());
                            activityCouponBean.setUnusedReason("商品券只能在点餐页");
                        }
                        disableCoupons.add(activityCouponBean);
                        disableCouponNum = disableCouponNum + 1;
                    } else if (Objects.equals(couponStateVo.getType(), CouponTypeEnum.TYPE_0.getCode()) || Objects.equals(couponStateVo.getType(), CouponTypeEnum.TYPE_4.getCode())) {
                        activityCouponBean.setCouponPic(memberCoupon.getLogo());
                        activityCouponBean.setUnusedReason("商品券只能在点餐页");
                        disableCoupons.add(activityCouponBean);
                        disableCouponNum = disableCouponNum + 1;
                    } else {
                        usableCoupons.add(activityCouponBean);
                        usableCouponNum = usableCouponNum + 1;
                    }
                }
            }

        }
        availableCouponResponseVo.setCouponNum(disableCouponNum + usableCouponNum);
        availableCouponResponseVo.setDisableCouponNum(disableCouponNum);
        availableCouponResponseVo.setUsableCouponNum(usableCouponNum);
        availableCouponResponseVo.setDisableCoupons(disableCoupons);
        availableCouponResponseVo.setUsableCoupons(usableCoupons);
        return availableCouponResponseVo;
    }

    private Long createProductRequest(List<CartGoods> cartGoods, List<Product> productList, int isNew) {
        Long totalAmount = 0L;

        if (isNew == 1) {
            for (CartGoods cartGood : cartGoods) {
                // 剔除商品券得商品
                if (StringUtils.isEmpty(cartGood.getSkuId()) && StringUtils.isEmpty(cartGood.getSpuId())) {
                    continue;
                }
                Product product = new Product();
                product.setProductId(StringUtils.isEmpty(cartGood.getSkuId()) ? cartGood.getSpuId() : cartGood.getSkuId());
                // 普通商品价格
                Integer currentCouponDiscount = cartGood.getCurrentCouponDiscount() != null ? cartGood.getCurrentCouponDiscount() : 0;
                product.setAmount(cartGood.getAmount().intValue() + currentCouponDiscount);
                totalAmount = totalAmount + product.getAmount();
                // todo ：小料价格累加到主商品上
                if (CollectionUtils.isNotEmpty(cartGood.getProductMaterialList())) {
                    for (CartGoods.MaterialGoods materialGoods : cartGood.getProductMaterialList()) {
                        Integer materialCurrentCouponDiscount = materialGoods.getCurrentCouponDiscount() != null ? materialGoods.getCurrentCouponDiscount() : 0;
                        product.setAmount(product.getAmount() + materialGoods.getAmount().intValue() + materialCurrentCouponDiscount);
                        totalAmount = totalAmount + materialGoods.getAmount() + materialCurrentCouponDiscount;
                    }
                }
                // 可选搭配优惠累加到主商品上
                if (CollectionUtils.isNotEmpty(cartGood.getProductGroupList())) {
                    for (CartGoods.ComboxGoods comboxGoods : cartGood.getProductGroupList()) {
                        Integer comboxCurrentCouponDiscount = comboxGoods.getCurrentCouponDiscount() != null ? comboxGoods.getCurrentCouponDiscount() : 0;
                        totalAmount = totalAmount + comboxCurrentCouponDiscount;
                    }
                }
                // 数量
                product.setQuantity(1);
                productList.add(product);
            }
        } else {
            for (CartGoods cartGood : cartGoods) {
                // 剔除商品券得商品
                if (StringUtils.isEmpty(cartGood.getSkuId()) && StringUtils.isEmpty(cartGood.getSpuId())) {
                    continue;
                }
                Product product = new Product();
                product.setProductId(StringUtils.isEmpty(cartGood.getSkuId()) ? cartGood.getSpuId() : cartGood.getSkuId());
                // 普通商品价格
                product.setAmount(Integer.valueOf(cartGood.getOriginalPrice() + ""));
                // 套餐价格为： 套餐价+可选商品总价格
                if (ObjectUtils.equals(GoodsTypeEnum.SET_MEAL_GOODS.getGoodsType(), cartGood.getGoodsType())) {
                    Long finalPrice = cartGood.getFinalPrice();
                    if (CollectionUtils.isNotEmpty(cartGood.getProductGroupList())) {
                        finalPrice += cartGood.getProductGroupList().stream().mapToLong(group -> group.getFinalPrice() * group.getQty()).sum();
                    }
                    product.setAmount(finalPrice.intValue());
                }

                totalAmount = totalAmount + product.getAmount() * cartGood.getQty();
                // todo ：小料价格累加到主商品上
                if (CollectionUtils.isNotEmpty(cartGood.getProductMaterialList())) {
                    for (CartGoods.MaterialGoods materialGoods : cartGood.getProductMaterialList()) {
                        product.setAmount(product.getAmount() + Integer.valueOf(materialGoods.getOriginalPrice() * materialGoods.getQty() * cartGood.getQty() + ""));
                        totalAmount = totalAmount + materialGoods.getOriginalPrice() * materialGoods.getQty() * cartGood.getQty();
                    }
                }
                // 数量
                product.setQuantity(cartGood.getQty());
                productList.add(product);
            }
        }
        return totalAmount;
    }

    private ActivityClassifyCouponBean returnEmptyAvailableCoupon(ActivityClassifyCouponBean availableCouponResponseVo, List<ActivityCouponBean> usableCoupons, List<ActivityCouponBean> disableCoupons) {
        availableCouponResponseVo.setCouponNum(0);
        availableCouponResponseVo.setDisableCouponNum(0);
        availableCouponResponseVo.setUsableCouponNum(0);
        availableCouponResponseVo.setDisableCoupons(disableCoupons);
        availableCouponResponseVo.setUsableCoupons(usableCoupons);
        return availableCouponResponseVo;
    }

    private static Object formatAmount(Double amount) {
        if (amount % (amount.intValue()) == 0.0) {
            return amount.intValue();
        } else {
            return amount;
        }
    }

    @Override
    public CheckSpqInfoResponseDto checkSpqInfo(CheckSpqInfoRequestDto requestDto) {
        log.info("checkSpqInfo****" + gson.toJson(requestDto));
        String partnerId = requestDto.getPartnerId();
        String couponCode = requestDto.getCouponCode();
        String storeId = requestDto.getStoreId();
        //TODO 查询券详情券是否存在
        GetMemberCouponRequestVo requestVo = new GetMemberCouponRequestVo();
        requestVo.setPartnerId(partnerId);
        requestVo.setCouponCode(couponCode);
        requestVo.setStoreId(requestDto.getStoreId());
        GetCouponDetailResponseDto couponDetailResponseDto = couponService.getMemberCoupon(requestVo);
        LogUtil.info("couponService.getMemberCoupon", gson.toJson(requestVo), gson.toJson(couponDetailResponseDto));
        if (couponDetailResponseDto == null || !couponDetailResponseDto.getResult().equals(ResponseCodeConstant.RESPONSE_SUCCESS_1) || CollectionUtils.isEmpty(couponDetailResponseDto.getDetails())) {
            return null;
        }
        //校验商品券是否可用
        if (!Objects.equals(couponDetailResponseDto.getDetails().get(0).getStatus(), CouponStatus.STATUS_0.getCode())) {
            return null;
        }
        List<String> couPonstoreIds = Lists.newArrayList();
        //TODO 判断该券是否在这个门店下(一个券可以在多个门店下使用)
        if (CollectionUtils.isNotEmpty(couponDetailResponseDto.getDetails().get(0).getActiveRestrictionVOS())) {
            couponDetailResponseDto.getDetails().get(0).getActiveRestrictionVOS().forEach(activeRestrictionVOS -> {
                couPonstoreIds.add(activeRestrictionVOS.getStoreIdPartner());
            });
        }
        if (CollectionUtils.isNotEmpty(couPonstoreIds) && !couPonstoreIds.contains(storeId)) {
            return null;
        }
        //券返回的商品id
        List<String> skuIds = Lists.newArrayList();
        String skuId = couponDetailResponseDto.getDetails().get(0).getActiveProduct().get(0).getProductIdPartner();
        skuIds.add(String.valueOf(skuId));
        //TODO 通过skuid查询spuid
        Map<String, GetProductsVo> productsVoMap = itemService.getProducts(skuIds, partnerId, storeId , requestDto.getMenuType());
        GetProductsVo productsVo = productsVoMap.get(skuId);
        if (null == productsVo || !Objects.equals(productsVo.getStatus(), StoreItemStatus.PUT_ON_SALE.getCode())) {
            return null;
        }
        // 校验券的可用时间
        List<GetCouponDetailResponseDto.ActiveRedeemTimeInterval> activeRedeemTimeIntervalList = couponDetailResponseDto.getDetails().get(0).getActiveRedeemTimeIntervalList();
        boolean verificationPassed = checkCouonRedeemTime(activeRedeemTimeIntervalList);
        if (!verificationPassed){
            return null;
        }
        // 校验商品可用时间
        ValidateShopProductRequest request = getValidateShopProductRequest(productsVo, requestDto);
        ProductResponseDTO<ValiadShopProductResponse> valiadProductResponse = storeItemClient.validateShopProduct(request);
        if (null == valiadProductResponse || !Objects.equals(ResponseConstant.SUCCESS_RESPONSE_CODE, valiadProductResponse.getErrcode())
                || valiadProductResponse.getData() == null || CollectionUtils.isEmpty(valiadProductResponse.getData().getSuccessList())) {
            return null;
        }
        CheckSpqInfoResponseDto dto = new CheckSpqInfoResponseDto();
        dto.setCouponCode(couponCode);
        dto.setActiveCode(couponDetailResponseDto.getDetails().get(0).getActive().getActiveCode());
        dto.setCouponName(couponDetailResponseDto.getDetails().get(0).getTitle());
        dto.setActivityName(couponDetailResponseDto.getDetails().get(0).getActive().getActiveName());
        if (couponDetailResponseDto.getDetails().get(0).getActive().getMaxRedeemTimes() != null && couponDetailResponseDto.getDetails().get(0).getActive().getMaxRedeemTimes() > 1){
            if (couponDetailResponseDto.getDetails().get(0).getToday_available_times() != null){
                dto.setTodayAvailableTimes(couponDetailResponseDto.getDetails().get(0).getToday_available_times());
            } else {
                dto.setTodayAvailableTimes(1);
            }
        } else {
            dto.setTodayAvailableTimes(1);
        }
        dto.setPrice(productsVo.getFinalPrice());
        dto.setSpuId(productsVo.getSpuId());
        dto.setSpuName(productsVo.getSkuName());
        dto.setStockLimit(ObjectUtils.equals(1, productsVo.getStockLimit()));
        dto.setSkuId(productsVo.getSkuId());
        dto.setSkuName(StringUtils.isNotBlank(productsVo.getSkuName()) ? productsVo.getSkuName() : productsVo.getSpuName());
        dto.setPicture(productsVo.getSpuPicture());
        dto.setCouponType(0);
        log.info("dto***" + dto);
        return dto;
    }


    private boolean checkCouonRedeemTime(List<GetCouponDetailResponseDto.ActiveRedeemTimeInterval> activeRedeemTimeIntervalList) {
        boolean verificationPassed = false;
        if (CollectionUtils.isNotEmpty(activeRedeemTimeIntervalList)){
            for (GetCouponDetailResponseDto.ActiveRedeemTimeInterval dateLimit : activeRedeemTimeIntervalList){
                boolean dayCheck = true;
                String weekday = dateLimit.getWeekday(); // 日期限制 0011100 周日开始,0表示不可用
                if (StringUtils.isNotBlank(weekday)){ // 存在校验周几
                    char[] chars = weekday.toCharArray();
                    int dayOfWeek = LocalDate.now().getDayOfWeek().getValue();  // 从周一开始
                    if (dayOfWeek == 7){
                        dayOfWeek = 0;
                    }
                    if (Integer.parseInt(String.valueOf(chars[dayOfWeek])) == 0){ //限制
                        dayCheck = false;
                    }
                }
                boolean timeCheck = true;
                String begintime = dateLimit.getBegintime(); // 开始时间  00:00:00
                String endtime = dateLimit.getEndtime();  // 结束时间 12:59:59
                if (StringUtils.isNotBlank(begintime) && StringUtils.isNotBlank(endtime)){ // 存在校验时段
                    String[] beginTimeArr = begintime.split(":");
                    String[] endTimeArr = endtime.split(":");
                    LocalTime beginLocalTime = LocalTime.of(Integer.valueOf(beginTimeArr[0]), Integer.valueOf(beginTimeArr[1]), Integer.valueOf(beginTimeArr[2]));
                    LocalTime endLocalTime = LocalTime.of(Integer.valueOf(endTimeArr[0]), Integer.valueOf(endTimeArr[1]), Integer.valueOf(endTimeArr[2]));
                    LocalTime now = LocalTime.now();
                    if (now.isBefore(beginLocalTime) || now.isAfter(endLocalTime)){
                        timeCheck = false;
                    }
                }
                if (dayCheck && timeCheck){
                    verificationPassed = true;
                    break;
                }
            }
        } else {
            verificationPassed = true;
        }
        return verificationPassed;

    }

    private ValidateShopProductRequest getValidateShopProductRequest(GetProductsVo product, CheckSpqInfoRequestDto requestDto) {
        ValidateShopProductRequest request = new ValidateShopProductRequest();
        request.setChannel(requestDto.getMenuType());
        request.setPartnerId(requestDto.getPartnerId());
        request.setStoreId(requestDto.getStoreId());
        List<ValidateShopProductType> productTypeList = new ArrayList<>();
        ValidateShopProductType productType = new ValidateShopProductType();

        productType.setAttributeList(null);
        productType.setComboProductTypeList(null);
        productType.setMemberDiscount(null);
        productType.setPrice(product.getFinalPrice().intValue());
        productType.setProductGroupTypeList(null);
        productType.setSkuId(product.getSkuId());
        productType.setSpuId(product.getSpuId());
        productType.setUuid(UUID.randomUUID().toString());
        productType.setValidateAttribute(0);
        productType.setValidatePrice(0);
        productType.setValidateStatuses(null);

        productTypeList.add(productType);
        request.setProductTypeList(productTypeList);
        return  request;

    }

    /**
     * 换购券
     * 商品券支持多商品
     *
     * @param requestDto
     * @param goodsId
     * @return
     */
    @Override
    public CheckSpqInfoResponseDto checkSpqInfo(CheckSpqInfoRequestDto requestDto, String goodsId) {
        log.info("checkSpqInfo****" + gson.toJson(requestDto));
        String partnerId = requestDto.getPartnerId();
        String couponCode = requestDto.getCouponCode();
        String storeId = requestDto.getStoreId();
        //TODO 查询券详情券是否存在
        GetMemberCouponRequestVo requestVo = new GetMemberCouponRequestVo();
        requestVo.setPartnerId(partnerId);
        requestVo.setCouponCode(couponCode);
        requestVo.setStoreId(requestDto.getStoreId());
        GetCouponDetailResponseDto couponDetailResponseDto = couponService.getMemberCoupon(requestVo);
        LogUtil.info("couponService.getMemberCoupon", gson.toJson(requestVo), gson.toJson(couponDetailResponseDto));
        if (couponDetailResponseDto == null || !couponDetailResponseDto.getResult().equals(ResponseCodeConstant.RESPONSE_SUCCESS_1) || CollectionUtils.isEmpty(couponDetailResponseDto.getDetails())) {
            return null;
        }
        if (CollectionUtils.isEmpty(couponDetailResponseDto.getDetails())) {
            return null;
        }
        boolean productValid = false;
        Integer couponType = 0;
        GetCouponDetailResponseDto.Details couponActivityDetail = null;
        for (GetCouponDetailResponseDto.Details detail : couponDetailResponseDto.getDetails()) {
            if (productValid) break;
            if (!CouponStatus.STATUS_0.getCode().equals(detail.getStatus()) && !CouponStatus.STATUS_2.getCode().equals(detail.getStatus())) continue;
            for (GetCouponDetailResponseDto.ActiveProduct activeProduct : detail.getActiveProduct()) {
                if (goodsId.equals(activeProduct.getProductIdPartner())) {
                    productValid = true;
                    couponActivityDetail = detail;
                    couponType = CouponTypeEnum.TYPE_4.getCode();
                    break;
                }
            }
        }
        //检查商品是否有效
        if (!productValid) {
            return null;
        }
        //TODO 判断该券是否在这个门店下(一个券可以在多个门店下使用)
        List<String> couPonstoreIds = Lists.newArrayList();
        for (GetCouponDetailResponseDto.Details detail : couponDetailResponseDto.getDetails()) {
            if (!CouponStatus.STATUS_0.getCode().equals(detail.getStatus())) continue;
            for (GetCouponDetailResponseDto.ActiveRestrictionVOS activeRestrictionVO : detail.getActiveRestrictionVOS()) {
                couPonstoreIds.add(activeRestrictionVO.getStoreIdPartner());
            }
        }
        if (CollectionUtils.isNotEmpty(couPonstoreIds) && !couPonstoreIds.contains(storeId)) {
             return null;
        }

        //券返回的商品id
        List<String> skuIds = Lists.newArrayList();
        String skuId = goodsId;
        skuIds.add(skuId);
        //TODO 通过skuid查询spuid
        Map<String, GetProductsVo> productsVoMap = itemService.getProducts(skuIds, partnerId, storeId, requestDto.getMenuType());
        GetProductsVo productsVo = productsVoMap.get(skuId);
        if (null == productsVo || !Objects.equals(productsVo.getStatus(), StoreItemStatus.PUT_ON_SALE.getCode())) {
            return null;
        }
        // 校验券的可用时间
        List<GetCouponDetailResponseDto.ActiveRedeemTimeInterval> activeRedeemTimeIntervalList = couponDetailResponseDto.getDetails().get(0).getActiveRedeemTimeIntervalList();
        boolean verificationPassed = checkCouonRedeemTime(activeRedeemTimeIntervalList);
        if (!verificationPassed){
            return null;
        }
        // 校验商品可用时间
        ValidateShopProductRequest request = getValidateShopProductRequest(productsVo, requestDto);
        ProductResponseDTO<ValiadShopProductResponse> valiadProductResponse = storeItemClient.validateShopProduct(request);
        if (null == valiadProductResponse || !Objects.equals(ResponseConstant.SUCCESS_RESPONSE_CODE, valiadProductResponse.getErrcode())
                || valiadProductResponse.getData() == null || CollectionUtils.isEmpty(valiadProductResponse.getData().getSuccessList())) {
            return null;
        }
        CheckSpqInfoResponseDto dto = new CheckSpqInfoResponseDto();
        if (couponDetailResponseDto.getDetails().get(0).getActive().getMaxRedeemTimes() != null && couponDetailResponseDto.getDetails().get(0).getActive().getMaxRedeemTimes() > 1){
            if (couponDetailResponseDto.getDetails().get(0).getToday_available_times() != null){
                dto.setTodayAvailableTimes(couponDetailResponseDto.getDetails().get(0).getToday_available_times());
            } else {
                dto.setTodayAvailableTimes(1);
            }
        } else {
            dto.setTodayAvailableTimes(1);
        }
        dto.setCouponCode(couponCode);
        dto.setActiveCode(couponActivityDetail.getActive().getActiveCode());
        dto.setCouponName(couponActivityDetail.getTitle());
        dto.setActivityName(couponActivityDetail.getActive().getActiveName());
        dto.setPrice(productsVo.getFinalPrice());
        dto.setSpuId(productsVo.getSpuId());
        dto.setSpuName(productsVo.getSkuName());
        dto.setSkuId(productsVo.getSkuId());
        dto.setSkuName(StringUtils.isNotBlank(productsVo.getSkuName()) ? productsVo.getSkuName() : productsVo.getSpuName());
        dto.setPicture(productsVo.getSpuPicture());
        dto.setDefaultSpecName(productsVo.getDefaultSpecName());
        dto.setDefaultSpecId(productsVo.getDefaultSpecId());
        dto.setStockLimit(ObjectUtils.equals(1, productsVo.getStockLimit()));
        dto.setExtras(productsVo.getExtra());
        dto.setCouponType(couponType);
        log.info("dto***" + dto);
        return dto;
    }

    @Override
    public GetProductsVo getSpqProductInfo(CheckSpqInfoRequestDto requestDto) {
        String partnerId = requestDto.getPartnerId();
        String couponCode = requestDto.getCouponCode();
        String storeId = requestDto.getStoreId();
        //TODO 查询券详情券是否存在
        GetMemberCouponRequestVo requestVo = new GetMemberCouponRequestVo();
        requestVo.setPartnerId(partnerId);
        requestVo.setCouponCode(couponCode);
        requestVo.setStoreId(requestDto.getStoreId());
        GetCouponDetailResponseDto couponDetailResponseDto = couponService.getMemberCoupon(requestVo);
        LogUtil.info("couponService.getMemberCoupon", gson.toJson(requestVo), gson.toJson(couponDetailResponseDto));
        if (couponDetailResponseDto == null || !couponDetailResponseDto.getResult().equals(ResponseCodeConstant.RESPONSE_SUCCESS_1) || CollectionUtils.isEmpty(couponDetailResponseDto.getDetails())) {
            return null;
        }

        //券返回的商品id
        List<String> skuIds = Lists.newArrayList();
        String skuId = couponDetailResponseDto.getDetails().get(0).getActiveProduct().get(0).getProductIdPartner();
        skuIds.add(String.valueOf(skuId));
        //TODO 通过skuid查询spuid
        Map<String, GetProductsVo> productsVoMap = itemService.getProducts(skuIds, partnerId, storeId , requestDto.getMenuType());
        GetProductsVo productsVo = productsVoMap.get(skuId);
        if (null == productsVo || !Objects.equals(productsVo.getStatus(), StoreItemStatus.PUT_ON_SALE.getCode())) {
            return null;
        }

        // 校验商品可用时间
        ValidateShopProductRequest request = getValidateShopProductRequest(productsVo, requestDto);
        ProductResponseDTO<ValiadShopProductResponse> valiadProductResponse = storeItemClient.validateShopProduct(request);
        if (null == valiadProductResponse || !Objects.equals(ResponseConstant.SUCCESS_RESPONSE_CODE, valiadProductResponse.getErrcode())
                || valiadProductResponse.getData() == null || CollectionUtils.isEmpty(valiadProductResponse.getData().getSuccessList())) {
            return null;
        }

        return productsVo;
    }


    /**
     * 换购券
     * 商品券支持多商品
     *
     * @param requestDto
     * @param goodsId
     * @return
     */
    @Override
    public GetProductsVo getSpqProductInfo(CheckSpqInfoRequestDto requestDto, String goodsId) {
        log.info("checkSpqInfo****" + gson.toJson(requestDto));
        String partnerId = requestDto.getPartnerId();
        String couponCode = requestDto.getCouponCode();
        String storeId = requestDto.getStoreId();
        //TODO 查询券详情券是否存在
        GetMemberCouponRequestVo requestVo = new GetMemberCouponRequestVo();
        requestVo.setPartnerId(partnerId);
        requestVo.setCouponCode(couponCode);
        requestVo.setStoreId(requestDto.getStoreId());
        GetCouponDetailResponseDto couponDetailResponseDto = couponService.getMemberCoupon(requestVo);
        LogUtil.info("couponService.getMemberCoupon", gson.toJson(requestVo), gson.toJson(couponDetailResponseDto));
        if (couponDetailResponseDto == null || !couponDetailResponseDto.getResult().equals(ResponseCodeConstant.RESPONSE_SUCCESS_1) || CollectionUtils.isEmpty(couponDetailResponseDto.getDetails())) {
            return null;
        }
        if (CollectionUtils.isEmpty(couponDetailResponseDto.getDetails())) {
            return null;
        }
        Integer couponType = 0;

        //券返回的商品id
        List<String> skuIds = Lists.newArrayList();
        String skuId = goodsId;
        skuIds.add(skuId);
        //TODO 通过skuid查询spuid
        Map<String, GetProductsVo> productsVoMap = itemService.getProducts(skuIds, partnerId, storeId, requestDto.getMenuType());
        GetProductsVo productsVo = productsVoMap.get(skuId);
        if (null == productsVo || !Objects.equals(productsVo.getStatus(), StoreItemStatus.PUT_ON_SALE.getCode())) {
            return null;
        }

        // 校验商品可用时间
        ValidateShopProductRequest request = getValidateShopProductRequest(productsVo, requestDto);
        ProductResponseDTO<ValiadShopProductResponse> valiadProductResponse = storeItemClient.validateShopProduct(request);
        if (null == valiadProductResponse || !Objects.equals(ResponseConstant.SUCCESS_RESPONSE_CODE, valiadProductResponse.getErrcode())
                || valiadProductResponse.getData() == null || CollectionUtils.isEmpty(valiadProductResponse.getData().getSuccessList())) {
            return null;
        }

        return productsVo;
    }

    @Autowired
    private ActivityClient activityClient;

    private final static String application = "isaas";

    /**
     * 券来源:
     * 60:wechat
     * 61:xinmeida
     * 62:tmall
     * 63:isaas
     */
    private final static String SOURCE_FLAG = "63";

    private final static String FORMAT_YYYY_DD_23_59_59 = "yyyy-MM-dd 23:59:59";

    /**
     * 领券
     * 领券不需要关心应用和点餐方式
     *
     * @param activityDiscountDtos
     * @param partnerId
     * @param storeId
     * @param mobile
     * @param userId
     */
    @Override
    public List<CreateCouponBeanVo> createCoupon(List<ActivityDiscountDto> activityDiscountDtos, String partnerId, String storeId, String mobile, String userId) {
        Map<String, Integer> activityDiscountMap = activityDiscountDtos.stream().collect(Collectors.toMap(ActivityDiscountDto::getDiscountId, a -> a.getCount(), (k1, k2) -> k1));
        List<String> activityCodes = activityDiscountDtos.stream().map(ActivityDiscountDto::getDiscountId).collect(Collectors.toList());
        ActivityQueryRequestDto activityQueryRequestDto = ActivityQueryRequestDto.builder()
                .ver(Version.VERSION_1)
                .partnerCode(partnerId)
                .storeId(storeId)
                .userId(userId)
                .application(application)
                .activityCodes(activityCodes)
                .isShowBenefit(1)
                .isShowCycles(0)
                .isShowGoods(1)
                .isShowSendGoods(0)
                .isShowStore(0)
                .isShowTime(0)
                .build();
        // 领券调用统一查询接口不需要关心 appid, 和  点餐方式
        ActivityQueryResponseDto activityQueryResponseDto = activityClient.query(activityQueryRequestDto);
        LogUtil.debug("CouponServiceImpl_createCoupon", JSON.toJSONString(activityQueryRequestDto), JSON.toJSONString(activityQueryResponseDto));
        if (Objects.equals(activityQueryResponseDto.getStatusCode(), ResponseResult.SUCCESS.getCode())
                && CollectionUtils.isNotEmpty(activityQueryResponseDto.getResult())) {
            Long now = System.currentTimeMillis();
            // 构建券
            List<CreateCouponVo> coupons = buildCreateCoupons(activityDiscountMap, activityQueryResponseDto, now);
            GetCouponVo getCouponVo = new GetCouponVo();
            //
            getCouponVo.setPartner_id(Integer.valueOf(couponPartnerId));
            getCouponVo.setMerchant_id(Integer.valueOf(partnerId));
            if (StringUtils.isBlank(mobile)) {
                mobile = "18900000000";
            }
            getCouponVo.setMobile(mobile);
            getCouponVo.setMemberId(userId);
            getCouponVo.setAppSecret(getAppSecret(couponPartnerId));
            getCouponVo.setCoupons(coupons);
            log.info("CouponServiceImpl getCoupons start:{}", JSON.toJSONString(getCouponVo));
            GetCodeRespVo getCodeRespVo = getCouponService.getCoupons(getCouponVo);
            log.info("CouponServiceImpl getCoupons end:{}", JSON.toJSONString(getCodeRespVo));
            Map<String, ActivityResponseDto> activityResponseDtoMap = activityQueryResponseDto.getResult().stream().collect(
                    Collectors.toMap(ActivityResponseDto::getActivityCode, a -> a, (k1, k2) -> k1));
            if (Objects.equals(String.valueOf(getCodeRespVo.getResult()), ResponseResult.SUCCESS.getCode()) && CollectionUtils.isNotEmpty(getCodeRespVo.getCodeList())) {
                List<ActivityResponseDto> activityResponseDtos = Lists.newArrayList();
                getCodeRespVo.getCodeList().forEach(code -> {
                    if (activityResponseDtoMap.get(code.getActiveCode()) != null) {
                        ActivityResponseDto activityResponseDto = activityResponseDtoMap.get(code.getActiveCode());
                        activityResponseDto.setActivityCode(code.getCode());
                        activityResponseDto.setCode(code.getActiveCode());
                        activityResponseDtos.add(activityResponseDto);
                    }
                });
                List<CreateCouponBeanVo> createCouponBeanVos = convert2CreateCouponBeanVo(activityResponseDtos);
                return createCouponBeanVos;
            }
        }
        return null;
    }

    private List<CreateCouponVo> buildCreateCoupons(Map<String, Integer> activityDiscountMap, ActivityQueryResponseDto activityQueryResponseDto, Long now) {
        List<CreateCouponVo> coupons = Lists.newArrayList();
        for (ActivityResponseDto activityResponseDto : activityQueryResponseDto.getResult()) {
            // 多张券送多次
            int count = activityDiscountMap.get(activityResponseDto.getActivityCode()) != null ? activityDiscountMap.get(activityResponseDto.getActivityCode()) : 1;
            // 不再可领取有效期范围内直接过
            if (activityResponseDto.getStartTime() == null || activityResponseDto.getEndTime() == null) {
                continue;
            }
            if (now < activityResponseDto.getStartTime() || now > activityResponseDto.getEndTime()) {
                continue;
            }
            // 券活动状态不是已启用得过
            if (!Objects.equals(activityResponseDto.getActivityStatus(), ActivityStatusEnum.START.getCode())) {
                continue;
            }
            CreateCouponVo createCouponVo = new CreateCouponVo();
            String uuid = UUID.randomUUID().toString().replaceAll("-", "");
            createCouponVo.setOrder_id(uuid);
            createCouponVo.setNumber(count);
            createCouponVo.setTitle(activityResponseDto.getActivityName());
            createCouponVo.setState(0);
            createCouponVo.setTimestamp(DateUtil.convert2Str(new Date(), DateUtil.FORMAT_YYYY_MM_DD_HHMMSS));
            createCouponVo.setActive_code(activityResponseDto.getActivityCode());
            createCouponVo.setActive_name(activityResponseDto.getActivityName());
            createCouponVo.setPromotionActiveCode(activityResponseDto.getActivityCode());
            if (activityResponseDto.getValidityPeriodStart() != null && activityResponseDto.getValidityPeriodEnd() != null) {
                // 根据有效期来计算
                createCouponVo.setValid_start(DateUtil.convert2Str(new Date(activityResponseDto.getValidityPeriodStart()), DateUtil.FORMAT_YYYY_MM_DD_HHMMSS));
                createCouponVo.setValid_ends(DateUtil.convert2Str(new Date(activityResponseDto.getValidityPeriodEnd()), DateUtil.FORMAT_YYYY_MM_DD_HHMMSS));
            } else {
                // 根据固定时长来计算 天来计算
                int delayTimes = activityResponseDto.getDelayTimes() != null ? activityResponseDto.getDelayTimes() : 0;
                // 有效期为0  默认传1天，做兼容处理
                int validityPeriod = activityResponseDto.getValidityPeriod() != null ? activityResponseDto.getValidityPeriod() : 1;
                createCouponVo.setValid_start(DateUtil.convert2Str(DateUtil.addDays(new Date(), delayTimes), DateUtil.FORMAT_YYYY_MM_DD_HHMMSS));
                createCouponVo.setValid_ends(DateUtil.convert2Str(DateUtil.addDays(new Date(), (delayTimes + validityPeriod - 1)), FORMAT_YYYY_DD_23_59_59));
            }
            createCouponVo.setSourceFlag(SOURCE_FLAG);
            createCouponVo.setRemark(activityResponseDto.getActivityName());
            if (Objects.equals(activityResponseDto.getActivityType(), ActivityTypeEnum.TYPE_32.getCode())) {
                createCouponVo.setCouponType(CouponTypeEnum.TYPE_0.getCode() + "");
            } else if (Objects.equals(activityResponseDto.getActivityType(), ActivityTypeEnum.TYPE_3.getCode())) {
                createCouponVo.setCouponType(CouponTypeEnum.TYPE_1.getCode() + "");
            } else if (Objects.equals(activityResponseDto.getActivityType(), ActivityTypeEnum.TYPE_31.getCode())) {
                createCouponVo.setCouponType(CouponTypeEnum.TYPE_3.getCode() + "");
            }
            coupons.add(createCouponVo);
        }
        return coupons;
    }


    private List<CreateCouponBeanVo> convert2CreateCouponBeanVo(List<ActivityResponseDto> coupons) {
        List<CreateCouponBeanVo> createCouponBeanVos = Lists.newArrayList();
        if (CollectionUtils.isNotEmpty(coupons)) {
            coupons.forEach(coupon -> {
                CreateCouponBeanVo createCouponBeanVo = new CreateCouponBeanVo();
                createCouponBeanVo.setCouponType(Objects.equals(coupon.getActivityType(), ActivityTypeEnum.TYPE_3.getCode())
                        ? CouponTypeEnum.TYPE_1.getCode()
                        : Objects.equals(coupon.getActivityType(), ActivityTypeEnum.TYPE_31.getCode())
                        ? CouponTypeEnum.TYPE_3.getCode() : CouponTypeEnum.TYPE_0.getCode());
                createCouponBeanVo.setActivityName(coupon.getActivityName());
                // 券code 在外面赋值得是券code
                createCouponBeanVo.setCouponCode(coupon.getActivityCode());
                createCouponBeanVo.setActivityCode(coupon.getCode());
                createCouponBeanVo.setThresholdAmount(CollectionUtils.isNotEmpty(coupon.getBenefits()) ? coupon.getBenefits().get(0).getThresholdAmount() : 0);
                createCouponBeanVo.setDiscountAmount(CollectionUtils.isNotEmpty(coupon.getBenefits()) ? coupon.getBenefits().get(0).getDiscountAmount() : 0);
                if (coupon.getValidityPeriodStart() != null && coupon.getValidityPeriodEnd() != null) {
                    // 根据有效期来计算
                    createCouponBeanVo.setValidityPeriodStart(DateUtil.convert2Str(new Date(coupon.getValidityPeriodStart()), DateUtil.FORMAT_YYYY_MM_DD_HHMMSS));
                    createCouponBeanVo.setValidityPeriodEnd(DateUtil.convert2Str(new Date(coupon.getValidityPeriodEnd()), DateUtil.FORMAT_YYYY_MM_DD_HHMMSS));
                } else {
                    // 根据固定时长来计算 天来计算
                    int delayTimes = coupon.getDelayTimes() != null ? coupon.getDelayTimes() : 0;
                    int validityPeriod = coupon.getValidityPeriod() != null ? coupon.getValidityPeriod() : 0;
                    createCouponBeanVo.setValidityPeriodStart(DateUtil.convert2Str(DateUtil.addDays(new Date(), delayTimes), DateUtil.FORMAT_YYYY_MM_DD_HHMMSS));
                    createCouponBeanVo.setValidityPeriodEnd(DateUtil.convert2Str(DateUtil.addDays(new Date(), (delayTimes + validityPeriod)), DateUtil.FORMAT_YYYY_MM_DD_HHMMSS));
                }
                createCouponBeanVos.add(createCouponBeanVo);
            });
        }
        return createCouponBeanVos;
    }

    /**
     * 查询当前门店下可用商品券，循环获取
     *
     * @param partnerId
     * @param storeId
     * @param codes
     */
    public List<CouponStateVo> getCouponStateByStoreId(String partnerId, String storeId, List<String> codes) {
        String appSecret = getAppSecret(partnerId);
        // 最大15一提交
        int maxNum = 15;
        int count = codes.size() / maxNum;
        // 计算可用不可用券
        CouponAvailableReqVo couponAvailableReqVo = new CouponAvailableReqVo();
        couponAvailableReqVo.setMerchantId(partnerId);
        couponAvailableReqVo.setProviderId(partnerId);
        couponAvailableReqVo.setStoreId(storeId);
        List<Product> productList = Lists.newArrayList();
        // 优惠券优先级最高，根据商品原价做计算
        // 订单金额
        Long totalAmount = 0L;
        couponAvailableReqVo.setTotalAmount(Integer.valueOf(totalAmount + ""));
        couponAvailableReqVo.setProductList(productList);
        couponAvailableReqVo.setChannelCodeList(commonService.getOrgCodes(partnerId, storeId));
        // 构建计算SDK
        List<CouponStateVo> couponStateList = Lists.newArrayList();
        for (int j = 0; j <= count; j++) {
            List calCouponCodes = null;
            if (j == count) {
                calCouponCodes = codes.subList(maxNum * j, codes.size());
            } else {
                calCouponCodes = codes.subList(maxNum * j, maxNum * j + maxNum);
            }
            // 书写逻辑
            couponAvailableReqVo.setCouponCodes(calCouponCodes);
            log.info("availableCoupon couponAvailableService.getCouponsAvailable num:{};start:{}", j, JSON.toJSONString(couponAvailableReqVo));
            //CouponAvailableRespVo couponsAvailable = couponAvailableService.getCouponsAvailable(couponAvailableReqVo, appSecret);
            CouponAvailableRespDto couponsAvailable = couponAdaptClient.getCouponsAvailable(couponAvailableReqVo);
            log.info("availableCoupon couponAvailableService.getCouponsAvailable num:{};end:{}", j, JSON.toJSONString(couponsAvailable));
            if (Objects.equals(String.valueOf(couponsAvailable.getResult()), ResponseResult.SUCCESS.getCode())
                    && CollectionUtils.isNotEmpty(couponsAvailable.getCouponStateList())) {
                couponStateList.addAll(couponsAvailable.getCouponStateList());
            }
        }
        return couponStateList;
    }

    @Override
    public GetCouponBarCodeResponseVo getCouponBarCode(String couponCode) {
        byte[] bytes = BarcodeUtil.generateBarCode128(couponCode, 6D, null, true, false);
        String base64Image = Base64.getEncoder().encodeToString(bytes);
        String base64Prefix = "data:image/png;base64,";
        GetCouponBarCodeResponseVo getCouponBarCodeResponseVo = new GetCouponBarCodeResponseVo();
        getCouponBarCodeResponseVo.setBase64Image(base64Prefix + base64Image);
        return getCouponBarCodeResponseVo;
    }

    /**
     * 获取券条形码
     */
    public Map<String, String> getCouponBarCodeMap(List<GetMemberCouponListResponseDto.Result.MemberCoupon> couponList) {
        Map<String, String> CouponBarCodeMap = Maps.newHashMap();
        if (CollectionUtils.isNotEmpty(couponList)) {
            couponList.forEach(coupon -> {
                GetCouponBarCodeResponseVo responseVo = this.getCouponBarCode(coupon.getCouponCode());
                CouponBarCodeMap.put(coupon.getCouponCode(), responseVo.getBase64Image());
            });
        }
        return CouponBarCodeMap;
    }
}
