package com.liquidnet.service.kylin.utils;

import com.liquidnet.common.cache.redis.util.RedisUtil;
import com.liquidnet.commons.lang.util.CollectionUtil;
import com.liquidnet.commons.lang.util.DateUtil;
import com.liquidnet.service.adam.constant.AdamRedisConst;
import com.liquidnet.service.adam.dto.vo.AdamMemberVo;
import com.liquidnet.service.adam.dto.vo.AdamUserMemberVo;
import com.liquidnet.service.goblin.constant.GoblinRedisConst;
import com.liquidnet.service.goblin.dto.manage.vo.GoblinGoodsAnticipateValueVo;
import com.liquidnet.service.goblin.dto.vo.*;
import com.liquidnet.service.kylin.constant.KylinRedisConst;
import com.liquidnet.service.kylin.constant.KylinTableStatusConst;
import com.liquidnet.service.kylin.dao.KylinTicketActive;
import com.liquidnet.service.kylin.dto.vo.KylinApiCameraDevicesVo;
import com.liquidnet.service.kylin.dto.vo.KylinPerformanceSubscribeUpushVo;
import com.liquidnet.service.kylin.dto.vo.WqTempVo;
import com.liquidnet.service.kylin.dto.vo.admin.OrderRefundAddress;
import com.liquidnet.service.kylin.dto.vo.admin.OrderRefundPoundage;
import com.liquidnet.service.kylin.dto.vo.admin.OrderRefundPoundageAll;
import com.liquidnet.service.kylin.dto.vo.express.KylinOrderExpressRouteVo;
import com.liquidnet.service.kylin.dto.vo.express.KylinOrderExpressVo;
import com.liquidnet.service.kylin.dto.vo.mongo.*;
import com.liquidnet.service.kylin.dto.vo.partner.KylinTicketExpressModuleVo;
import com.liquidnet.service.kylin.dto.vo.partner.KylinTicketPartnerVo;
import com.liquidnet.service.kylin.dto.vo.returns.KylinOrderListVo;
import com.liquidnet.service.kylin.dto.vo.returns.KylinOrderRefundsVo;
import com.liquidnet.service.kylin.dto.vo.returns.NoticeKylinPerformanceVo;
import com.liquidnet.service.kylin.entity.KylinOrderCoupons;
import com.liquidnet.service.kylin.entity.KylinRecommendActive;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Component
@Slf4j
public class DataUtils {

    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    GoblinRedisUtils goblinRedisUtils;


    /**
     * 转赠订单
     *
     * @param uid
     * @param vo
     */
    public void setTransferOrder(String uid, KylinOrderTicketVo vo) {
        String redisKey = KylinRedisConst.ORDER_TRANSFER.concat(uid);
        redisUtil.set(redisKey, vo);
    }

    /**
     * 转赠订单
     *
     * @param uid
     */
    public KylinOrderTicketVo getTransferOrder(String uid) {
        String redisKey = KylinRedisConst.ORDER_TRANSFER.concat(uid);
        Object obj = redisUtil.get(redisKey);
        if (obj != null) {
            return (KylinOrderTicketVo) obj;
        } else {
            return null;
        }
    }

    /**
     * 转赠订单
     *
     * @param uid
     */
    public void delTransferOrder(String uid) {
        String redisKey = KylinRedisConst.ORDER_TRANSFER.concat(uid);
        redisUtil.del(redisKey);
    }

    /**
     * 转赠订单
     *
     * @param uid
     */
    public boolean hasTransferOrder(String uid) {
        String redisKey = KylinRedisConst.ORDER_TRANSFER.concat(uid);
        return redisUtil.hasKey(redisKey);
    }

    /**
     * 获取普通剩余库存
     *
     * @param ticketId 票id
     * @return 普通剩余库存
     */
    public int getSurplusGeneral(String ticketId) {
        return (int) redisUtil.get(KylinRedisConst.PERFORMANCES_INVENTORY + ticketId + ":" + KylinRedisConst.SURPLUS_GENERAL);
    }

    /**
     * 获取兑换剩余库存
     *
     * @param ticketId 票id
     * @return 普通剩余库存
     */
    public int getSurplusExchange(String ticketId) {
        return (int) redisUtil.get(KylinRedisConst.PERFORMANCES_INVENTORY + ticketId + ":" + KylinRedisConst.SURPLUS_EXCHANGE);
    }

    /**
     * 判断 当前库存是否售罄
     *
     * @param ticketId 票id
     * @return boolean
     */
    public boolean ticketIsSoldOut(String ticketId) {
        if (0 >= getSurplusGeneral(ticketId)) {
            return true;
        } else {
            return false;
        }
    }

    public void setOrderList(String userId, List<KylinOrderListVo> vo) {
        redisUtil.set(KylinRedisConst.ORDER_LIST + userId, vo);
    }

    public List<KylinOrderListVo> getOrderList(String userId) {
        Object obj = redisUtil.get(KylinRedisConst.ORDER_LIST + userId);
        if (obj != null) {
            return (List<KylinOrderListVo>) obj;
        } else {
            List<KylinOrderListVo> voList = mongoTemplate.find(Query.query(Criteria.where("userId").is(userId))
                            .with(Sort.by(Sort.Direction.DESC, "createdAt")).limit(40),
                    KylinOrderListVo.class, KylinOrderTicketVo.class.getSimpleName());
            for (KylinOrderListVo item : voList) {
                item.setStatus(item.getStatus());
            }
            redisUtil.set(KylinRedisConst.ORDER_LIST + userId, voList);
            return voList;
        }
    }

    /**
     * 根据订单id 获取 订单vo 详情
     *
     * @param orderId
     * @return
     */
    public KylinOrderTicketVo getOrderTicketVo(String orderId) {
        Object obj = redisUtil.get(KylinRedisConst.ORDER + orderId);
        if (obj != null) {
            return (KylinOrderTicketVo) obj;
        } else {
            KylinOrderTicketVo ticketData = mongoTemplate.findOne(Query.query(Criteria.where("orderTicketsId").is(orderId)), KylinOrderTicketVo.class, KylinOrderTicketVo.class.getSimpleName());
            if (ticketData == null) {
                return null;
            }
            List<KylinOrderTicketEntitiesVo> kylinOrderTicketEntitiesVoList = mongoTemplate.find(Query.query(Criteria.where("orderId").is(orderId)), KylinOrderTicketEntitiesVo.class, KylinOrderTicketEntitiesVo.class.getSimpleName());
            ticketData.setEntitiesVoList(kylinOrderTicketEntitiesVoList);
            redisUtil.set(KylinRedisConst.ORDER + orderId, ticketData);
            return ticketData;
        }
    }

    public void setOrderTicketVo(String orderId, KylinOrderTicketVo vo) {
        String redisKey = KylinRedisConst.ORDER + orderId;
        redisUtil.set(redisKey, vo);
    }

    /**
     * 删除订单redis
     *
     * @param orderId
     */
    public void delOrderTicketRedis(String orderId) {
        redisUtil.del(KylinRedisConst.ORDER + orderId);
    }


    /**
     * 获取 验票账号关系 vo
     *
     * @param checkUserId
     * @return
     */
    public KylinCheckUserPerformanceVo getCheckUserRelationVo(String checkUserId) {
        Object obj = redisUtil.get(KylinRedisConst.CHECK_USER_RELATION + checkUserId);
        if (obj != null) {
            return (KylinCheckUserPerformanceVo) obj;
        } else {
            KylinCheckUserPerformanceVo ticketData = mongoTemplate.findOne(Query.query(Criteria.where("checkUserId").is(checkUserId)), KylinCheckUserPerformanceVo.class, KylinCheckUserPerformanceVo.class.getSimpleName());
            redisUtil.set(KylinRedisConst.CHECK_USER_RELATION + checkUserId, ticketData);
            return ticketData;
        }
    }

    /**
     * 获取入场须知
     * 11：音乐节电子票实名 12：音乐节快递票实名 13音乐节电子票非实名 14音乐节快递票非实名 15：音乐节电子学生票实名 16：音乐节快递学生票实名 17音乐节电子学生票非实名 18音乐节快递学生票非实名
     * 21：巡演电子票实名 22：巡演快递票实名 23巡演电子票非实名 24巡演快递票非实名 25：巡演电子学生票实名 26：巡演快递学生票实名 27巡演电子学生票非实名 28巡演快递学生票非实名
     *
     * @param type       类型：101音乐节 102小型演出(livehouse演出) 103巡演
     * @param ticketType 票种类型：电子票electronic快递票express
     * @param isStudent  是否学生票：0否1是
     * @param isTrueName 是否实名：0否1是
     * @return
     */
    public String getEnterInfo(int type, String ticketType, Integer isStudent, Integer isTrueName) {
        String redisKey = KylinRedisConst.ENTER_INFO.concat(":type:" + type).concat(":ticketType:" + ticketType).concat(":isStudent:" + isStudent).concat(":isTrueName:" + isTrueName);
        Object obj = redisUtil.get(redisKey);
        if (obj != null) {
            return (String) obj;
        } else {
            String content = "";
            if (type == 101) {
                content = content.concat("音乐节");
            } else if (type == 102) {
                content = content.concat("巡演");
            } else if (type == 103) {
                content = content.concat("巡演");
            }

            if (isStudent == 0) {
                if (ticketType.equalsIgnoreCase("electronic")) {
                    content = content.concat("电子票");
                } else if (ticketType.equalsIgnoreCase("express")) {
                    content = content.concat("快递票");
                }
            } else if (isStudent == 1) {
                if (ticketType.equalsIgnoreCase("electronic")) {
                    content = content.concat("电子学生票");
                } else if (ticketType.equalsIgnoreCase("express")) {
                    content = content.concat("快递学生票");
                }
            }

            if (isTrueName == 0) {
                content = content.concat("非实名");
            } else if (isTrueName == 1) {
                content = content.concat("实名");
            }

            redisUtil.set(redisKey, content);
            return content;
        }
    }


