package com.liquidnet.service.kylin.service.impl.partner;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.liquidnet.common.cache.redis.util.RedisUtil;
import com.liquidnet.commons.lang.util.IDGenerator;
import com.liquidnet.service.kylin.constant.KylinRedisConst;
import com.liquidnet.service.kylin.dto.TicketInventoryDto;
import com.liquidnet.service.kylin.dto.param.PerformanceCreateParam;
import com.liquidnet.service.kylin.dto.param.PerformanceStep1Param;
import com.liquidnet.service.kylin.dto.param.PerformanceStep2Param;
import com.liquidnet.service.kylin.dto.vo.PerformanceVo;
import com.liquidnet.service.kylin.dto.vo.TicketTimesVo;
import com.liquidnet.service.kylin.dto.vo.TicketVo;
import com.liquidnet.service.kylin.dto.vo.partner.PerformanceCreatePartnerVo;
import com.liquidnet.service.kylin.dto.vo.partner.TicketCreatePartnerVo;
import com.liquidnet.service.kylin.dto.vo.partner.TicketTimesCreatePartnerVo;
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.kylin.service.partner.IKylinPerformancesPartnerService;
import com.liquidnet.service.kylin.service.impl.PerformanceVoTask;
import com.mongodb.BasicDBObject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
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.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 演出 服务实现类
 * </p>
 *
 * @author liquidnet
 * @since 2021-05-05
 */
@Service
public class KylinPerformancesPartnerServiceImpl extends ServiceImpl<KylinPerformancesMapper, KylinPerformances> implements IKylinPerformancesPartnerService {

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private MongoConverter mongoConverter;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private PerformanceVoTask performanceVoTask;

    @Autowired
    private KylinPerformancesMapper performancesMapper;

    @Autowired
    private KylinPerformanceStatusMapper performanceStatusMapper;

    @Autowired
    private KylinPerformanceRelationsMapper performanceRelationsMapper;

    @Autowired
    private KylinTicketTimesMapper ticketTimesMapper;

    @Autowired
    private KylinTicketTimeRelationMapper ticketTimeRelationMapper;

    @Autowired
    private KylinTicketsMapper ticketsMapper;

    @Autowired
    private KylinTicketStatusMapper ticketStatusMapper;

    @Autowired
    private KylinTicketRelationsMapper ticketRelationsMapper;

    @Autowired
    private KylinTicketsPartnerServiceImpl ticketsPartnerService;

    @Autowired
    private KylinTicketTimesPartnerServiceImpl ticketTimesPartnerService;

