package com.liquidnet.client.admin.zhengzai.kylin.utils;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fasterxml.jackson.core.type.TypeReference;
import com.liquidnet.common.cache.redis.util.RedisUtil;
import com.liquidnet.commons.lang.util.DateUtil;
import com.liquidnet.commons.lang.util.IDGenerator;
import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.service.kylin.constant.KylinRedisConst;
import com.liquidnet.service.kylin.dto.param.PerformancePartnerVo;
import com.liquidnet.service.kylin.dto.vo.middle.KylinBuyNoticeVo;
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.mongodb.BasicDBObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
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.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;

@Component
@Slf4j
public class PerformanceVoUtils {

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private MongoConverter mongoConverter;

    @Autowired
    private DataUtils dataUtils;
    @Autowired
    private MongoVoUtils mongoVoUtils;
    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private KylinPerformancesMapper performancesMapper;

    @Autowired
    private KylinPerformanceStatusMapper performanceStatusMapper;

    @Autowired
    private KylinPerformanceRelationsMapper performanceRelationsMapper;

    @Autowired
    private KylinTicketsMapper ticketsMapper;

    @Autowired
    private KylinTicketStatusMapper ticketStatusMapper;

    @Autowired
    private KylinTicketRelationsMapper ticketRelationsMapper;

    @Autowired
    private KylinTicketTimesMapper ticketTimesMapper;

    @Autowired
    private KylinTicketTimeRelationMapper ticketTimeRelationMapper;