    /**
     * 删除订单redis
     *
     * @param orderEntitiesId
     */
    public void delOrderTicketEntitiesRedis(String orderEntitiesId) {
        redisUtil.del(KylinRedisConst.ORDER_ENTITIES + orderEntitiesId);
    }

    /**
     * 根据演出id 获取 演出vo 详情
     *
     * @param performanceId
     * @return
     */
    public KylinPerformanceVo getPerformanceVo(String performanceId) {
        Object obj = redisUtil.get(KylinRedisConst.PERFORMANCES + performanceId);
        obj = null;
        if (obj != null) {
            return (KylinPerformanceVo) obj;
        } else {

            KylinPerformanceVo performanceData = mongoTemplate.findOne(Query.query(Criteria.where("performancesId").is(performanceId)), KylinPerformanceVo.class, KylinPerformanceVo.class.getSimpleName());
            redisUtil.set(KylinRedisConst.PERFORMANCES + performanceId, performanceData);
            return performanceData;
        }
    }

    /**
     * 获取分销用户名字
     *
     * @param agentId
     * @return
     */
    public String getAgentInfoName(String agentId) {
        String redisKey = KylinRedisConst.PERFORMANCES_AGENT_INFO.concat(agentId);
        String name = (String) redisUtil.getDB15RedisHGet(redisKey, "name");
//        String name = "";
        return name;
    }

    /**
     * 获取演出列表redis
     *
     * @param cityName
     */
    public List<KylinPerformanceVo> getPerformancesListOfcityNameOradCode(String cityName, Integer adCode) {
        if (!cityName.isEmpty()) {
            if (!cityName.endsWith("州") && !cityName.endsWith("县") && !cityName.endsWith("区") && !cityName.endsWith("市")) {
                cityName = cityName.concat("市");
            }
            adCode = CityJsonUtils.get(cityName);
        }
        String redisKey = KylinRedisConst.PERFORMANCES_LIST_CITY.concat(String.valueOf(adCode));
        Object object = redisUtil.get(redisKey);

        if (object == null) {
            // 固定查询条件
            Query query = getCommonWhere();
            // 其他条件
            query.addCriteria(Criteria.where("cityId").is(adCode));
            // 排序
            Sort sortName = Sort.by(Sort.Direction.ASC, "timeStart");
            query.with(sortName);
            // 不要查询的字段
            query.fields().exclude("details");
            query.fields().exclude("noticeImage");
            query.fields().exclude("ticketTimeList");
            query.fields().exclude("describeElectronic");
            List<KylinPerformanceVo> performancesList = mongoTemplate.find(query, KylinPerformanceVo.class, KylinPerformanceVo.class.getSimpleName());
            redisUtil.set(redisKey, performancesList);
            return performancesList;
        }
        return (List<KylinPerformanceVo>) object;
    }

    /**
     * 获取系统推荐演出列表redis
     */
    public List<KylinPerformanceVo> getPerformancesListIsSystemRecommend() {
        String redisKey = KylinRedisConst.PERFORMANCES_LIST_SYSTEM_RECOMMEND;
        Object obj = redisUtil.get(redisKey);
        if (obj == null) {
            // 固定条件
            Query query = getCommonWhere();
            // 排序
            Sort sortName = Sort.by(Sort.Direction.ASC, "timeStart");
            Pageable pageable = PageRequest.of(0, 8, sortName);
            query.with(pageable);
            // 不要查询的字段
            query.fields().exclude("details");
            query.fields().exclude("noticeImage");
            query.fields().exclude("ticketTimeList");
            query.fields().exclude("describeElectronic");
            // 推荐
            List<KylinPerformanceVo> systemRecommendList = mongoTemplate.find(query, KylinPerformanceVo.class, KylinPerformanceVo.class.getSimpleName());
            redisUtil.set(redisKey, systemRecommendList);
            return systemRecommendList;
        }
        return (List<KylinPerformanceVo>) obj;
    }


    /**
     * 获取演出预告列表redis
     */
    public HashMap<String, Object> getPerformancesListNotice() {
        HashMap<String, Object> info = CollectionUtil.mapStringObject();
        //演出
        List<KylinPerformanceVo> toDayList = ObjectUtil.getKylinPerformanceVoArrayList();
        List<KylinPerformanceVo> threeDaysList = ObjectUtil.getKylinPerformanceVoArrayList();
        //数字藏品
        List<NoticeGoblinGoodsSkuInfoVo> toDayNftVoList = ObjectUtil.getNoticeGoblinGoodsSkuInfoVoList();
        List<NoticeGoblinGoodsSkuInfoVo> threeDayNftVoList = ObjectUtil.getNoticeGoblinGoodsSkuInfoVoList();
        //组合购
        List<NoticeGoblinMixDetailsVo> toDayCombinationVoList = ObjectUtil.getNoticeGoblinMixDetailsVoList();
        List<NoticeGoblinMixDetailsVo> threeDayCombinationVoList = ObjectUtil.getNoticeGoblinMixDetailsVoList();
        Map<String, Object> map = getRedisNoticeIsd();
        if (map != null) {
            //获取ids
            List<String> toDayIds = (List<String>) map.get("toDayIds");
            List<String> threeDayIds = (List<String>) map.get("threeDayIds");
            List<String> toDayNftIds = (List<String>) map.get("toDayNftIds");
            List<String> threeNftIds = (List<String>) map.get("threeNftIds");
            List<String> toDayCombinationIds = (List<String>) map.get("toDayCombinationIds");
            List<String> threeDayCombinationIds = (List<String>) map.get("threeDayCombinationIds");

            // 固定条件
            toDayList = getKylinPerformanceVos(toDayIds);
            toDayList.forEach(kylinPerformanceVo -> {
                kylinPerformanceVo.setNoticeImage(null);
                kylinPerformanceVo.setTicketTimeList(null);
                kylinPerformanceVo.setDetails(null);
            });
            /*List<NoticeKylinPerformanceVo> toDayVoList = toDayList.stream().map(kylinPerformanceVo -> {
                return NoticeKylinPerformanceVo.getNew().copy(kylinPerformanceVo);
            }).collect(Collectors.toList());*/

            // 固定条件
            threeDaysList = getKylinPerformanceVos(threeDayIds);
            threeDaysList.forEach(kylinPerformanceVo -> {
                kylinPerformanceVo.setNoticeImage(null);
                kylinPerformanceVo.setTicketTimeList(null);
                kylinPerformanceVo.setDetails(null);
            });
            /*List<NoticeKylinPerformanceVo> threeDayVoList = threeDaysList.stream().map(kylinPerformanceVo -> {
                return NoticeKylinPerformanceVo.getNew().copy(kylinPerformanceVo);
            }).collect(Collectors.toList());*/

            try {
                //当天
                List<GoblinGoodsSkuInfoVo> toDaysNftList = getGoblinGoodsSkuInfoVos(toDayNftIds);
                toDayNftVoList = aboutDayNftVoList(toDaysNftList);


                //三天的
                List<GoblinGoodsSkuInfoVo> threeNftList = getGoblinGoodsSkuInfoVos(threeNftIds);
                threeDayNftVoList = aboutDayNftVoList(threeNftList);
            } catch (Exception e) {
                log.error("return NftVoList error!");
            }

            try {
                //当天
                List<GoblinMixDetailsVo> toDayCombinationList = getGoblinMixDetailsVos(toDayCombinationIds);
                toDayCombinationVoList = toDayCombinationList.stream().map(goblinMixDetailsVo -> NoticeGoblinMixDetailsVo.getNew().copy(goblinMixDetailsVo)).collect(Collectors.toList());

                //三天
                List<GoblinMixDetailsVo> threeDayCombinationList = getGoblinMixDetailsVos(threeDayCombinationIds);
                threeDayCombinationVoList = threeDayCombinationList.stream().map(goblinMixDetailsVo -> NoticeGoblinMixDetailsVo.getNew().copy(goblinMixDetailsVo)).collect(Collectors.toList());
            } catch (Exception e) {
                log.error("return CombinationVoList error!");
            }

        }
        info.put("toDayList", toDayList);
        info.put("threeDaysList", threeDaysList);
        //过滤数据
        info.put("toDaysNftList", toDayNftVoList);
        info.put("threeDayNftList", threeDayNftVoList);
        info.put("toDayCombinationList", toDayCombinationVoList);
        info.put("threeDayCombinationList", threeDayCombinationVoList);
        return info;
    }

