package com.liquidnet.service.platform.utils;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.liquidnet.common.cache.redis.util.RedisDataSourceUtil;
import com.liquidnet.commons.lang.constant.LnsEnum;
import com.liquidnet.commons.lang.constant.UpushTargetType;
import com.liquidnet.commons.lang.util.*;
import com.liquidnet.commons.lang.util.upush.AndroidNotification;
import com.liquidnet.commons.lang.util.upush.PushClient;
import com.liquidnet.commons.lang.util.upush.android.AndroidBroadcast;
import com.liquidnet.commons.lang.util.upush.android.AndroidUnicast;
import com.liquidnet.commons.lang.util.upush.ios.IOSBroadcast;
import com.liquidnet.commons.lang.util.upush.ios.IOSUnicast;
import com.liquidnet.service.kylin.constant.KylinRedisConst;
import com.liquidnet.service.kylin.dao.KylinPerformancesSubscribeDao;
import com.liquidnet.service.kylin.dto.param.PerformancePartnerVo;
import com.liquidnet.service.kylin.dto.vo.KylinPerformanceSubscribeUpushVo;
import com.liquidnet.service.kylin.dto.vo.middle.KylinTicketTimesVo;
import com.liquidnet.service.kylin.dto.vo.middle.KylinTicketVo;
import com.liquidnet.service.kylin.dto.vo.mongo.KylinPerformanceVo;
import com.liquidnet.service.kylin.dto.vo.partner.KylinPerformanceMisVo;
import com.liquidnet.service.kylin.dto.vo.partner.KylinTicketPartnerVo;
import com.liquidnet.service.kylin.dto.vo.partner.KylinTicketTimesPartnerVo;
import com.liquidnet.service.kylin.dto.vo.partner.TicketTimesTicketCreatePartnerVo;
import com.liquidnet.service.kylin.entity.*;
import com.liquidnet.service.kylin.mapper.*;
import com.liquidnet.service.platform.service.impl.partner.KylinTicketTimesPartnerServiceImpl;
import com.liquidnet.service.platform.service.impl.partner.KylinTicketsPartnerServiceImpl;
import com.mongodb.BasicDBObject;
import com.mongodb.client.model.FindOneAndUpdateOptions;
import com.mongodb.client.model.ReturnDocument;
import lombok.extern.slf4j.Slf4j;
import org.bson.Document;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.convert.MongoConverter;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

@Component
@Slf4j
public class PerformanceVoTask {

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private MongoConverter mongoConverter;

    @Autowired
    private DataUtils dataUtils;
    @Autowired
    private RedisDataSourceUtil redisDataSourceUtil;
    @Autowired
    private MongoVoUtils mongoVoUtils;

    @Autowired
    private KylinPerformancesMapper performancesMapper;

    @Autowired
    private KylinPerformanceStatusMapper performanceStatusMapper;

    @Autowired
    private KylinPerformanceRelationsMapper performanceRelationsMapper;

    @Autowired
    private KylinTicketTimesPartnerServiceImpl ticketTimesPartnerService;

    @Autowired
    private KylinTicketsMapper ticketsMapper;

    @Autowired
    private KylinTicketStatusMapper ticketStatusMapper;

    @Autowired
    private KylinTicketRelationsMapper ticketRelationsMapper;

    @Autowired
    private KylinTicketTimesMapper ticketTimesMapper;

    @Autowired
    private KylinTicketTimeRelationMapper ticketTimeRelationMapper;

    @Autowired
    private KylinTicketsPartnerServiceImpl ticketsPartnerService;


    @Value("${liquidnet.umeng.ios.appkey}")
    private String iosAppkey;
    @Value("${liquidnet.umeng.ios.appMasterSecret}")
    private String iosAppMasterSecret;
    @Value("${liquidnet.umeng.android.appkey}")
    private String androidAppkey;
    @Value("${liquidnet.umeng.android.appMasterSecret}")
    private String androidAppMasterSecret;
    @Autowired
    Environment environment;
    private PushClient client = new PushClient();