    /**
     * 根据票状态判断 演出状态 票状态
     *
     * @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", 6, 8, 9));
            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 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 (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;
                        }
                    }

                    if (kylinTicketVoItem.getStatus() == 7) {
                        status = 7;
                    }
                    //修改票状态
                    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 == status8Count) {//全票售罄为售罄
                        appStatus = 8;
                    } else if (ticketCount == status9Count) {//全票未开始 为未开始
                        appStatus = 9;
                    } else if (ticketCount == status10Count) {//全票结束 为结束
                        appStatus = 10;
                    }
                }
            }

            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) {
        PerformancePartnerVo performanceData = mongoTemplate.findOne(Query.query(Criteria.where("performancesId").is(performancesId)), PerformancePartnerVo.class, PerformancePartnerVo.class.getSimpleName());
        List<KylinTicketTimesPartnerVo> kylinTicketTimesPartnerVos = 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 = 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.setPrice(floatList.get(0) + "起");
        kylinPerformanceMisVo.setStopSellTime(StringList.get(0));
        kylinPerformanceMisVo.setTicketTimes(ticketTimesTicketCreatePartnerVoList);

        kylinPerformanceMisVo.setIsDistribution(0);
        kylinPerformanceMisVo.setSyncAgent(0);
        kylinPerformanceMisVo.setNoticeImageList(JsonUtils.fromJson(kylinPerformanceMisVo.getNoticeImage(), new TypeReference<List<KylinBuyNoticeVo>>() {
        }));

        return kylinPerformanceMisVo;
    }

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

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

            performanceStatus.setPerformanceId(performances.getPerformancesId());
            performanceStatus.setPerformanceStatusId(IDGenerator.nextSnowId().toString());
            performanceStatus.setCreatedAt(null);
            performanceStatus.setStatus(null);
            performanceStatus.setStatusSell(null);
            performanceStatus.setAuditStatus(auditStatus);
            performanceStatus.setUpdatedAt(updatedAt);

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

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


            //场次数据
            List<KylinTicketTimesPartnerVo> kylinTicketTimesPartnerVos = getTimesMongoList(performancesId);
            int isMember = 0;

            for (KylinTicketTimesPartnerVo ticketTimeItem : kylinTicketTimesPartnerVos) {
                //修改票
                List<KylinTicketPartnerVo> kylinTicketPartnerVoList = getTicketMongoList(ticketTimeItem.getTicketTimesId());
                for (KylinTicketPartnerVo ticketItem : kylinTicketPartnerVoList) {
                    try {
                        KylinTicketStatus statusData = ticketStatusMapper.selectOne(Wrappers.lambdaQuery(KylinTicketStatus.class).eq(KylinTicketStatus::getTicketId, ticketItem.getTicketsId()));
                        log.info("isMember = ", statusData);
                        if (statusData.getIsMember().equals(1)) {
                            isMember = 1;
                            break;
                        }
                    } catch (Exception e) {
                        log.info("isMember = ", e);
                    }
                }
            }

            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(null);
                ticketTimes.setUpdatedAt(updatedAt);

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

                if (ticketTimeItem.getStatus() == -1) {
                    ticketTimes.setStatus(1);
                    ticketTimesMapper.insert(ticketTimes);
                    ticketTimeRelationMapper.insert(ticketTimeRelation);

                    HashMap<String, Object> map2 = new HashMap<>();
                    map2.put("status", 1);
                    map2.put("updatedAt", map.get("updatedAt"));
                    BasicDBObject objectTicketVo = new BasicDBObject("$set", mongoConverter.convertToMongoType(map2));
                    mongoTemplate.getCollection(KylinTicketTimesPartnerVo.class.getSimpleName()).updateOne(
                            Query.query(Criteria.where("ticketTimesId").is(ticketTimeRelation.getTimesId())).getQueryObject(),
                            objectTicketVo
                    );
                } else {
                    ticketTimesMapper.update(ticketTimes, new UpdateWrapper<KylinTicketTimes>().eq("ticket_times_id", ticketTimes.getTicketTimesId()));
                    ticketTimeRelationMapper.update(ticketTimeRelation, new UpdateWrapper<KylinTicketTimeRelation>().eq("times_id", ticketTimes.getTicketTimesId()));
                }

                //修改票
                List<KylinTicketPartnerVo> kylinTicketPartnerVoList = getTicketMongoList(ticketTimeItem.getTicketTimesId());
                for (KylinTicketPartnerVo ticketItem : kylinTicketPartnerVoList) {
                    KylinTicketPartnerVo kylinTicketPartnerVo;
                    kylinTicketPartnerVo = mongoTemplate.findOne(
                            Query.query(Criteria.where("ticketsId").is(ticketItem.getTicketsId())),
                            KylinTicketPartnerVo.class,
                            KylinTicketPartnerVo.class.getSimpleName()
                    );

                    //创建演出
                    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.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.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.setUpdatedAt(updatedAt);

                    ticketStatus.setTicketStatusId(IDGenerator.nextSnowId());
                    ticketStatus.setTicketId(tickets.getTicketsId());

                    ticketStatus.setStatusExchange(7);
                    if (ticketItem.getIsShowCode() == 1) {
                        ticketStatus.setQrCodeShowTime(DateUtil.asLocalDateTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(ticketItem.getQrCodeShowTime())));
                    }

                    ticketRelations.setUpdatedAt(updatedAt);

                    ticketRelations.setTicketRelationsId(IDGenerator.nextSnowId());
                    ticketRelations.setTicketId(tickets.getTicketsId());
                    ticketRelations.setUpdatedAt(updatedAt);
                    if (ticketItem.getStatus() == -2) {
                        tickets.setAdvanceMinuteMember(5);
                        ticketStatus.setIsMember(isMember);
                        ticketStatus.setMemberLimitCount(1);
                        ticketRelations.setCreatedAt(LocalDateTime.now());
                        tickets.setCreatedAt(LocalDateTime.now());

                        ticketsMapper.insert(tickets);
                        ticketStatus.setStatus(9);
                        ticketStatus.setIsTrueName(performanceStatus.getIsTrueName());
                        ticketStatusMapper.insert(ticketStatus);
                        ticketRelationsMapper.insert(ticketRelations);

                        dataUtils.setSurplusExchange(tickets.getTicketsId(), ticketStatus.getSurplusExchange());
                        dataUtils.setSurplusGeneral(tickets.getTicketsId(), ticketStatus.getSurplusGeneral());

                        BasicDBObject objectTicketVo = new BasicDBObject("$set", mongoConverter.convertToMongoType(map));
                        mongoTemplate.getCollection(KylinTicketPartnerVo.class.getSimpleName()).updateOne(
                                Query.query(Criteria.where("ticketsId").is(ticketItem.getTicketsId())).getQueryObject(),
                                objectTicketVo
                        );
                    } else {
                        //不改动数据 价格 限购 购票时间
                        ticketStatus.setLimitCount(null);
                        ticketStatus.setTotalGeneral(null);
                        ticketStatus.setTotalExchange(null);
                        tickets.setTimeStart(null);
                        tickets.setTimeEnd(null);
                        tickets.setPriceDiscountMember(null);
                        tickets.setPriceDiscount(null);
                        ticketStatus.setCounts(null);
                        ticketStatus.setIsMember(null);
                        ticketStatus.setIsExclusive(null);
                        ticketRelations.setCreatedAt(null);
                        tickets.setCreatedAt(null);
                        ticketsMapper.update(tickets, new UpdateWrapper<KylinTickets>().eq("tickets_id", tickets.getTicketsId()));
                        ticketStatusMapper.update(ticketStatus, new UpdateWrapper<KylinTicketStatus>().eq("ticket_id", tickets.getTicketsId()));
                        ticketRelationsMapper.update(ticketRelations, new UpdateWrapper<KylinTicketRelations>().eq("ticket_id", tickets.getTicketsId()));
                        BasicDBObject objectTicketVo = new BasicDBObject("$set", mongoConverter.convertToMongoType(map));
                        mongoTemplate.getCollection(KylinTicketPartnerVo.class.getSimpleName()).updateOne(
                                Query.query(Criteria.where("ticketsId").is(ticketItem.getTicketsId())).getQueryObject(),
                                objectTicketVo);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public List<KylinTicketPartnerVo> getTicketMongoList(String timesId) {
        return mongoTemplate.find(Query.query(Criteria.where("timesId").is(timesId)), KylinTicketPartnerVo.class, KylinTicketPartnerVo.class.getSimpleName());
    }

    public List<KylinTicketTimesPartnerVo> getTimesMongoList(String performancesId) {
        return mongoTemplate.find(Query.query(Criteria.where("performancesId").is(performancesId)).with(Sort.by(Sort.Direction.ASC, "createdAt")), KylinTicketTimesPartnerVo.class, KylinTicketTimesPartnerVo.class.getSimpleName());
    }

}