    /**
     * 获取演出预告列表redis
     */
    public HashMap<String, Object> getPerformancesListNoticeOld() {
        String redisKey = KylinRedisConst.PERFORMANCES_LIST_NOTICE;
        Object obj = redisUtil.get(redisKey);
        if (obj == null) {
            // 固定条件
            Query query = getCommonWhere();
            // 排序
            Sort sortName = Sort.by(Sort.Direction.ASC, "sellTime");
            query.with(sortName);

            // 今天的
            HashMap toDayTime = DateUtil.oneDayStartEnd();
            String nowTimeTStr = (String) toDayTime.get("startStr");
            String toDayEndTimeStr = (String) toDayTime.get("endStr");
            query.addCriteria(Criteria.where("sellTime").gte(nowTimeTStr).lt(toDayEndTimeStr));
            query.fields().exclude("details");
            query.fields().exclude("noticeImage");
            query.fields().exclude("ticketTimeList");
            query.fields().exclude("describeElectronic");
            List<KylinPerformanceVo> toDayList = mongoTemplate.find(query, KylinPerformanceVo.class, KylinPerformanceVo.class.getSimpleName());
            List<String> roadShowId = toDayList.stream().filter(r -> !r.getRoadShowId().equals("0")).map(KylinPerformanceVo -> KylinPerformanceVo.getRoadShowId()).collect(Collectors.toList());

            // 固定条件
            Query queryT = getCommonWhere();
            // 排序
            Sort sortNameT = Sort.by(Sort.Direction.ASC, "sellTime");
            queryT.with(sortNameT);

            // 三天的
            Calendar cal = Calendar.getInstance();
            cal.setTime((Date) toDayTime.get("end"));
            Date beforeDayEnd = DateUtil.getBeforeDayEnd(cal, 2);
            String threeDaysLaterStr = DateUtil.SDF_YMD_HMS.format(beforeDayEnd);

            queryT.addCriteria(Criteria.where("sellTime").gte(toDayEndTimeStr).lt(threeDaysLaterStr));
            queryT.fields().exclude("details");
            queryT.fields().exclude("noticeImage");
            queryT.fields().exclude("ticketTimeList");
            queryT.fields().exclude("describeElectronic");
            queryT.addCriteria(Criteria.where("roadShowId").nin(roadShowId));
            List<KylinPerformanceVo> threeDaysList = mongoTemplate.find(queryT, KylinPerformanceVo.class, KylinPerformanceVo.class.getSimpleName());

            HashMap<String, Object> info = CollectionUtil.mapStringObject();
            info.put("toDayList", toDayList);
            info.put("threeDaysList", threeDaysList);
            redisUtil.set(redisKey, info);
            return info;
        }
        return (HashMap<String, Object>) obj;
    }

    private List<NoticeGoblinGoodsSkuInfoVo> aboutDayNftVoList(List<GoblinGoodsSkuInfoVo> toDaysNftList) {
        LocalDateTime now = LocalDateTime.now();
        String anticipateKey = GoblinRedisConst.ANTICIPATE_VALUE_SKUID;
        List<NoticeGoblinGoodsSkuInfoVo> toDayNftVoList = toDaysNftList.stream().map(goblinGoodsSkuInfoVo -> {
            NoticeGoblinGoodsSkuInfoVo noticeGoblinGoodsSkuInfoVo = NoticeGoblinGoodsSkuInfoVo.getNew().copy(goblinGoodsSkuInfoVo);


            //获取预约开始结束时间
            /*Object valueVo = redisUtil.get(anticipateKey.concat(goblinGoodsSkuInfoVo.getSkuId()));
            if (valueVo != null) {
                noticeGoblinGoodsSkuInfoVo = noticeGoblinGoodsSkuInfoVo.valueCopy((GoblinGoodsAnticipateValueVo) valueVo);
                noticeGoblinGoodsSkuInfoVo.setTagType(2);
            } else {
                //非预约sku  查询优先购分批购
                HashMap<String, Object> map = goblinRedisUtils.getGoodsSkuInfoVo(now, goblinGoodsSkuInfoVo.getSkuId());
                if (map != null) {
                    Integer tagType = (Integer) map.get("tagType");
                    String listId = (String) map.get("listId");
                    noticeGoblinGoodsSkuInfoVo.setTagType(tagType);
                    noticeGoblinGoodsSkuInfoVo.setListId(listId);
                }
            }*/
            //非预约sku  查询优先购分批购
            HashMap<String, Object> map = goblinRedisUtils.getGoodsSkuInfoVo(now, goblinGoodsSkuInfoVo.getSkuId());
            if (map != null) {
                Integer tagType = (Integer) map.get("tagType");
                String listId = (String) map.get("listId");
                noticeGoblinGoodsSkuInfoVo.setTagType(tagType);
                noticeGoblinGoodsSkuInfoVo.setListId(listId);
            }
            //根据spuId获取创作者  发行方
            GoblinGoodsInfoVo goodsInfoVo = goblinRedisUtils.getGoodsInfoVo(goblinGoodsSkuInfoVo.getSpuId());
            noticeGoblinGoodsSkuInfoVo.setPublisher(goodsInfoVo.getPublisher());
            noticeGoblinGoodsSkuInfoVo.setAuthor(goodsInfoVo.getAuthor());
            //普通数字藏品
            if (noticeGoblinGoodsSkuInfoVo.getTagType() == null) {
                noticeGoblinGoodsSkuInfoVo.setTagType(3);
            }
            return noticeGoblinGoodsSkuInfoVo;
        }).collect(Collectors.toList());
        return toDayNftVoList;
    }

    private List<GoblinMixDetailsVo> getGoblinMixDetailsVos(List<String> toDayCombinationIds) {
        List<GoblinMixDetailsVo> toDayCombinationList = ObjectUtil.getGoblinMixDetailsVoList();
        //redis key
        if (toDayCombinationIds != null && toDayCombinationIds.size() > 0) {
            //查询redis
            toDayCombinationIds.forEach(id -> {
                GoblinMixDetailsVo mixDetails = goblinRedisUtils.getMixDetails(id);
                for (GoblinMixDetailsItemVo item : mixDetails.getItem()) {
                    GoblinGoodsSkuInfoVo skuInfoVo = goblinRedisUtils.getGoodsSkuInfoVo(item.getSkuId());
                    item.setSkuName(skuInfoVo.getName());
                }
                toDayCombinationList.add(mixDetails);
            });

            /*Query queryToDayCombination = new Query();
            Sort sortToDayCombination = Sort.by(Sort.Direction.ASC, "saleStartTime");
            queryToDayCombination.with(sortToDayCombination);
            queryToDayCombination.fields().exclude("details");
            queryToDayCombination.addCriteria(Criteria.where("mixId").in(toDayCombinationIds));
            toDayCombinationList = mongoTemplate.find(queryToDayCombination, GoblinMixDetailsVo.class, GoblinMixDetailsVo.class.getSimpleName());
            toDayCombinationList.forEach(goblinMixDetailsVo -> {
                List<GoblinMixDetailsItemVo> item = goblinMixDetailsVo.getItem();
                item.forEach(goblinMixDetailsItemVo -> {
                    Query query = new Query();
                    query.addCriteria(Criteria.where("skuId").is(goblinMixDetailsItemVo.getSkuId()));
                    //skuName查询redis
                    Object objRk = redisUtil.get(rk.concat(goblinMixDetailsItemVo.getSkuId()));
                    if (objRk != null) {
                        goblinMixDetailsItemVo.setSkuName(((GoblinGoodsSkuInfoVo) objRk).getName());
                    }

                    //skuName查询mongodb
                    *//*GoblinGoodsSkuInfoVo one = mongoTemplate.findOne(query, GoblinGoodsSkuInfoVo.class, GoblinGoodsSkuInfoVo.class.getSimpleName());
                    if (one != null) {
                        goblinMixDetailsItemVo.setSkuName(one.getName());
                    }*//*
                });
            });*/
        }
        return toDayCombinationList;
    }


    private List<GoblinGoodsSkuInfoVo> getGoblinGoodsSkuInfoVos(List<String> toDayNftIds) {
        List<GoblinGoodsSkuInfoVo> toDaysNftList = ObjectUtil.getGoblinGoodsSkuInfoVoList();
        if (toDayNftIds != null && toDayNftIds.size() > 0) {
            //查询redis
            toDayNftIds.forEach(id -> {
                GoblinGoodsSkuInfoVo goodsSkuInfoVo = goblinRedisUtils.getGoodsSkuInfoVo(id);
                toDaysNftList.add(goodsSkuInfoVo);
            });
            //查询mongodb
            /*Query queryToDayNft = new Query();
            queryToDayNft.fields().exclude("extagVoList");
            queryToDayNft.addCriteria(Criteria.where("skuId").in(toDayNftIds));
            toDaysNftList = mongoTemplate.find(queryToDayNft, GoblinGoodsSkuInfoVo.class, GoblinGoodsSkuInfoVo.class.getSimpleName());*/
        }
        return toDaysNftList;
    }

    private List<KylinPerformanceVo> getKylinPerformanceVos(List<String> toDayIds) {
        List<KylinPerformanceVo> toDayList = ObjectUtil.getKylinPerformanceVoArrayList();
        if (toDayIds != null && toDayIds.size() > 0) {
            //查询redis
            toDayIds.forEach(id -> {
                KylinPerformanceVo one = getPerformanceVo(id);
                toDayList.add(one);
            });
        }
        return toDayList;
    }