    /**
     * 根据票状态判断 演出状态 票状态
     *
     * @param performanceSingleId
     */
    public void performanceVoStatus(String performanceSingleId) {
        LocalDateTime timeNow = LocalDateTime.now();
        List<String> performanceIdList = new ArrayList<>();

        if (performanceSingleId == null) {
            List<KylinPerformanceStatus> list = performanceStatusMapper.selectList(new UpdateWrapper<KylinPerformanceStatus>().in("status", 3, 4, 6, 7, 8, 9, 10));
            for (KylinPerformanceStatus item : list) {
                performanceIdList.add(item.getPerformanceId());
            }
        } else {
            performanceIdList.add(performanceSingleId);
        }

        for (String performancesId : performanceIdList) {
            KylinPerformanceVo vo = mongoVoUtils.combinePerformanceVoData(performancesId);
            //场次
            List<KylinTicketTimesVo> timesData = vo.getTicketTimeList();
            if (timesData.size() == 0) {
                continue;
            }
            int ticketCount = 0;            //总循环次数
            int status9Count = 0;            //未开售次数
            int status8Count = 0;            //售罄次数
            int status7Count = 0;            //下架次数
            int status10Count = 0;            //已结束次数

            //演出数据
            int appStatus = 6;
            for (KylinTicketTimesVo kylinTicketTimesVoItem : timesData) {
                //票
                List<KylinTicketVo> kylinTicketVoList = kylinTicketTimesVoItem.getTicketList();
                ticketCount += kylinTicketVoList.size();
                for (KylinTicketVo kylinTicketVoItem : kylinTicketVoList) {
                    //时间判断
                    LocalDateTime timeStart = DateUtil.Formatter.yyyyMMddHHmmss.parse(kylinTicketVoItem.getMemberTimeStart());
                    LocalDateTime timeEnd = DateUtil.Formatter.yyyyMMddHHmmss.parse(kylinTicketVoItem.getTimeEnd());
                    int surplusGeneral = -1;
                    int status = 0;
                    if (kylinTicketVoItem.getStatus() == 7) {
                        status = 7;
                        status7Count += 1;
                    } else if (timeStart.isAfter(timeNow)) {
                        //未开始
                        status = 9;
                        status9Count += 1;
                    } else if (timeEnd.isBefore(timeNow)) {
                        //结束
                        status = 10;
                        status10Count += 1;
                    } else {
                        //库存判断
                        surplusGeneral = dataUtils.getSurplusGeneral(kylinTicketVoItem.getTicketsId());
                        if (surplusGeneral > 0) {
                            status = 6;
                        } else {
                            status = 8;
                            status8Count += 1;
                        }
                    }

                    //修改票状态
                    KylinTicketStatus changeStatus = new KylinTicketStatus();
                    changeStatus.setStatus(status);
                    if (surplusGeneral != -1) {
                        changeStatus.setSurplusGeneral(surplusGeneral);
                    }
                    ticketStatusMapper.update(changeStatus, new UpdateWrapper<KylinTicketStatus>().eq("ticket_id", kylinTicketVoItem.getTicketsId()));
                    kylinTicketVoItem.setStatus(status);

                    //演出状态
                    if (status == 6) {//单一票 可购买 则为可购买
                        appStatus = 6;
                    } else if ((ticketCount-status7Count) == status10Count) {//全票结束 为结束
                        appStatus = 10;
                    } else if ((ticketCount-status7Count) == status8Count) {//全票售罄为售罄
                        appStatus = 8;
                    } else if ((ticketCount-status7Count) == status9Count) {//全票未开始 为未开始
                        appStatus = 9;
                    }
                }
            }
            if (vo.getAppStatus() <= 4) {
                appStatus = vo.getAppStatus();
            }
            if (vo.getAppStatus() == 7) {
                appStatus = 7;
            }
            //修改演出状态
            KylinPerformanceStatus changeStatus = new KylinPerformanceStatus();
            changeStatus.setStatus(appStatus);
            performanceStatusMapper.update(changeStatus, new UpdateWrapper<KylinPerformanceStatus>().eq("performance_id", performancesId));
            vo.setAppStatus(appStatus);
            dataUtils.updatePerformanceMongo(performancesId, vo);
        }
    }