    @Override
    public String createStep1(PerformanceStep1Param step1Param) {
        // 获取 主键id
        String performanceId = IDGenerator.nextSnowId().toString();
        // 获取 当前时间 -> 创建时间
        LocalDateTime createdAt = LocalDateTime.now();

        try {
            step1Param.setCreatedAt(createdAt.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            step1Param.setPerformancesId(performanceId);
            PerformanceStep1Param data = mongoTemplate.insert(
                    step1Param, PerformanceStep1Param.class.getSimpleName()
            );
            return performanceId;
        } catch (Exception e) {
            return "";
        }
    }

    @Override
    public boolean createStep2(PerformanceStep2Param step2Param) {

        // 获取 主键id
        String performanceId = step2Param.getPerformancesId();
        // 获取 当前时间 -> 创建时间
        LocalDateTime createdAt = LocalDateTime.now();

        PerformanceStep1Param info = mongoTemplate.findOne(Query.query(Criteria.where("performancesId").is(performanceId)),
                PerformanceStep1Param.class,
                PerformanceStep1Param.class.getSimpleName());

        boolean isExists = mongoTemplate.exists(Query.query(Criteria.where("performancesId").is(performanceId).and("status").is(0)),
                PerformanceCreateParam.class,
                PerformanceCreateParam.class.getSimpleName());

        boolean isExistsSubmit = mongoTemplate.exists(Query.query(Criteria.where("performancesId").is(performanceId).and("status").is(1)),
                PerformanceCreateParam.class,
                PerformanceCreateParam.class.getSimpleName());

        if (isExistsSubmit) {
            return false;
        }

        //演出修改数据
        HashMap<String, Object> map = new HashMap<>();
        map.put("isTrueName", step2Param.getIsTrueName());
        map.put("limitCount", step2Param.getLimitCount());
        map.put("createdAt", createdAt.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        map.put("isSubmit", step2Param.getIsSubmit());
        map.put("merchantId", step2Param.getMerchantId());
        map.put("statuSell", 1);

        //演出新增数据
        PerformanceCreateParam performanceCreateParam = new PerformanceCreateParam();
        BeanUtils.copyProperties(info, performanceCreateParam);
        performanceCreateParam.setIsTrueName(step2Param.getIsTrueName());
        performanceCreateParam.setLimitCount(step2Param.getLimitCount());
        performanceCreateParam.setCreatedAt(createdAt.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        performanceCreateParam.setIsSubmit(step2Param.getIsSubmit());
        performanceCreateParam.setMerchantId(step2Param.getMerchantId());

        // 获取第一步数据
        if (step2Param.getIsSubmit() == 1) { // 提交
            if (isExists) {
                map.put("status", 1);
                BasicDBObject object = new BasicDBObject("$set", mongoConverter.convertToMongoType(map));
                mongoTemplate.getCollection(PerformanceCreateParam.class.getSimpleName()).updateOne(
                        Query.query(Criteria.where("performancesId").is(performanceId)).getQueryObject(),
                        object
                );
            } else {
                // 提交 演出
                performanceCreateParam.setStatus(1);
                PerformanceCreateParam data = mongoTemplate.insert(
                        performanceCreateParam, PerformanceCreateParam.class.getSimpleName()
                );
            }


            //提交 票
            List<TicketTimesCreatePartnerVo> ticketTimesCreatePartnerVoList = ticketTimesPartnerService.getTimesMongoList(performanceId);
            for (TicketTimesCreatePartnerVo ticketTimes : ticketTimesCreatePartnerVoList) {
                boolean boolResult = ticketsPartnerService.submitTicketByTimes(ticketTimes.getTicketTimesId());
                if (boolResult) {
                    return false;
                }
            }
            if (ticketTimesCreatePartnerVoList.size() <= 0) {
                return false;
            }
        } else { //保存
            if (isExists) {
                map.put("status", 0);
                BasicDBObject object = new BasicDBObject("$set", mongoConverter.convertToMongoType(map));
                mongoTemplate.getCollection(PerformanceCreateParam.class.getSimpleName()).updateMany(
                        Query.query(Criteria.where("performancesId").is(performanceId)).getQueryObject(),
                        object
                );
            } else {
                // 保存 演出
                performanceCreateParam.setStatus(0);
                PerformanceCreateParam data = mongoTemplate.insert(
                        performanceCreateParam, PerformanceCreateParam.class.getSimpleName()
                );
            }
        }

        return true;
    }

    @Override
    public PerformanceStep1Param getStep1(String performancesId) {
        PerformanceStep1Param data = mongoTemplate.findOne(
                Query.query(Criteria.where("performancesId").is(performancesId)), PerformanceStep1Param.class, PerformanceStep1Param.class.getSimpleName()
        );
        if (data == null) {
            return new PerformanceStep1Param();
        }
        return data;
    }

    @Override
    public PerformanceStep2Param getStep2(String performancesId) {
        PerformanceCreateParam data = mongoTemplate.findOne(
                Query.query(Criteria.where("performancesId").is(performancesId)), PerformanceCreateParam.class, PerformanceCreateParam.class.getSimpleName()
        );

        if (data == null) {
            return new PerformanceStep2Param();
        }

        List<TicketTimesCreatePartnerVo> ticketTimesCreatePartnerVos = ticketTimesPartnerService.getTimesMongoList(performancesId);
        List<TicketTimesTicketCreatePartnerVo> ticketTimesTicketCreatePartnerVoList = new ArrayList<TicketTimesTicketCreatePartnerVo>();

        for (TicketTimesCreatePartnerVo ticketTimes : ticketTimesCreatePartnerVos) {
            TicketTimesTicketCreatePartnerVo ticketTimesTicketCreatePartnerVo = new TicketTimesTicketCreatePartnerVo();
            BeanUtils.copyProperties(ticketTimes, ticketTimesTicketCreatePartnerVo);
            List<TicketCreatePartnerVo> ticketCreatePartnerVos = ticketsPartnerService.getTicketMongoList(ticketTimes.getTicketTimesId());
            ticketTimesTicketCreatePartnerVo.setTicket(ticketCreatePartnerVos);
            ticketTimesTicketCreatePartnerVoList.add(ticketTimesTicketCreatePartnerVo);
        }

        PerformanceStep2Param performanceStep2Param = new PerformanceStep2Param();
        BeanUtils.copyProperties(data, performanceStep2Param);
        performanceStep2Param.setTicketTimes(ticketTimesTicketCreatePartnerVoList);

        return performanceStep2Param;
    }

    @Override
    public boolean onLinePerformance(String performancesId) {
        try {

            KylinPerformanceStatus performanceStatusData = performanceStatusMapper.selectOne(new UpdateWrapper<KylinPerformanceStatus>().eq("performance_id", performancesId));

            if (performanceStatusData.getStatus() > 7) {
                return false;
            }

            // mysql
            LocalDateTime updatedAt = LocalDateTime.now();
            KylinPerformanceStatus performanceStatusUpdate = new KylinPerformanceStatus();
            performanceStatusUpdate.setStatus(9);
            performanceStatusUpdate.setUpdatedAt(updatedAt);
            performanceStatusMapper.update(performanceStatusUpdate
                    , new UpdateWrapper<KylinPerformanceStatus>().eq("performance_id", performancesId));

            //mongo操作 票
            KylinPerformances performancesData = performancesMapper.selectOne(new UpdateWrapper<KylinPerformances>().eq("performances_id", performancesId));
            PerformanceVo performanceVoData = new PerformanceVo();
            performanceVoData.setPerformance(performancesData);
            performanceVoData.setPerformanceStatus(performanceStatusData);

            //场次
            List<KylinTicketTimeRelation> ticketTimeRelation = ticketTimeRelationMapper.selectList(new UpdateWrapper<KylinTicketTimeRelation>().eq("performance_id", performancesId));

            LocalDateTime stopSellTime = null;
            LocalDateTime sellTime = null;
            int isLackRegister = 0;
            int isMember = 0;
            int isExclusive = 0;
            BigDecimal price = new BigDecimal("0.00");


            for (KylinTicketTimeRelation ticketTimeRelationItem : ticketTimeRelation) {
                KylinTicketTimes ticketTimes = ticketTimesMapper.selectOne(new UpdateWrapper<KylinTicketTimes>().eq("ticket_times_id", ticketTimeRelationItem.getTimesId()));
                TicketTimesVo ticketTimesVo = new TicketTimesVo();
                ticketTimesVo.setTicketTimes(ticketTimes);
                ticketTimesVo.setPerformanceId(ticketTimeRelationItem.getPerformanceId());
                ticketTimesVo.setTimeId(ticketTimeRelationItem.getTimesId());

                //票
                List<KylinTicketRelations> ticketRelations = ticketRelationsMapper.selectList(new UpdateWrapper<KylinTicketRelations>().eq("times_id", ticketTimes.getTicketTimesId()));
                for (KylinTicketRelations ticketRelationsItem : ticketRelations) {
                    KylinTicketStatus ticketStatus = ticketStatusMapper.selectOne(new UpdateWrapper<KylinTicketStatus>().eq("ticket_id", ticketRelationsItem.getTicketId()));
                    KylinTickets tickets = ticketsMapper.selectOne(
                            new UpdateWrapper<KylinTickets>().eq("tickets_id", ticketRelationsItem.getTicketId()
                            )
                    );

                    KylinTicketStatus ticketStatusUpdate = new KylinTicketStatus();
                    ticketStatusUpdate.setStatus(9);
                    ticketStatusUpdate.setUpdatedAt(updatedAt);
                    ticketStatusMapper.update(ticketStatusUpdate
                            , new UpdateWrapper<KylinTicketStatus>().eq("ticket_id", ticketRelationsItem.getTicketId()));

                    TicketVo ticketVo = new TicketVo();
                    ticketVo.setTimeId(ticketRelationsItem.getTimesId());
                    ticketVo.setTicket(tickets);
                    ticketVo.setTicketStatus(ticketStatus);
                    mongoTemplate.insert(
                            ticketVo, TicketVo.class.getSimpleName()
                    );

                    //票种 库存redis TODO 库存可能会丢
                    TicketInventoryDto ticketInventoryRedis= (TicketInventoryDto) redisUtil.hget(KylinRedisConst.PERFORMANCES_INVENTORY,ticketVo.getTicketsId());
                    TicketInventoryDto ticketInventoryDto = new TicketInventoryDto();
                    if(ticketInventoryRedis==null){
                        ticketInventoryDto.setSurplusExchange(ticketStatus.getSurplusExchange());
                        ticketInventoryDto.setSurplusGeneral(ticketStatus.getTotalGeneral());
                        ticketInventoryDto.setTicketsId(ticketVo.getTicketsId());
                    }else{
                        ticketInventoryDto.setSurplusExchange(ticketStatus.getSurplusExchange()-ticketInventoryRedis.getSurplusExchange());
                        ticketInventoryDto.setSurplusGeneral(ticketStatus.getTotalGeneral()-ticketInventoryRedis.getSurplusGeneral());
                        ticketInventoryDto.setTicketsId(ticketVo.getTicketsId());
                    }
                    redisUtil.hset(KylinRedisConst.PERFORMANCES_INVENTORY, ticketVo.getTicketsId(), ticketInventoryDto);

                    if (ticketVo.getIsMember() == 1) {
                        isMember = 1;
                    }
                    if (ticketVo.getIsLackRegister() == 1) {
                        isLackRegister = 1;
                    }
                    if (ticketVo.getIsExclusive() == 1) {
                        isExclusive = 1;
                    }
                    if (price.subtract(ticketVo.getPrice()).compareTo(new BigDecimal("0.00")) < 0) {
                        price = ticketVo.getPrice();
                    }
                    if (stopSellTime == null || stopSellTime.isBefore(tickets.getTimeEnd())) {
                        stopSellTime = tickets.getTimeEnd();
                    }

                    if (sellTime == null || sellTime.isAfter(tickets.getTimeStart().plusMinutes(-tickets.getAdvanceMinuteMember()))) {
                        sellTime = tickets.getTimeStart().plusMinutes(-tickets.getAdvanceMinuteMember());
                    }

                }

                mongoTemplate.insert(
                        ticketTimesVo, TicketTimesVo.class.getSimpleName()
                );
            }
            performanceVoData.setTimePriceVipAndLack(isLackRegister, isMember, isExclusive, price, stopSellTime, sellTime);
            mongoTemplate.insert(
                    performanceVoData, PerformanceVo.class.getSimpleName()
            );

            //修改 提审vo
            Map<String,Object> map = new HashMap<>();
            map.put("status", 3);
            BasicDBObject objectPerformance = new BasicDBObject("$set", mongoConverter.convertToMongoType(map));
            mongoTemplate.getCollection(PerformanceCreatePartnerVo.class.getSimpleName()).updateOne(
                    Query.query(Criteria.where("performancesId").is(performancesId)).getQueryObject(),
                    objectPerformance
            );

            //判断状态
            performanceVoTask.performanceVoStatus(performancesId);

            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    @Override
    public boolean outLinePerformance(String performancesId) {
        try {
            LocalDateTime updatedAt = LocalDateTime.now();
            KylinPerformanceStatus performanceStatus = new KylinPerformanceStatus();
            performanceStatus.setStatus(7);
            performanceStatus.setUpdatedAt(updatedAt);
            performanceStatusMapper.update(performanceStatus
                    , new UpdateWrapper<KylinPerformanceStatus>().eq("performance_id", performancesId));
            return true;
        } catch (Exception e) {
            return false;
        }
    }
}