    //执行脚本
    public HashMap<String, Object> setNoticeIds() {
        // 固定条件
        Query query = getCommonWhere();
        // 排序
        Sort sortName = Sort.by(Sort.Direction.ASC, "sellTime");
        query.with(sortName);
        // 今天的
        HashMap toDayTime = DateUtil.oneDayStartEnd();
        String nowTimeTStr = (String) toDayTime.get("startStr");
        String toDayEndTimeStr = (String) toDayTime.get("endStr");
        query.addCriteria(Criteria.where("sellTime").gte(nowTimeTStr).lt(toDayEndTimeStr));
        query.fields().exclude("details");
        query.fields().exclude("noticeImage");
        query.fields().exclude("ticketTimeList");
        query.fields().exclude("describeElectronic");
        List<KylinPerformanceVo> toDayList = mongoTemplate.find(query, KylinPerformanceVo.class, KylinPerformanceVo.class.getSimpleName());
        List<String> roadShowId = toDayList.stream().filter(r -> !r.getRoadShowId().equals("0")).map(KylinPerformanceVo -> KylinPerformanceVo.getRoadShowId()).collect(Collectors.toList());
        List<String> toDayIds = toDayList.stream().map(KylinPerformanceVo::getPerformancesId).collect(Collectors.toList());
        // 固定条件
        Query queryT = getCommonWhere();
        // 排序
        Sort sortNameT = Sort.by(Sort.Direction.ASC, "sellTime");
        queryT.with(sortNameT);
        // 三天的
        Calendar cal = Calendar.getInstance();
        cal.setTime((Date) toDayTime.get("end"));
        Date beforeDayEnd = DateUtil.getBeforeDayEnd(cal, 2);
        String threeDaysLaterStr = DateUtil.SDF_YMD_HMS.format(beforeDayEnd);
        queryT.addCriteria(Criteria.where("sellTime").gte(toDayEndTimeStr).lt(threeDaysLaterStr));
        queryT.fields().exclude("details");
        queryT.fields().exclude("noticeImage");
        queryT.fields().exclude("ticketTimeList");
        queryT.fields().exclude("describeElectronic");
        queryT.addCriteria(Criteria.where("roadShowId").nin(roadShowId));
        List<KylinPerformanceVo> threeDaysList = mongoTemplate.find(queryT, KylinPerformanceVo.class, KylinPerformanceVo.class.getSimpleName());
        List<String> threeDayIds = threeDaysList.stream().map(KylinPerformanceVo::getPerformancesId).collect(Collectors.toList());
        //数字藏品

        List<String> toDayNftIds = null;
        List<String> threeNftIds = null;
        try {
            DateTimeFormatter df = DateTimeFormatter.ofPattern(DateUtil.DATE_FULL_STR);
            LocalDateTime nowTime = LocalDateTime.parse(nowTimeTStr, df);
            LocalDateTime endTime = LocalDateTime.parse(toDayEndTimeStr, df);

            LocalDateTime threeEndTime = DateUtil.asLocalDateTime(beforeDayEnd);
            //查询预约(当天)
//        List<GoblinGoodsSkuInfoVo> toDayAboutNft = getAboutNftByStartAndEndTime(nowTimeTime, toDayEndTime,0);
//        List<String> toDayAboutNftSkuIds = toDayAboutNft.stream().map(GoblinGoodsSkuInfoVo::getSkuId).collect(Collectors.toList());
            /*List<String> toDayAboutNft = getAboutNftByStartAndEndTime(nowTimeTime, toDayEndTime, 0);*/
            //查询预约（三天）
//        List<GoblinGoodsSkuInfoVo> threeDayAboutNft = getAboutNftByStartAndEndTime(toDayEndTime, threeEndTime,1);
//        List<String> threeDayAboutNftSkuIds = threeDayAboutNft.stream().map(GoblinGoodsSkuInfoVo::getSkuId).collect(Collectors.toList());
//        toDayAboutNftSkuIds.addAll(threeDayAboutNftSkuIds);
            /*List<String> threeDayAboutNft = getAboutNftByStartAndEndTime(toDayEndTime, threeEndTime, 1);*/
        /*ArrayList<String> allListSkuIds = new ArrayList<>();
        allListSkuIds.addAll(toDayAboutNft);
        allListSkuIds.addAll(threeDayAboutNft);*/

            //当天
            Query queryToDayNft = new Query();
            queryToDayNft.addCriteria(Criteria.where("skuType").is(1));
            queryToDayNft.addCriteria(Criteria.where("delFlg").is("0"));
            queryToDayNft.addCriteria(Criteria.where("soldoutStatus").is("0"));
            queryToDayNft.addCriteria(Criteria.where("skuAppear").is("0"));
            queryToDayNft.addCriteria(Criteria.where("saleStartTime").gte(nowTime).lt(endTime));
//        queryToDayNft.addCriteria(Criteria.where("skuId").nin(toDayAboutNftSkuIds));
            /* queryToDayNft.addCriteria(Criteria.where("skuId").nin(allListSkuIds));*/
            queryToDayNft.addCriteria(Criteria.where("shelvesHandle").ne("3"));
            Sort sortNameToDayNft = Sort.by(Sort.Direction.ASC, "saleStartTime");
            queryToDayNft.with(sortNameToDayNft);
            List<GoblinGoodsSkuInfoVo> toDaysNftList = mongoTemplate.find(queryToDayNft, GoblinGoodsSkuInfoVo.class, GoblinGoodsSkuInfoVo.class.getSimpleName());
//        toDaysNftList.addAll(toDayAboutNft);
            toDayNftIds = toDaysNftList.stream().map(GoblinGoodsSkuInfoVo::getSkuId).collect(Collectors.toList());
            /*toDayNftIds.addAll(toDayAboutNft);*/

            //三天的
            Query queryThreeNft = new Query();
            queryThreeNft.addCriteria(Criteria.where("skuType").is(1));
            queryThreeNft.addCriteria(Criteria.where("delFlg").is("0"));
            queryThreeNft.addCriteria(Criteria.where("soldoutStatus").is("0"));
            queryThreeNft.addCriteria(Criteria.where("skuAppear").is("0"));
            queryThreeNft.addCriteria(Criteria.where("saleStartTime").gte(endTime).lt(threeEndTime));
            /*queryThreeNft.addCriteria(Criteria.where("skuId").nin(allListSkuIds));*/
            queryThreeNft.addCriteria(Criteria.where("shelvesHandle").ne("3"));
            Sort sortThreeNft = Sort.by(Sort.Direction.ASC, "saleStartTime");
            queryThreeNft.with(sortThreeNft);
            List<GoblinGoodsSkuInfoVo> threeNftList = mongoTemplate.find(queryThreeNft, GoblinGoodsSkuInfoVo.class, GoblinGoodsSkuInfoVo.class.getSimpleName());
//        threeNftList.addAll(threeDayAboutNft);
            threeNftIds = threeNftList.stream().map(GoblinGoodsSkuInfoVo::getSkuId).collect(Collectors.toList());
            /*threeNftIds.addAll(threeDayAboutNft);*/
        } catch (Exception e) {
            log.error("get NftIds error!");
        }

        //组合购
        List<String> toDayCombinationIds = null;
        List<String> threeDayCombinationIds = null;
        try {
            //当天
            Query queryToDayCombination = new Query();
            Sort sortToDayCombination = Sort.by(Sort.Direction.ASC, "saleStartTime");
            queryToDayCombination.addCriteria(Criteria.where("timeStart").gte(nowTimeTStr).lt(toDayEndTimeStr));
            queryToDayCombination.addCriteria(Criteria.where("status").ne(7));
            queryToDayCombination.with(sortToDayCombination);
            List<GoblinMixDetailsVo> toDayCombinationList = mongoTemplate.find(queryToDayCombination, GoblinMixDetailsVo.class, GoblinMixDetailsVo.class.getSimpleName());
            toDayCombinationIds = toDayCombinationList.stream().map(GoblinMixDetailsVo::getMixId).collect(Collectors.toList());
            //三天
            Query queryThreeDayCombination = new Query();
            Sort sortThreeDayCombination = Sort.by(Sort.Direction.ASC, "saleStartTime");
            queryThreeDayCombination.addCriteria(Criteria.where("timeStart").gte(toDayEndTimeStr).lt(threeDaysLaterStr));
            queryThreeDayCombination.addCriteria(Criteria.where("status").ne(7));
            queryThreeDayCombination.with(sortThreeDayCombination);
            List<GoblinMixDetailsVo> threeDayCombinationList = mongoTemplate.find(queryThreeDayCombination, GoblinMixDetailsVo.class, GoblinMixDetailsVo.class.getSimpleName());
            threeDayCombinationIds = threeDayCombinationList.stream().map(GoblinMixDetailsVo::getMixId).collect(Collectors.toList());
        } catch (Exception e) {
            log.error("get CombinationIds error!");
        }


        //缓存ids
        HashMap<String, Object> idsList = CollectionUtil.mapStringObject();
        idsList.put("toDayIds", toDayIds);
        idsList.put("threeDayIds", threeDayIds);
        idsList.put("toDayNftIds", toDayNftIds);
        idsList.put("threeNftIds", threeNftIds);
        idsList.put("toDayCombinationIds", toDayCombinationIds);
        idsList.put("threeDayCombinationIds", threeDayCombinationIds);
        setRedisNoticeIsd(idsList);
        return idsList;
    }