    /**
     * 生成 PerformanceCreatePartnerVo(用于审核第一次提交数据)
     *
     * @param performancesId
     * @return
     */
    public KylinPerformanceMisVo getPerformanceMisVo(String performancesId) {
        try {
            PerformancePartnerVo performanceData = mongoTemplate.findOne(Query.query(Criteria.where("performancesId").is(performancesId)), PerformancePartnerVo.class, PerformancePartnerVo.class.getSimpleName());
            List<KylinTicketTimesPartnerVo> kylinTicketTimesPartnerVos = ticketTimesPartnerService.getTimesMongoList(performancesId);
            List<TicketTimesTicketCreatePartnerVo> ticketTimesTicketCreatePartnerVoList = new ArrayList<TicketTimesTicketCreatePartnerVo>();

            ArrayList<BigDecimal> floatList = new ArrayList<>();
            ArrayList<String> StringList = new ArrayList<>();

            for (KylinTicketTimesPartnerVo ticketTimes : kylinTicketTimesPartnerVos) {
                TicketTimesTicketCreatePartnerVo ticketTimesTicketCreatePartnerVo = new TicketTimesTicketCreatePartnerVo();
                BeanUtils.copyProperties(ticketTimes, ticketTimesTicketCreatePartnerVo);
                List<KylinTicketPartnerVo> kylinTicketPartnerVos = ticketsPartnerService.getTicketMongoList(ticketTimes.getTicketTimesId());
                ticketTimesTicketCreatePartnerVo.setTicket(kylinTicketPartnerVos);
                ticketTimesTicketCreatePartnerVoList.add(ticketTimesTicketCreatePartnerVo);
                for (KylinTicketPartnerVo kylinTicketPartnerVoItem : kylinTicketPartnerVos) {
                    floatList.add(kylinTicketPartnerVoItem.getPrice());
                    StringList.add(kylinTicketPartnerVoItem.getTimeEnd());
                }
            }
            KylinPerformanceMisVo kylinPerformanceMisVo = new KylinPerformanceMisVo();
            BeanUtils.copyProperties(performanceData, kylinPerformanceMisVo);

            floatList.sort(Comparator.naturalOrder());
            StringList.sort(Comparator.naturalOrder());

            kylinPerformanceMisVo.setDetails(performanceData.getDetails());
            kylinPerformanceMisVo.setPrice(floatList.get(0) + "起");
            kylinPerformanceMisVo.setStopSellTime(StringList.get(0));
            kylinPerformanceMisVo.setTicketTimes(ticketTimesTicketCreatePartnerVoList);

            kylinPerformanceMisVo.setIsDistribution(0);
            kylinPerformanceMisVo.setSyncAgent(0);
            kylinPerformanceMisVo.setAuditStatus(0);

            return kylinPerformanceMisVo;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 插入数据库
     *
     * @param performancesId
     * @param map
     * @param kylinPerformanceMisVo
     * @param updatedAt
     */
    public void createPerformanceMySql(String performancesId, HashMap<String, Object> map, KylinPerformanceMisVo kylinPerformanceMisVo, LocalDateTime updatedAt) {
        try {
            //创建演出
            KylinPerformances performances = new KylinPerformances();
            BeanUtils.copyProperties(kylinPerformanceMisVo, performances);
            KylinPerformanceStatus performanceStatus = new KylinPerformanceStatus();
            BeanUtils.copyProperties(kylinPerformanceMisVo, performanceStatus);
            KylinPerformanceRelations performanceRelations = new KylinPerformanceRelations();
            BeanUtils.copyProperties(kylinPerformanceMisVo, performanceRelations);

            performances.setCreatedAt(DateUtil.asLocalDateTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(kylinPerformanceMisVo.getCreatedAt())));
            performances.setTimeStart(DateUtil.asLocalDateTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(kylinPerformanceMisVo.getTimeStart())));
            performances.setTimeEnd(DateUtil.asLocalDateTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(kylinPerformanceMisVo.getTimeEnd())));
            performances.setCityName((String) redisDataSourceUtil.getRedisKylinUtil().getDB15RedisHGet(KylinRedisConst.FIELDS + ":" + performanceRelations.getFieldId(), "city_name"));
            performances.setCityId(Integer.parseInt((String) redisDataSourceUtil.getRedisKylinUtil().getDB15RedisHGet(KylinRedisConst.FIELDS + ":" + performanceRelations.getFieldId(), "city_id")));
            performances.setUpdatedAt(updatedAt);

            performanceStatus.setPerformanceId(performances.getPerformancesId());
            performanceStatus.setPerformanceStatusId(IDGenerator.nextSnowId().toString());
            performanceStatus.setCreatedAt(performances.getCreatedAt());
            performanceStatus.setAuditStatus(0);
            performanceStatus.setUpdatedAt(updatedAt);

            performanceStatus.setLimitCountMember(1);

            performanceRelations.setPerformanceId(performances.getPerformancesId());
            performanceRelations.setPerformanceRelationsId(IDGenerator.nextSnowId().toString());
            performanceRelations.setCreatedAt(performances.getCreatedAt());
            performanceRelations.setUpdatedAt(updatedAt);

            performancesMapper.delete(new UpdateWrapper<KylinPerformances>().eq("performances_id", performances.getPerformancesId()));
            performancesMapper.insert(performances);
            performanceStatusMapper.delete(new UpdateWrapper<KylinPerformanceStatus>().eq("performance_id", performanceStatus.getPerformanceId()));
            performanceStatusMapper.insert(performanceStatus);
            performanceRelationsMapper.delete(new UpdateWrapper<KylinPerformanceRelations>().eq("performance_id", performanceRelations.getPerformanceId()));
            performanceRelationsMapper.insert(performanceRelations);


            //场次数据
            List<KylinTicketTimesPartnerVo> kylinTicketTimesPartnerVos = ticketTimesPartnerService.getTimesMongoList(performancesId);
            for (KylinTicketTimesPartnerVo ticketTimeItem : kylinTicketTimesPartnerVos) {
                //创建场次
                KylinTicketTimes ticketTimes = new KylinTicketTimes();
                BeanUtils.copyProperties(ticketTimeItem, ticketTimes);
                KylinTicketTimeRelation ticketTimeRelation = new KylinTicketTimeRelation();
                BeanUtils.copyProperties(ticketTimeItem, ticketTimeRelation);

                ticketTimes.setUseStart(DateUtil.asLocalDateTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(ticketTimeItem.getUseStart())));
                ticketTimes.setUseEnd(DateUtil.asLocalDateTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(ticketTimeItem.getUseEnd())));
                ticketTimes.setCreatedAt(DateUtil.asLocalDateTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(ticketTimeItem.getCreatedAt())));
                ticketTimes.setUpdatedAt(updatedAt);

                ticketTimeRelation.setPerformanceId(performancesId);
                ticketTimeRelation.setTicketTimeRelationId(IDGenerator.nextSnowId().toString());
                ticketTimeRelation.setTimesId(ticketTimes.getTicketTimesId());
                ticketTimeRelation.setCreatedAt(ticketTimes.getCreatedAt());
                ticketTimeRelation.setUpdatedAt(updatedAt);

                ticketTimesMapper.delete(new UpdateWrapper<KylinTicketTimes>().eq("ticket_times_id", ticketTimes.getTicketTimesId()));
                ticketTimesMapper.insert(ticketTimes);
                ticketTimeRelationMapper.delete(new UpdateWrapper<KylinTicketTimeRelation>().eq("times_id", ticketTimeRelation.getTimesId()));
                ticketTimeRelationMapper.insert(ticketTimeRelation);

                //修改票
                for (KylinTicketPartnerVo ticketItem : ticketsPartnerService.getTicketMongoList(ticketTimeItem.getTicketTimesId())) {
                    BasicDBObject objectTicketVo = new BasicDBObject("$set", mongoConverter.convertToMongoType(map));
                    Document docTicket = mongoTemplate.getCollection(KylinTicketPartnerVo.class.getSimpleName()).findOneAndUpdate(
                            Query.query(Criteria.where("ticketsId").is(ticketItem.getTicketsId())).getQueryObject(),
                            objectTicketVo,
                            new FindOneAndUpdateOptions().returnDocument(ReturnDocument.AFTER)
                    );
                    KylinTicketPartnerVo kylinTicketPartnerVo = JsonUtils.fromJson(docTicket.toJson(), KylinTicketPartnerVo.class);

                    //创建演出
                    KylinTickets tickets = new KylinTickets();
                    BeanUtils.copyProperties(kylinTicketPartnerVo, tickets);
                    KylinTicketStatus ticketStatus = new KylinTicketStatus();
                    BeanUtils.copyProperties(kylinTicketPartnerVo, ticketStatus);
                    KylinTicketRelations ticketRelations = new KylinTicketRelations();
                    BeanUtils.copyProperties(kylinTicketPartnerVo, ticketRelations);

                    tickets.setPayCountdownMinute(kylinPerformanceMisVo.getPayCountdownMinute());
                    tickets.setPriceExpress(new BigDecimal("0.00"));
                    tickets.setPriceDiscountMember(new BigDecimal("0.00"));
                    tickets.setPriceDiscount(new BigDecimal("0.00"));
                    tickets.setTimeStart(DateUtil.asLocalDateTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(ticketItem.getTimeStart())));
                    tickets.setTimeEnd(DateUtil.asLocalDateTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(ticketItem.getTimeEnd())));
                    if (ticketItem.getIsExpress() == 1) {
                        tickets.setTimeEndExpress(DateUtil.asLocalDateTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(ticketItem.getTimeEndExpress())));
                        tickets.setDescribeExpress(ticketItem.getDescribeExpress());
                    }