    //    private List<GoblinGoodsSkuInfoVo> getAboutNftByStartAndEndTime(LocalDateTime nowTime, LocalDateTime EndTime,Integer tag) {
    private List<String> getAboutNftByStartAndEndTime(LocalDateTime nowTime, LocalDateTime EndTime, Integer tag) {
        Query aboutQuery = new Query();
        if (tag.equals(0)) {
            //当天   查询当天可预约的nft   预约结束时间>当前时间>预约开始
            aboutQuery.addCriteria(Criteria.where("aboutStartDate").lt(nowTime));
            aboutQuery.addCriteria(Criteria.where("aboutEndDate").gte(EndTime));
        } else {
            //三天   预约开始时间 范围在三天以内
            aboutQuery.addCriteria(Criteria.where("aboutStartDate").gte(nowTime).lt(EndTime));
        }
        aboutQuery.addCriteria(Criteria.where("delTag").is(0));
        List<GoblinGoodsAnticipateValueVo> aboutQueryList = mongoTemplate.find(aboutQuery, GoblinGoodsAnticipateValueVo.class, GoblinGoodsAnticipateValueVo.class.getSimpleName());
        List<String> aboutIds = aboutQueryList.stream().map(GoblinGoodsAnticipateValueVo::getSkuId).collect(Collectors.toList());
        if (aboutIds.size() > 0) {
           /* Query queryAbout = new Query();
            queryAbout.addCriteria(Criteria.where("skuId").in(aboutIds));
            return mongoTemplate.find(queryAbout, GoblinGoodsSkuInfoVo.class, GoblinGoodsSkuInfoVo.class.getSimpleName());*/
            return aboutIds;
        }
        return new ArrayList<>();
    }

    /**
     * 获取推荐演出列表redis
     */
    public List<KylinPerformanceVo> getPerformancesListIsRecommend() {
        String redisKey = KylinRedisConst.PERFORMANCES_LIST_RECOMMEND;
        Object obj = redisUtil.get(redisKey);
        if (obj == null) {
            // 固定条件
            Query query = getCommonWhere();
            // 排序
            Sort sortName = Sort.by(Sort.Direction.DESC, "isRecommend");
            query.with(sortName);
            // 不要查询的字段
            query.fields().exclude("details");
            query.fields().exclude("noticeImage");
            query.fields().exclude("ticketTimeList");
            query.fields().exclude("describeElectronic");
            // 推荐
            query.addCriteria(Criteria.where("isRecommend").gte(1));
            List<KylinPerformanceVo> recommendList = mongoTemplate.find(query, KylinPerformanceVo.class, KylinPerformanceVo.class.getSimpleName());
            redisUtil.set(redisKey, recommendList);
            return recommendList;
        }
        return (List<KylinPerformanceVo>) obj;
    }

    /**
     * 获取会员专属演出列表redis
     */
    public List<KylinPerformanceVo> getPerformancesListIsExclusive() {
        String redisKey = KylinRedisConst.PERFORMANCES_LIST_EXCLUSIVE;
        Object obj = redisUtil.get(redisKey);
        if (obj == null) {
            // 固定条件
            Query query = getCommonWhere();
            // 不要查询的字段
            query.fields().exclude("details");
            query.fields().exclude("noticeImage");
            query.fields().exclude("ticketTimeList");
            query.fields().exclude("describeElectronic");
            // 推荐
            query.addCriteria(Criteria.where("isExclusive").is(1));
            List<KylinPerformanceVo> exclusiveList = mongoTemplate.find(query, KylinPerformanceVo.class, KylinPerformanceVo.class.getSimpleName());
            redisUtil.set(redisKey, exclusiveList);
            return exclusiveList;
        }
        return (List<KylinPerformanceVo>) obj;
    }

    /**
     * 获取巡演列表redis
     */
    public List<KylinPerformanceVo> getRoadList(String roadShowId) {
        String redisKey = KylinRedisConst.PERFORMANCES_ROADLIST.concat(roadShowId);
        Object obj = redisUtil.get(redisKey);
        if (obj == null) {
            List<KylinPerformanceVo> roadList = mongoTemplate.find(
                    Query.query(Criteria.where("roadShowId").is(roadShowId)),
                    KylinPerformanceVo.class,
                    KylinPerformanceVo.class.getSimpleName()
            );
            redisUtil.set(redisKey, roadList);
            return roadList;
        }
        return (List<KylinPerformanceVo>) obj;
    }

    /**
     * 演出搜索固定参数
     */
    public Query getCommonWhere() {
        // 固定条件
        Query query = new Query();
        LocalDateTime nowTime = LocalDateTime.now();
        String nowTimeStr = DateUtil.Formatter.yyyyMMddHHmmss.format(nowTime);
        query.addCriteria(Criteria.where("timeEnd").gte(nowTimeStr));
        query.addCriteria(Criteria.where("appStatus").in(6, 8, 9, 10));
        query.addCriteria(Criteria.where("isShow").is(1));
        return query;
    }

    public KylinOrderRefundsVo getOrderRefundVo(String orderRefundsId) {
        Object obj = redisUtil.get(KylinRedisConst.ORDER_REFUND + orderRefundsId);
        if (obj != null) {
            return (KylinOrderRefundsVo) obj;
        } else {
            KylinOrderRefundsVo orderRefundsVo = mongoTemplate.findOne(Query.query(Criteria.where("orderRefundsId").is(orderRefundsId)), KylinOrderRefundsVo.class, KylinOrderRefundsVo.class.getSimpleName());
            List<KylinOrderRefundEntitiesVo> kylinOrderTicketEntitiesVoList = mongoTemplate.find(Query.query(Criteria.where("orderRefundsId").is(orderRefundsId)), KylinOrderRefundEntitiesVo.class, KylinOrderRefundEntitiesVo.class.getSimpleName());
            List<KylinOrderRefundPicVo> picVos = mongoTemplate.find(Query.query(Criteria.where("orderRefundsId").is(orderRefundsId)), KylinOrderRefundPicVo.class, KylinOrderRefundPicVo.class.getSimpleName());
            orderRefundsVo.setOrderRefundEntitiesVoList(kylinOrderTicketEntitiesVoList);
            orderRefundsVo.setOrderRefundPicVos(picVos);
            redisUtil.set(KylinRedisConst.ORDER_REFUND + orderRefundsId, orderRefundsVo);
            return orderRefundsVo;
        }
    }

    public List<KylinOrderRefundsVo> getOrderRefundVoByOrderId(String orderId) {
        Object obj = redisUtil.get(KylinRedisConst.ORDER_REFUND_BY_ORDER_ID + orderId);
        if (obj != null) {
            return (List<KylinOrderRefundsVo>) obj;
        } else {
            List<KylinOrderRefundsVo> orderRefundsVoList = ObjectUtil.getKylinOrderRefundsVoArrayList();
            List<KylinOrderRefundsVo> data = mongoTemplate.find(Query.query(Criteria.where("orderTicketsId").is(orderId)), KylinOrderRefundsVo.class, KylinOrderRefundsVo.class.getSimpleName());
            for (KylinOrderRefundsVo item : data) {
                List<KylinOrderRefundEntitiesVo> kylinOrderTicketEntitiesVoList = mongoTemplate.find(Query.query(Criteria.where("orderRefundsId").is(item.getOrderRefundsId())), KylinOrderRefundEntitiesVo.class, KylinOrderRefundEntitiesVo.class.getSimpleName());
//                if(kylinOrderTicketEntitiesVoList.size()>1){
//                    continue;
//                }
                item.setOrderRefundEntitiesVoList(kylinOrderTicketEntitiesVoList);
                List<KylinOrderRefundPicVo> picVos = mongoTemplate.find(Query.query(Criteria.where("orderRefundsId").is(item.getOrderRefundsId())), KylinOrderRefundPicVo.class, KylinOrderRefundPicVo.class.getSimpleName());
                item.setOrderRefundPicVos(picVos);
                orderRefundsVoList.add(item);
            }
            redisUtil.set(KylinRedisConst.ORDER_REFUND_BY_ORDER_ID + orderId, orderRefundsVoList);
            return orderRefundsVoList;
        }
    }

    public void delOrderRefundVo(String orderRefundsId) {
        redisUtil.del(KylinRedisConst.ORDER_REFUND + orderRefundsId);
    }

    public void delOrderRefundVoByOrderId(String orderId) {
        redisUtil.del(KylinRedisConst.ORDER_REFUND_BY_ORDER_ID + orderId);
    }

    /**
     * 获取可退款票单价格
     *
     * @param orderTicketVo         订单vo数据
     * @param orderTicketEntitiesId 票单id
     * @return
     */
    public BigDecimal getCanRefundOrderEntitiesPrice(KylinOrderTicketVo orderTicketVo, List<KylinOrderRefundsVo> kylinOrderRefundsVoBaseList, String orderTicketEntitiesId) {
        // 单票实付价格
        BigDecimal singlePrice = orderTicketVo.getPriceActual().subtract(orderTicketVo.getPriceExpress()).divide(BigDecimal.valueOf(orderTicketVo.getNumber()), 2, BigDecimal.ROUND_HALF_UP);
        // 单票剩余未退款金额
        BigDecimal canRefundSinglePrice = BigDecimal.valueOf(0);
        for (KylinOrderTicketEntitiesVo item : orderTicketVo.getEntitiesVoList()) {
            if (item.getOrderTicketEntitiesId().equals(orderTicketEntitiesId)) {
                canRefundSinglePrice = singlePrice.subtract(item.getRefundPrice() == null ? BigDecimal.valueOf(0) : item.getRefundPrice());
            }
        }
        // 订单锁定金额
        BigDecimal orderLockPrice = BigDecimal.valueOf(0);
        for (KylinOrderRefundsVo refundVo : kylinOrderRefundsVoBaseList) {
            int status = refundVo.getStatus();
            if (status != KylinTableStatusConst.ORDER_REFUND_STATUS_CANCEL && status != KylinTableStatusConst.ORDER_REFUND_STATUS_REJECT && status != KylinTableStatusConst.ORDER_REFUND_STATUS_REFUNDED) { //退款流程未完成 金额锁定
                List<KylinOrderRefundEntitiesVo> refundEntitiesVos = refundVo.getOrderRefundEntitiesVoList();
                for (KylinOrderRefundEntitiesVo refundEntitiesVo : refundEntitiesVos) {
                    if (refundEntitiesVo.getOrderTicketEntitiesId().equals(orderTicketEntitiesId)) {
                        orderLockPrice = orderLockPrice.add(refundEntitiesVo.getRefundPrice());
                    }
                }
            }
        }
        // 订单可退金额
        BigDecimal refundSinglePrice = canRefundSinglePrice.subtract(orderLockPrice);
        return refundSinglePrice;
    }

    /**
     * 获取演出订单快递状态
     */
    public Integer getOrderExpressInfo(String orderId) {
        String redisKey = KylinRedisConst.ORDER_EXPRESS_INFO.concat(orderId);
        Object obj = redisUtil.get(redisKey);
        if (obj == null) {
            return 1;
        } else {
            KylinOrderExpressVo expressInfo = (KylinOrderExpressVo) obj;
            return expressInfo.getExpressStatus();
        }
    }

    /**
     * 演出订单快递路由
     */
    public LinkedList<KylinOrderExpressRouteVo> getOrderExpressRoute(String orderTicketsId) { // 获取
        String redisKey = KylinRedisConst.ORDER_ROUTE_INFO.concat(orderTicketsId);
        LinkedList<KylinOrderExpressRouteVo> list = (LinkedList<KylinOrderExpressRouteVo>) redisUtil.get(redisKey);
        if (null == list || CollectionUtil.isEmpty(list)) {
            list = new LinkedList<>();
        }
        return list;
    }

    public KylinOrderExpressVo getOrderExpressInfos(String orderId) {
        String redisKey = KylinRedisConst.ORDER_EXPRESS_INFO.concat(orderId);
        return (KylinOrderExpressVo) redisUtil.get(redisKey);
    }

    /**
     * 演出是否实名
     *
     * @param performanceId
     */
    public int getPerformanceIsTrueName(String performanceId) {
        Object obj = redisUtil.get(KylinRedisConst.PERFORMANCES_TRUE_NAME + performanceId);
        if (obj != null) {
            return (int) obj;
        } else {
            int isTrueName = getPerformanceVo(performanceId).getIsTrueName();
            redisUtil.set(KylinRedisConst.PERFORMANCES_TRUE_NAME + performanceId, isTrueName);
            return isTrueName;
        }
    }

    public void changeBuyInfo(String userId, String idCard, String performanceId, String ticketId, int buyCount) {
        String redisKeyUid;
        String redisKeyIdCard;
        String performanceIdKeyIdCard = "";
        String ticketIdKeyIdCard = "";

        int isTrueName = getPerformanceIsTrueName(performanceId);

        redisKeyUid = KylinRedisConst.USERID_BUY_INFO + userId;
        redisKeyIdCard = KylinRedisConst.IDCARD_BUY_INFO + idCard;
        String performanceIdKeyUid = redisKeyUid + ":" + KylinRedisConst.PERFORMANCE_ID + ":" + performanceId;
        String ticketIdKeyUid = redisKeyUid + ":" + KylinRedisConst.TICKET_ID + ":" + ticketId;
        if (isTrueName != 0) {
            performanceIdKeyIdCard = redisKeyIdCard + ":" + KylinRedisConst.PERFORMANCE_ID + ":" + performanceId;
            ticketIdKeyIdCard = redisKeyIdCard + ":" + KylinRedisConst.TICKET_ID + ":" + ticketId;
        }

        if (buyCount > 0) {
            redisUtil.incr(ticketIdKeyUid, buyCount);
            redisUtil.incr(performanceIdKeyUid, buyCount);
            if (isTrueName != 0) {
                redisUtil.incr(ticketIdKeyIdCard, buyCount);
                redisUtil.incr(performanceIdKeyIdCard, buyCount);
            }
        } else {
            if (isTrueName != 0) {
                redisUtil.decr(ticketIdKeyIdCard, Math.abs(buyCount));
                redisUtil.decr(performanceIdKeyIdCard, Math.abs(buyCount));
            }
            redisUtil.decr(ticketIdKeyUid, Math.abs(buyCount));
            redisUtil.decr(performanceIdKeyUid, Math.abs(buyCount));
        }
    }

    // 获取 用户维度 演出购买数量
    public int getUserPBuyCount(String userId, String performanceId) {
        try {
            return (int) redisUtil.get(KylinRedisConst.USERID_BUY_INFO + userId + ":" + KylinRedisConst.PERFORMANCE_ID + ":" + performanceId);
        } catch (Exception e) {
            return 0;
        }
    }

    // 获取 用户维度 票种购买数量
    public int getUserTBuyCount(String userId, String ticketId) {
        try {
            return (int) redisUtil.get(KylinRedisConst.USERID_BUY_INFO + userId + ":" + KylinRedisConst.TICKET_ID + ":" + ticketId);
        } catch (Exception e) {
            return 0;
        }
    }

    // 获取 证件维度 演出购买数量
    public int getIdCardPBuyCount(String idCard, String performanceId) {
        try {
            return (int) redisUtil.get(KylinRedisConst.IDCARD_BUY_INFO + idCard + ":" + KylinRedisConst.PERFORMANCE_ID + ":" + performanceId);
        } catch (Exception e) {
            return 0;
        }
    }

    // 获取 证件维度 票种购买数量
    public int getIdCardTBuyCount(String idCard, String ticketId) {
        try {
            return (int) redisUtil.get(KylinRedisConst.IDCARD_BUY_INFO + idCard + ":" + KylinRedisConst.TICKET_ID + ":" + ticketId);
        } catch (Exception e) {
            return 0;
        }
    }

    public void setRedisNoticeIsd(HashMap<String, Object> idsList) {
        String redisKeyIds = KylinRedisConst.PERFORMANCES_LIST_NOTICE_IDS;
        redisUtil.set(redisKeyIds, idsList);
    }

    public Map<String, Object> getRedisNoticeIsd() {
        String redisKeyIds = KylinRedisConst.PERFORMANCES_LIST_NOTICE_IDS;
        Object obj = redisUtil.get(redisKeyIds);
        if (obj != null) {
            return (HashMap<String, Object>) obj;
        }
        return null;
    }

    /**
     * 获取我的演出列表
     */
    public List<KylinPerformanceVo> myPerformancesList(String userId) {
        LocalDateTime nowTime = LocalDateTime.now();
        String nowTimeStr = DateUtil.Formatter.yyyyMMddHHmmss.format(nowTime);

        Query queryNew = new Query();
        queryNew.addCriteria(Criteria.where("userId").is(userId));
        queryNew.addCriteria(Criteria.where("timeEnd").gte(nowTimeStr));
        queryNew.addCriteria(Criteria.where("appStatus").in(6, 8, 9, 10));
        queryNew.addCriteria(Criteria.where("isShow").is(1));
        List<String> performanceIdList = mongoTemplate.findDistinct(queryNew, "performanceId", "KylinOrderTicketVo", KylinOrderTicketVo.class, String.class);
        log.info("myPerformancesList performanceIdList.size:{}", performanceIdList.size());

        // 固定条件
        Query query = getCommonWhere();
        // 不要查询的字段
        query.fields().exclude("details");
        query.fields().exclude("noticeImage");
        query.fields().exclude("ticketTimeList");
        query.fields().exclude("describeElectronic");
        //
        query.addCriteria(Criteria.where("performancesId").in(performanceIdList));
        query.with(Sort.by(
                Sort.Order.desc("timeStart")
        ));

        List<KylinPerformanceVo> kylinPerformanceVoList = mongoTemplate.find(query, KylinPerformanceVo.class, KylinPerformanceVo.class.getSimpleName());
        return kylinPerformanceVoList;
    }

    // 获取手续费
    public ArrayList<OrderRefundPoundage> getRefundPoundage(Integer isRefundPoundage, String performanceId) {
        ArrayList<OrderRefundPoundage> orderRefundPoundageArrayList = ObjectUtil.getOrderRefundPoundageArrayList();
        if (null != isRefundPoundage && isRefundPoundage > 0) { // 开启了演出退票有手续费
            Object obj = redisUtil.get(KylinRedisConst.ORDER_REFUND_POUNDAGE.concat(":").concat(performanceId));
            if (obj == null) {
                return orderRefundPoundageArrayList;
            } else {
                return (ArrayList<OrderRefundPoundage>) obj;
            }
        } else { // 退票不需要手续费
            return orderRefundPoundageArrayList;
        }
    }