//                    else{
//                        tickets.setTimeEndExpress(DateUtil.asLocalDateTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2030-01-01 12:00:00")));
//                    }
                    if (ticketItem.getIsElectronic() == 1) {
                        tickets.setDescribeElectronic(ticketItem.getDescribeElectronic());
                    }
                    tickets.setUseStart(DateUtil.asLocalDateTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(ticketTimeItem.getUseStart())));
                    tickets.setUseEnd(DateUtil.asLocalDateTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(ticketTimeItem.getUseEnd())));
                    tickets.setSaleRemindMinute(60);
                    tickets.setCreatedAt(DateUtil.asLocalDateTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(ticketItem.getCreatedAt())));
                    tickets.setUpdatedAt(updatedAt);

                    ticketStatus.setTicketStatusId(IDGenerator.nextSnowId().toString());
                    ticketStatus.setTicketId(tickets.getTicketsId());
                    ticketStatus.setIsMember(1);
                    ticketStatus.setIsExclusive(0);
                    ticketStatus.setIsTrueName(performanceStatus.getIsTrueName());
                    ticketStatus.setMemberLimitCount(1);
                    ticketStatus.setStatusExchange(7);
                    if (ticketItem.getIsShowCode() == 1) {
                        ticketStatus.setQrCodeShowTime(DateUtil.asLocalDateTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(ticketItem.getQrCodeShowTime())));
                    }

                    ticketRelations.setCreatedAt(tickets.getCreatedAt());
                    ticketRelations.setUpdatedAt(updatedAt);

                    ticketRelations.setTicketRelationsId(IDGenerator.nextSnowId().toString());
                    ticketRelations.setTicketId(tickets.getTicketsId());
                    ticketRelations.setCreatedAt(tickets.getCreatedAt());
                    ticketRelations.setUpdatedAt(updatedAt);

                    ticketsMapper.delete(new UpdateWrapper<KylinTickets>().eq("tickets_id", tickets.getTicketsId()));
                    ticketsMapper.insert(tickets);
                    ticketStatusMapper.delete(new UpdateWrapper<KylinTicketStatus>().eq("ticket_id", ticketStatus.getTicketId()));
                    ticketStatusMapper.insert(ticketStatus);
                    ticketRelationsMapper.delete(new UpdateWrapper<KylinTicketRelations>().eq("ticket_id", ticketRelations.getTicketId()));
                    ticketRelationsMapper.insert(ticketRelations);

                    dataUtils.setSurplusExchange(tickets.getTicketsId(), ticketStatus.getSurplusExchange());
                    dataUtils.setSurplusGeneral(tickets.getTicketsId(), ticketStatus.getSurplusGeneral());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    // 判断是否需要审核
    public boolean judgeIsAudit(String performanceId) {
        KylinPerformanceMisVo misVo = getPerformanceMisVo(performanceId);
        KylinPerformanceVo mongoVo = mongoVoUtils.combinePerformanceVoData(performanceId);
        if (!misVo.getTitle().equals(mongoVo.getTitle())) {
            log.info("performanceId = " + performanceId + " NEED CHANGE TITLE");
            return true;
        }
        if (!misVo.getImgPoster().equals(mongoVo.getImgPoster())) {
            log.info("performanceId = " + performanceId + " NEED CHANGE IMGPOSTER");
            return true;
        } else if (!misVo.getType().equals(mongoVo.getType())) {
            log.info("performanceId = " + performanceId + " NEED CHANGE TYPE");
            return true;
        } else if (!misVo.getTimeStart().equals(mongoVo.getTimeStart())) {
            log.info("performanceId = " + performanceId + " NEED CHANGE TIMESTART");
            return true;
        } else if (!misVo.getTimeEnd().equals(mongoVo.getTimeEnd())) {
            log.info("performanceId = " + performanceId + " NEED CHANGE TIMEEND");
            return true;
        } else if (!misVo.getFieldId().equals(mongoVo.getFieldId())) {
            log.info("performanceId = " + performanceId + " NEED CHANGE FIELDID");
            return true;
        } else if (!misVo.getNotice().equals(mongoVo.getNotice())) {
            log.info("performanceId = " + performanceId + " NEED CHANGE NOTICE");
            return true;
        } else if (!misVo.getDetails().replace("'", "").equals(mongoVo.getDetails().replace("'", ""))) {
            log.info("performanceId = " + performanceId + " NEED CHANGE DETAILS");
            return true;
        } else if (!misVo.getApprovalUrl().equals(mongoVo.getApprovalUrl())) {
            log.info("performanceId = " + performanceId + " NEED CHANGE APPROVALURL");
            return true;
        } else if (!misVo.getPayCountdownMinute().equals(mongoVo.getPayCountdownMinute())) {
            log.info("performanceId = " + performanceId + " NEED CHANGE PAYCOUTDOWN");
            return true;
        }

        boolean exists = mongoTemplate.exists(Query.query(Criteria.where("status").is(-1).and("performancesId").is(performanceId)),
                KylinTicketTimesPartnerVo.class, KylinTicketTimesPartnerVo.class.getSimpleName());
        if (exists) {
            log.info("performanceId = " + performanceId + " NEED CHANGE NEW TIMES");
            return true;
        }

        for (int i = 0; i < misVo.getTicketTimes().size(); i++) {
            TicketTimesTicketCreatePartnerVo times = misVo.getTicketTimes().get(i);
            KylinTicketTimesVo timesVo = mongoVo.getTicketTimeList().get(i);

            if (!times.getUseStart().equals(timesVo.getUseStart())) {
                log.info("performanceId = " + performanceId + " NEED CHANGE TIMES USE_START");
                return true;
            }

            if (!times.getUseEnd().equals(timesVo.getUseEnd())) {
                log.info("performanceId = " + performanceId + " NEED CHANGE TIMES USE_END");
                return true;
            }

            boolean exists2 = mongoTemplate.exists(Query.query(Criteria.where("status").is(-2).and("timesId").is(times.getTicketTimesId())), KylinTicketPartnerVo.class, KylinTicketPartnerVo.class.getSimpleName());
            if (exists2) {
                log.info("performanceId = " + performanceId + " NEED CHANGE NEW TICKET");
                return true;
            }
            for (KylinTicketPartnerVo ticketPartnerVo : times.getTicket()) {
                for (KylinTicketVo ticketVo : timesVo.getTicketList()) {
                    if (ticketVo.getTicketsId().equals(ticketPartnerVo.getTicketsId())) {
                        if (!ticketVo.getTitle().equals(ticketPartnerVo.getTitle())) {
                            log.info("performanceId = " + performanceId + " ticketId = " + ticketVo.getTicketsId() + " NEED CHANGE TICKET TITLE");
                            return true;
                        }
//                        else if (!ticketVo.getQrCodeShowTime().equals(ticketPartnerVo.getQrCodeShowTime())) {
//                            log.debug("NEED CHANGE TICKET QRCODESHOWTIME");
//                            return true;
//                    }
                        else if (!ticketVo.getDescribeElectronic().equals(ticketPartnerVo.getDescribeElectronic())) {
                            log.info("performanceId = " + performanceId + " ticketId = " + ticketVo.getTicketsId() + " NEED CHANGE TICKET DESCRIBEELECTRONIC");
                            return true;
                        } else if (!ticketVo.getDescribeExpress().equals(ticketPartnerVo.getDescribeExpress())) {
                            log.info("performanceId = " + performanceId + " ticketId = " + ticketVo.getTicketsId() + " NEED CHANGE TICKET DESCRIBEELEXPRESS");
                            return true;
                        }
                        if (!ticketVo.getDescribes().equals(ticketPartnerVo.getDescribes())) {
                            log.info("performanceId = " + performanceId + " NEED CHANGE TICKET DESCRIBES");
                            return true;
                        }
                        break;
                    }
                }
            }
        }
        return false;
    }

    public void performanceSubscribePush()throws Exception{
        //异步处理ios
        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            try {
                //IOS开票提醒推送
                IOSPush();
            } catch (Exception e) {
                e.printStackTrace();
            }
            log.info("IOS开票提醒推送异步任务执行完毕");
        });
        //Android开票提醒推送
        log.info("Android开票提醒推送主线程继续执行");
        AndroidPush();
        future.get(); // 等待异步任务完成
        log.info("开票提醒推送所有任务执行完毕");
    }
    public void AndroidPush(){
        List<KylinPerformancesSubscribeDao> kylinPerformancesSubscribeDaoAndroidList = performancesMapper.performanceSubscribePush(0, "Android", 0);
        if(!CollectionUtil.isEmpty(kylinPerformancesSubscribeDaoAndroidList)){
            long startTime = System.currentTimeMillis(); // 获取开始时间
            log.info("友盟Android开票提醒推送开始startTime===={}",startTime);
            for (KylinPerformancesSubscribeDao kylinPerformancesSubscribeDao : kylinPerformancesSubscribeDaoAndroidList) {
                //友盟推送
                sendAndroidUnicast(kylinPerformancesSubscribeDao.getDeviceTokens(),kylinPerformancesSubscribeDao.getPushTitle(),6,kylinPerformancesSubscribeDao.getJumpValue());
            }
            long endTime = System.currentTimeMillis(); // 获取结束时间
            log.info("友盟Android开票提醒推送结束方法执行时间秒===={}",(startTime-endTime)/1000);
            List<Integer> IOSIds = kylinPerformancesSubscribeDaoAndroidList.stream().map(KylinPerformancesSubscribeDao::getMid).collect(Collectors.toList());
            //批量修改变成已推送
            performancesMapper.updatePerformanceSubscribePushById(IOSIds);
        }
    }
    public void IOSPush(){
        List<KylinPerformancesSubscribeDao> kylinPerformancesSubscribeDaoIOSList = performancesMapper.performanceSubscribePush(0, "IOS", 0);
        if(!CollectionUtil.isEmpty(kylinPerformancesSubscribeDaoIOSList)){
            long startTime = System.currentTimeMillis(); // 获取开始时间
            log.info("友盟IOS开票提醒推送开始startTime===={}",startTime);
            for (KylinPerformancesSubscribeDao kylinPerformancesSubscribeDao : kylinPerformancesSubscribeDaoIOSList) {
                //友盟推送
                sendIOSUnicast(kylinPerformancesSubscribeDao.getDeviceTokens(),kylinPerformancesSubscribeDao.getPushTitle(),6,kylinPerformancesSubscribeDao.getJumpValue());
            }
            long endTime = System.currentTimeMillis(); // 获取结束时间
            log.info("友盟IOS开票提醒推送结束方法执行时间秒===={}",(startTime-endTime)/1000);
            List<Integer> IOSIds = kylinPerformancesSubscribeDaoIOSList.stream().map(KylinPerformancesSubscribeDao::getMid).collect(Collectors.toList());
            //批量修改变成已推送
            performancesMapper.updatePerformanceSubscribePushById(IOSIds);
        }
    }
    public void sendAndroidUnicast(String deviceTokens,String pushTitle,Integer jumpType,String jumpValue) {
        try {
            AndroidUnicast unicast = new AndroidUnicast(androidAppkey, androidAppMasterSecret);
            unicast.setBadge(1);
            unicast.setTicker("【正在现场】开票提醒");
            unicast.setTitle("【正在现场】开票提醒");
            unicast.setText(pushTitle+"，10分钟后即将开售，请点击进入详情页购买。");
            String custom = UpushTargetType.getTypeAction(jumpType);
            unicast.goCustomAfterOpen(custom);
            unicast.setDisplayType(AndroidNotification.DisplayType.NOTIFICATION);
            if (!LnsEnum.ENV.prod.name().equals(environment.getProperty(CurrentUtil.CK_ENV_ACTIVE))) {
                unicast.setTestMode();
            } else {
                unicast.setProductionMode();
            }

            // Set customized fields
            unicast.setExtraField("type", jumpType.toString());
            unicast.setExtraField("id", jumpValue);
            unicast.setExtraField("url", jumpValue);
            //表示指定的单个设备
            unicast.setDeviceToken(deviceTokens);
            //配置华为离线通知
            unicast.setPredefinedKeyValue("channel_activity","com.modernsky.istv.ui.activity.MfrMessageActivity");

            log.info("友盟消息推送开始Android============deviceTokens========={},pushTitle========={}",deviceTokens,pushTitle);
            String sendRes = client.send(unicast);
            log.info("友盟消息推送成功AndroidReturn============sendRes===={}",sendRes);
        } catch (Exception e) {
            log.info("友盟消息推送失败Android============deviceTokens={},pushTitle={},e={}",deviceTokens,pushTitle,e);
        }
    }

    public void sendIOSUnicast(String deviceTokens,String pushTitle,Integer jumpType,String jumpValue) {
        AdminUpush updatePush = new AdminUpush();
        try {
            IOSUnicast unicast = new IOSUnicast(iosAppkey, iosAppMasterSecret);
            //alert的值设置为字典
            unicast.setAlert("【正在现场】开票提醒", "", pushTitle+"，10分钟后即将开售，请点击进入详情页购买。");
            unicast.setBadge(1);
            unicast.setSound("default");
            if (!LnsEnum.ENV.prod.name().equals(environment.getProperty(CurrentUtil.CK_ENV_ACTIVE))) {
                unicast.setTestMode();
            } else {
                unicast.setProductionMode();
            }
            // Set customized fields
            unicast.setCustomizedField("type", jumpType.toString());
            unicast.setCustomizedField("id", jumpValue);
            unicast.setCustomizedField("url", jumpValue);
            //表示指定的单个设备
            unicast.setDeviceToken(deviceTokens);
            log.info("友盟消息推送开始IOS============deviceTokens========={},pushTitle========={}",deviceTokens,pushTitle);
            String sendRes = client.send(unicast);
            log.info("友盟消息推送成功IOS============sendRes===={}",sendRes);
        } catch (Exception e) {
            log.info("友盟消息推送失败IOS============deviceTokens={},pushTitle={},e={}",deviceTokens,pushTitle,e);;
        }
    }
}