    // 获取手续费ALL说明
    public OrderRefundPoundageAll getRefundPoundageAll(Integer isRefundPoundage, String performanceId) {
        ArrayList<OrderRefundPoundage> refundPoundage = getRefundPoundage(isRefundPoundage, performanceId);

        OrderRefundPoundageAll aNew = OrderRefundPoundageAll.getNew();
        aNew.setOrderRefundPoundageList(refundPoundage);

        Object obj = redisUtil.get(KylinRedisConst.ORDER_REFUND_POUNDAGE_EXPLAIN.concat(":").concat(performanceId));
        if (null == obj) {
            aNew.setExplain("");
        } else {
            String explain = (String) obj;
            aNew.setExplain(explain);
        }
        return aNew;
    }

    public String getExplain(String performanceId){
        Object obj = redisUtil.get(KylinRedisConst.ORDER_REFUND_POUNDAGE_EXPLAIN.concat(":").concat(performanceId));
        if (null == obj) {
            return "";
        } else {
            return (String) obj;
        }
    }

    // 获取订单券的使用情况
    public ArrayList<KylinOrderCoupons> getOrderCoupon(String orderId) {
        String redisKey = KylinRedisConst.ORDER_COUPON.concat(orderId);
        Object obj = redisUtil.get(redisKey);
        if (obj == null) {
            return ObjectUtil.getKylinOrderCouponsArrayList();
        } else {
            return (ArrayList<KylinOrderCoupons>) obj;
        }
    }

    // 快递地址
    public OrderRefundAddress getRefundAddress(String getTicketType) {
        log.info("getRefundAddress getTicketType[{}]", getTicketType);
//        if (getTicketType.equals("express")) { // 快递票
//            return null;
//        } else { // 电子票
        Object obj = redisUtil.get(KylinRedisConst.ORDER_REFUND_ADDRESS);
        if (obj == null) {
            return null;
        } else {
            return (OrderRefundAddress) obj;
        }
//        }
    }

    // 快递票退款物流信息
    public void setOrderRefundExpressInfo(String orderId, KylinOrderExpressVo kylinOrderExpressVo) {
        String redisKey = KylinRedisConst.ORDER_REFUND_EXPRESS_INFO.concat(orderId);
        redisUtil.set(redisKey, kylinOrderExpressVo);
    }

    public KylinOrderExpressVo getOrderRefundExpressInfo(String orderId) {
        String redisKey = KylinRedisConst.ORDER_REFUND_EXPRESS_INFO.concat(orderId);
        return (KylinOrderExpressVo) redisUtil.get(redisKey);
    }

    /**
     * 获取 票种快递票模板关联vo [线上]
     *
     * @param ticketId
     * @return
     */
    public KylinTicketExpressModuleVo getTEMVo(String ticketId) {
        String redisKey = KylinRedisConst.TICKET_EXPRESS_MODULE.concat(ticketId);
        Object obj = redisUtil.get(redisKey);
        if (obj != null) {
            return (KylinTicketExpressModuleVo) obj;
        } else {
            return null;
        }
    }

    public KylinIpAreaVo getKylinIpAreaVo(String ipAddress) {
//        List<KylinIpAreaVo> data = mongoTemplate.find(Query.query(Criteria.where("ipBeginLong").lte(IPUtil.ipToLong(ipAddress))
//                .and("ipEndLong").gte(IPUtil.ipToLong(ipAddress))), KylinIpAreaVo.class, KylinIpAreaVo.class.getSimpleName());
//        if(data==null || data.size()==0){
        KylinIpAreaVo data0 = KylinIpAreaVo.getNew();
        data0.setArea("未知");
        data0.setCity("未知");
        data0.setCounty("未知");
        data0.setProvince("未知");
        return data0;
//        }else{
//            return data.get(0);
//        }
    }

    /**
     * 获取已经退了的快递费
     *
     * @return
     */
    public BigDecimal getCanRefundPriceExpress(List<KylinOrderRefundsVo> kylinOrderRefundsVoBaseList) {
        BigDecimal priceExpress = BigDecimal.valueOf(0);
        if (!CollectionUtils.isEmpty(kylinOrderRefundsVoBaseList)) {
            kylinOrderRefundsVoBaseList.forEach(r -> {
                priceExpress.add(r.getPriceExpress());
            });
        }
        return priceExpress;
    }

    public boolean setRefundLock(String orderTicketEntitiesId) {
        String redisKey = KylinRedisConst.REDIS_KEY_KYLIN_REFUND_LOCK
                .concat(orderTicketEntitiesId);
        return redisUtil.lock(redisKey, 1, 60);
    }

    public void delRefundLock(String orderTicketEntitiesId) {
        String redisKey = KylinRedisConst.REDIS_KEY_KYLIN_REFUND_LOCK
                .concat(orderTicketEntitiesId);
        redisUtil.uLock(redisKey);
    }

    public List<KylinApiCameraDevicesVo> getCameraDevices(String fieldId) {
        String redisKey = KylinRedisConst.CAMERA_DEVICES_FIELD.concat(fieldId);
        Object obj = redisUtil.get(redisKey);
        if (null == obj) {
            return ObjectUtil.getKylinApiCameraDevicesVoArrayList();
        } else {
            return (List<KylinApiCameraDevicesVo>) obj;
        }
    }

    public Integer getCameraDevicePersonNum(String cameraId) {
        String redisKey = KylinRedisConst.CAMERA_DEVICE_PERSON_NUM.concat(cameraId);
        Object obj = redisUtil.get(redisKey);
        if (null == obj) {
            return 0;
        } else {
            return (int) obj;
        }
    }

    public void setSubscribe(String uid, String performancesId) {
        String redisKey = KylinRedisConst.REDIS_KEY_KYLIN_PERFORM_SUBSCRIBE
                .concat(uid)
                .concat(":")
                .concat(performancesId);
        redisUtil.set(redisKey, 1);
    }

    public Integer getSubscribe(String uid, String performancesId) {
        String redisKey = KylinRedisConst.REDIS_KEY_KYLIN_PERFORM_SUBSCRIBE
                .concat(uid)
                .concat(":")
                .concat(performancesId);
        Object obj = redisUtil.get(redisKey);
        if (obj == null) {
            return 0;
        } else {
            return (Integer) obj;
        }
    }

    //保存会员信息
    public void saveMember(String uid, Integer value, long time) {
        String redisKey = KylinRedisConst.ADAM_IS_MEMBER
                .concat(uid);
        redisUtil.set(redisKey, value, time);
    }

    public void delMember(String uid) {
        String redisKey = KylinRedisConst.ADAM_IS_MEMBER
                .concat(uid);
        redisUtil.del(redisKey);
    }

    //万青补偿id 获取
    public Integer getWqOrderId(String orderId) {
        String rdk = KylinRedisConst.REDIS_WQ_ORDER_FIX.concat(orderId);
        Object obj = redisUtil.get(rdk);
        if (obj == null) {
            return 0;
        } else {
            return 1;
        }
    }

    //万青补偿id 添加
    public void setWqOrderId(String orderId) {
        String rdk = KylinRedisConst.REDIS_WQ_ORDER_FIX.concat(orderId);
        redisUtil.set(rdk, orderId);
    }

    //万青补偿id 删除
    public void delWqOrderId(String orderId) {
        String rdk = KylinRedisConst.REDIS_WQ_ORDER_FIX.concat(orderId);
        redisUtil.del(rdk, orderId);
    }

    // 万青补偿vo覆盖
    public void setWqOrderVo(WqTempVo vo) {
        String rdk = KylinRedisConst.REDIS_WQ_ORDER_EXPRESS.concat(vo.getOrderId());
        redisUtil.set(rdk, vo);
    }

    // 万青补偿vo获取
    public WqTempVo getWqOrderVo(String orderId) {
        String rdk = KylinRedisConst.REDIS_WQ_ORDER_EXPRESS.concat(orderId);
        Object obj = redisUtil.get(rdk);
        if (obj == null) {
            WqTempVo vo = WqTempVo.getNew();
            vo.setIsTemp(getWqOrderId(orderId));
            return vo;
        } else {
            WqTempVo vo = (WqTempVo) obj;
            vo.setIsTemp(getWqOrderId(orderId));
            return vo;
        }
    }

    // 获取用户状态
    public String getUserStatus(String userId) {
        return (String) redisUtil.get(KylinRedisConst.ACTIVE_TICKET_AR_USER + userId);
    }

    //获得 ar券
    public KylinTicketActive getArTicket(String code) {
        return (KylinTicketActive) redisUtil.get(KylinRedisConst.ACTIVE_TICKET_AR_TICKET + code);
    }

    //设置 tikcet
    public void setArTicket(KylinTicketActive kylinTicketActive) {
        redisUtil.set(KylinRedisConst.ACTIVE_TICKET_AR_TICKET + kylinTicketActive.getCode(), kylinTicketActive);
    }

    //设置用户状态。
    public void setUser(String userId, String value) {
        redisUtil.set(KylinRedisConst.ACTIVE_TICKET_AR_USER + userId, value);
    }


    //根据 券id 获取 可用巡演id数组
    public List<String> getCouponRoad(String couponId) {
        String rdk = KylinRedisConst.COUPON_ROADSHOWS.concat(couponId);
        Object obj = redisUtil.get(rdk);
        if (obj == null) {
            return CollectionUtil.arrayListString();
        } else {
            return (List<String>) obj;
        }
    }

    //获得 admin配置的推荐活动
    public List<KylinRecommendActive> getRecommendActive(String id) {
        return (List<KylinRecommendActive>) redisUtil.get(KylinRedisConst.RECOMMEND_ACTIVE + id);
    }

    /**
     * @param userId  用户id
     * @param type    1新增 2修改
     * @param orderId 订单id [需要新增或者修改的订单id]
     */
    public Boolean resetOrderListVo(String userId, Integer type, String orderId, KylinOrderTicketVo dataSingle) {
        List<KylinOrderListVo> vo = new ArrayList<>();
        List<KylinOrderListVo> redisVo = new ArrayList();
        KylinOrderTicketVo data = dataSingle;
        KylinOrderListVo voItem = KylinOrderListVo.getNew().copy(data);
        List<KylinOrderListVo> redisData = (List<KylinOrderListVo>) redisUtil.get(KylinRedisConst.ORDER_LIST + userId);
        if (redisData == null) {
            return false;
        }
        if (type == 1) {
            redisVo.add(voItem);
            if (redisData.size() > 0) {
                if (redisData.get(0).getOrderTicketsId().equals(orderId)) {
                    redisData.remove(0);
                }
            }
        }

        redisVo.addAll(redisData);

        switch (type) {
            case 1:
                for (int i = 0; i < redisVo.size(); i++) {
                    if (i == 40) {
                        break;
                    }
                    if (i == 0) {
                        vo.add(voItem);
                    } else {
                        vo.add(redisVo.get(i));
                    }
                }
                if (redisVo.size() == 0) {
                    vo.add(voItem);
                }
                redisUtil.set(KylinRedisConst.ORDER_LIST + userId, vo);
                return true;
            case 2:
                for (int i = 0; i < redisVo.size(); i++) {
                    if (i == 40) {
                        break;
                    }
                    if (redisVo.get(i).getOrderTicketsId().equals(orderId)) {
                        vo.add(voItem);
                    } else {
                        vo.add(redisVo.get(i));
                    }
                }
                redisUtil.set(KylinRedisConst.ORDER_LIST + userId, vo);
                return true;
            default:
                return false;
        }
    }

    //删除 订单Ar激活码
    public void delOrderArCode(String orderId) {
        String rdk = KylinRedisConst.ORDER_AR_CODE.concat(orderId);
        redisUtil.del(rdk);
    }

    //添加 订单Ar激活码
    public void addOrderArCode(String orderId, String arCode) {
        String rdk = KylinRedisConst.ORDER_AR_CODE.concat(orderId);
        List<String> data = getOrderArCode(orderId);
        data.add(arCode);
        redisUtil.set(rdk, data);
    }

    //获取 订单Ar激活码
    public List<String> getOrderArCode(String orderId) {
        String rdk = KylinRedisConst.ORDER_AR_CODE.concat(orderId);
        Object obj = redisUtil.get(rdk);
        if (obj == null) {
            return CollectionUtil.arrayListString();
        } else {
            return (List<String>) obj;
        }
    }
    public void setPerformanceTicketsSubscribe(String uid,String performancesId,String ticketTimesId,String ticketsId,long expirationTime) {
        String redisKey=getPerformanceTicketsSubscribeKey(uid,performancesId,ticketTimesId,ticketsId);
        redisUtil.set(redisKey, 1,expirationTime);
    }

    public Integer getPerformanceTicketsSubscribe(String uid,String performancesId,String ticketTimesId,String ticketsId) {
        String redisKey=getPerformanceTicketsSubscribeKey(uid,performancesId,ticketTimesId,ticketsId);
        Object obj = redisUtil.get(redisKey);
        if (obj == null) {
            return 0;
        } else {
            return (Integer) obj;
        }
    }
    public void setPerformanceSubscribe(String uid,String performancesId,long expirationTime) {
        String redisKey=getPerformanceSubscribeKey(uid,performancesId);
        redisUtil.set(redisKey, 1,expirationTime);
    }

    public Integer getPerformanceSubscribe(String uid,String performancesId) {
        String redisKey=getPerformanceSubscribeKey(uid,performancesId);
        Object obj = redisUtil.get(redisKey);
        if (obj == null) {
            return 0;
        } else {
            return (Integer) obj;
        }
    }


    public void deleteIsSubscribe(String uid,String performancesId,String ticketTimesId,String ticketsId){
        String redisKey=getPerformanceTicketsSubscribeKey(uid,performancesId,ticketTimesId,ticketsId);
        redisUtil.del(redisKey);
    }
    private String  getPerformanceTicketsSubscribeKey(String uid,String performancesId,String ticketTimesId,String ticketsId){
        String redisKey = KylinRedisConst.REDIS_KEY_KYLIN_PERFORMANCE_SUBSCRIBE_TICKETS
                .concat(uid)
                .concat(":")
                .concat(performancesId)
                .concat(":")
                .concat(ticketTimesId)
                .concat(":")
                .concat(ticketsId);
        return redisKey;
    }

    private String  getPerformanceSubscribeKey(String uid,String performancesId){
        String redisKey = KylinRedisConst.REDIS_KEY_KYLIN_PERFORMANCE_SUBSCRIBE
                .concat(uid)
                .concat(":")
                .concat(performancesId);
        return redisKey;
    }
    public void setPerformanceSubscribeList(String uid, LinkedList<KylinPerformanceSubscribeUpushVo> list) {
        String redisKey=getPerformanceSubscribeListKey(uid);
        redisUtil.set(redisKey, list);
    }

    public LinkedList<KylinPerformanceSubscribeUpushVo> getPerformanceSubscribeList(String uid) {
        String redisKey=getPerformanceSubscribeListKey(uid);
        Object obj = redisUtil.get(redisKey);
        if (obj == null) {
            return new LinkedList<KylinPerformanceSubscribeUpushVo>();
        } else {
            return (LinkedList<KylinPerformanceSubscribeUpushVo>) obj;
        }
    }
    private String  getPerformanceSubscribeListKey(String uid){
        String redisKey = KylinRedisConst.REDIS_KEY_KYLIN_PERFORMANCE_SUBSCRIBE_LIST
                .concat(uid);
        return redisKey;
    }

    public void deleteIsSubscribeRead(String uid,String performancesId,String ticketTimesId){
        String redisKey=getPerformanceSubscribeReadKey(uid,performancesId,ticketTimesId);
        redisUtil.del(redisKey);
    }
    public void setPerformanceSubscribeRead(String uid,String performancesId,String ticketTimesId) {
        String redisKey=getPerformanceSubscribeReadKey(uid,performancesId,ticketTimesId);
        redisUtil.set(redisKey, 1);
    }

    public Integer getPerformanceSubscribeRead(String uid,String performancesId,String ticketTimesId) {
        String redisKey=getPerformanceSubscribeReadKey(uid,performancesId,ticketTimesId);
        Object obj = redisUtil.get(redisKey);
        if (obj == null) {
            return 0;
        } else {
            return (Integer) obj;
        }
    }

    public void deletePerformanceSubscribeRead(String uid,String performancesId,String ticketTimesId) {
        String redisKey=getPerformanceSubscribeReadKey(uid,performancesId,ticketTimesId);
        redisUtil.del(redisKey);
    }
    private String  getPerformanceSubscribeReadKey(String uid,String performancesId,String ticketTimesId){
        String redisKey = KylinRedisConst.REDIS_KEY_KYLIN_PERFORMANCE_SUBSCRIBE_READ
                .concat(uid)
                .concat(":")
                .concat(performancesId)
                .concat(":")
                .concat(ticketTimesId);
        return redisKey;
    }
    //添加激活码使用量
    public void incrArCode() {
        redisUtil.incr(KylinRedisConst.ACTIVE_USE_AR_COUNT, 1);
    }

    public int incrOrderRefundCode(String orderCode) {
        return (int) redisUtil.incr(KylinRedisConst.ORDER_REFUND_TEMP + orderCode,1);
    }

    //判断是否是会员
    public Integer isMemberByUser(String uid) {
        Integer isMember=0;
        AdamUserMemberVo userMemberVo = getUserMemberVoByUid(uid);
        if (null != userMemberVo && userMemberVo.isActive()){
            isMember=1;
        }
        return isMember;
    }
    //获取用户信息
    public AdamUserMemberVo getUserMemberVoByUid(String uid) {
        String rk = AdamRedisConst.INFO_USER_MEMBER.concat(uid);
        long s = System.currentTimeMillis();
        AdamUserMemberVo vo = (AdamUserMemberVo) redisUtil.get(rk);

        if (null != vo) {
            vo.setState(vo.getState() == 1 ? (vo.getExpiryAt().isAfter(LocalDateTime.now()) ? 1 : 2) : vo.getState());
        }
        log.debug("#RDM耗时:{}ms", System.currentTimeMillis() - s);
        return vo;
    }

    public int getPerformanceInvoiceReminder(String performanceId) {
        String redisKey = KylinRedisConst.PERFORMANCES_INVOICE_REMINDER + performanceId;
        Object obj = redisUtil.get(redisKey);
        if (obj == null) {
            return 0;
        }else {
            return (int) obj;
        }
    }

    public KylinTicketPartnerVo getKylinTicketPartnerVoByTicketId(String ticketId) {
        return mongoTemplate.findOne(Query.query(Criteria.where("ticketsId").is(ticketId)),
                KylinTicketPartnerVo.class,
                KylinTicketPartnerVo.class.getSimpleName());
    }
}
