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.commons.lang.util.JsonUtils;
import com.liquidnet.service.kylin.constant.KylinRedisConst;
import com.liquidnet.service.kylin.dto.param.TicketCreateParam;
import com.liquidnet.service.kylin.dto.vo.TicketVo;
import com.liquidnet.service.kylin.dto.vo.ignore.TicketIgnoreVo;
import com.liquidnet.service.kylin.dto.vo.partner.TicketTimesPartnerVo;
import com.liquidnet.service.kylin.dto.vo.partner.TicketPartnerVo;
import com.liquidnet.service.kylin.entity.*;
import com.liquidnet.service.kylin.mapper.*;
import com.liquidnet.service.kylin.service.partner.IKylinTicketsPartnerService;
import com.mongodb.BasicDBObject;
import com.mongodb.client.model.FindOneAndUpdateOptions;
import com.mongodb.client.model.ReturnDocument;
import com.mongodb.client.result.UpdateResult;
import lombok.extern.slf4j.Slf4j;
import org.bson.Document;
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.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;

/**
 * <p>
 * 票 服务实现类
 * </p>
 *
 * @author liquidnet
 * @since 2021-05-06
 */
@Service
@Slf4j
public class KylinTicketsPartnerServiceImpl extends ServiceImpl<KylinTicketsMapper, KylinTickets> implements IKylinTicketsPartnerService {

    @Autowired
    MongoTemplate mongoTemplate;

    @Autowired
    private MongoConverter mongoConverter;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private KylinPerformanceStatusMapper performanceStatusMapper;

    @Autowired
    private KylinTicketTimeRelationMapper ticketTimeRelationMapper;

    @Autowired
    private KylinTicketsMapper ticketsMapper;

    @Autowired
    private KylinTicketStatusMapper ticketStatusMapper;

    @Autowired
    private KylinTicketRelationsMapper ticketRelationsMapper;

    @Override
    public TicketPartnerVo createTicketSummary(TicketCreateParam ticketCreateParam) {
        TicketPartnerVo ticketPartnerVo = null;
        //获取演出状态
        TicketTimesPartnerVo timesPartnerVo = mongoTemplate.findOne(Query.query(Criteria.where("ticketTimesId").is(ticketCreateParam.getTimesId())),TicketTimesPartnerVo.class,TicketTimesPartnerVo.class.getSimpleName());

        if (null != timesPartnerVo) {
            KylinPerformanceStatus performanceStatus = performanceStatusMapper.selectOne(
                    new UpdateWrapper<KylinPerformanceStatus>().eq("performance_id", timesPartnerVo.getPerformancesId()));
            if (null == performanceStatus) {
                ticketPartnerVo = createTicket(ticketCreateParam);
                log.info(" PERFORMANCE 票 创建");
            } else if (performanceStatus.getStatus() >= 3 && performanceStatus.getStatus() != 4) {//未被拒绝 且 通过审核的演出
                ticketPartnerVo = addNewTicket(ticketCreateParam);
                log.info(" PERFORMANCE 票 添加");
            } else {
                ticketPartnerVo = createTicket(ticketCreateParam);
                log.info(" PERFORMANCE 票 创建");
            }
        } else {
            ticketPartnerVo = createTicket(ticketCreateParam);
            log.info(" PERFORMANCE 票 创建");
        }
        return ticketPartnerVo;
    }

    @Override
    public TicketPartnerVo createTicket(TicketCreateParam ticketCreateParam) {
        // 获取 主键id
        String ticketsId = IDGenerator.nextSnowId().toString();
        // 获取 当前时间 -> 创建时间
        LocalDateTime createdAt = LocalDateTime.now();
        ticketCreateParam.setTicketsId(ticketsId);

        // mongo 操作
        TicketPartnerVo ticketPartnerVo = new TicketPartnerVo();
        BeanUtils.copyProperties(ticketCreateParam, ticketPartnerVo);
        ticketPartnerVo.setTicketsId(ticketsId);
        ticketPartnerVo.setCreatedAt(createdAt.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        ticketPartnerVo.setTimeStart(ticketCreateParam.getTimeStart().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        ticketPartnerVo.setTimeEnd(ticketCreateParam.getTimeEnd().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));

        TicketTimesPartnerVo ticketTimesPartnerVo = mongoTemplate.findOne(Query.query(Criteria.where("ticketTimesId").is(ticketCreateParam.getTimesId())), TicketTimesPartnerVo.class, TicketTimesPartnerVo.class.getSimpleName());
        ticketPartnerVo.setUseStart(ticketTimesPartnerVo.getUseStart());
        ticketPartnerVo.setUseEnd(ticketTimesPartnerVo.getUseEnd());
        ticketPartnerVo.setType(ticketTimesPartnerVo.getType());
        ticketPartnerVo.setStatus(0);
        ticketPartnerVo.setDefault();

        if (ticketCreateParam.getIsExpress() == 1) {
            ticketPartnerVo.setTimeEndExpress(ticketCreateParam.getTimeEndExpress().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        }

        if (ticketCreateParam.getIsShowCode() == 1) {
            ticketPartnerVo.setQrCodeShowTime(ticketCreateParam.getQrCodeShowTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        }

        TicketPartnerVo data = mongoTemplate.insert(
                ticketPartnerVo, TicketPartnerVo.class.getSimpleName()
        );

        return ticketPartnerVo;
    }

    @Override
    public TicketPartnerVo addNewTicket(TicketCreateParam ticketCreateParam) {
        // 获取 主键id
        String ticketsId = IDGenerator.nextSnowId().toString();
        // 获取 当前时间 -> 创建时间
        LocalDateTime createdAt = LocalDateTime.now();
        ticketCreateParam.setTicketsId(ticketsId);

        // mongo 操作
        TicketPartnerVo ticketPartnerVo = new TicketPartnerVo();
        BeanUtils.copyProperties(ticketCreateParam, ticketPartnerVo);
        ticketPartnerVo.setTicketsId(ticketsId);
        ticketPartnerVo.setCreatedAt(createdAt.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        ticketPartnerVo.setTimeStart(ticketCreateParam.getTimeStart().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        ticketPartnerVo.setTimeEnd(ticketCreateParam.getTimeEnd().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));

        TicketTimesPartnerVo ticketTimesPartnerVo = mongoTemplate.findOne(Query.query(Criteria.where("ticketTimesId").is(ticketCreateParam.getTimesId())), TicketTimesPartnerVo.class, TicketTimesPartnerVo.class.getSimpleName());
        ticketPartnerVo.setUseStart(ticketTimesPartnerVo.getUseStart());
        ticketPartnerVo.setUseEnd(ticketTimesPartnerVo.getUseEnd());
        ticketPartnerVo.setType(ticketTimesPartnerVo.getType());
        ticketPartnerVo.setStatus(-2);
        ticketPartnerVo.setDefault();

        if (ticketCreateParam.getIsExpress() == 1) {
            ticketPartnerVo.setTimeEndExpress(ticketCreateParam.getTimeEndExpress().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        }

        if (ticketCreateParam.getIsShowCode() == 1) {
            ticketPartnerVo.setQrCodeShowTime(ticketCreateParam.getQrCodeShowTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        }

        TicketPartnerVo data = mongoTemplate.insert(
                ticketPartnerVo, TicketPartnerVo.class.getSimpleName()
        );

        return ticketPartnerVo;
    }

    @Override
    public TicketPartnerVo updateTicket(TicketCreateParam ticketCreateParam) {
        try {
            String ticketId = ticketCreateParam.getTicketsId();
            LocalDateTime updatedAt = LocalDateTime.now();
            // mongo 操作
            TicketPartnerVo ticketPartnerVo = new TicketPartnerVo();
            BeanUtils.copyProperties(ticketCreateParam, ticketPartnerVo);
            ticketPartnerVo.setUpdatedAt(updatedAt.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            ticketPartnerVo.setTimeStart(ticketCreateParam.getTimeStart().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            ticketPartnerVo.setTimeEnd(ticketCreateParam.getTimeEnd().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            ticketPartnerVo.setTimesId(null);
            ticketPartnerVo.setStatus(null);
            ticketPartnerVo.setDefault();
            if (ticketCreateParam.getIsExpress() == 1) {
                ticketPartnerVo.setTimeEndExpress(ticketCreateParam.getTimeEndExpress().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            }
            if (ticketCreateParam.getIsShowCode() == 1) {
                ticketPartnerVo.setQrCodeShowTime(ticketCreateParam.getQrCodeShowTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            }

            BasicDBObject object = new BasicDBObject("$set", mongoConverter.convertToMongoType(ticketPartnerVo));
            Document doc = mongoTemplate.getCollection(TicketPartnerVo.class.getSimpleName()).findOneAndUpdate(
                    Query.query(Criteria.where("ticketsId").is(ticketId)).getQueryObject(),
                    object,
                    new FindOneAndUpdateOptions().returnDocument(ReturnDocument.AFTER)
            );

            TicketPartnerVo ticketPartnerVoData = JsonUtils.fromJson(doc.toJson(), TicketPartnerVo.class);
            return ticketPartnerVoData;
        } catch (Exception e) {
            return null;
        }
    }

    @Override
    public boolean deleteTicket(String ticketsId) {
        try {
            LocalDateTime updatedAt = LocalDateTime.now();

            KylinTicketRelations ticketRelations = ticketRelationsMapper.selectOne(
                    new UpdateWrapper<KylinTicketRelations>().eq("ticket_id", ticketsId));

            if (ticketRelations == null) {
                mongoTemplate.remove(Query.query(Criteria.where("ticketsId").is(ticketsId)), TicketPartnerVo.class, TicketPartnerVo.class.getSimpleName());
                return true;
            }
            KylinTicketTimeRelation ticketTimeRelation = ticketTimeRelationMapper.selectOne(
                    new UpdateWrapper<KylinTicketTimeRelation>().eq("times_id", ticketRelations.getTimesId()));

            KylinPerformanceStatus performanceStatus = performanceStatusMapper.selectOne(
                    new UpdateWrapper<KylinPerformanceStatus>().eq("performance_id", ticketTimeRelation.getPerformanceId()));

            if (performanceStatus.getStatus() == 0 || performanceStatus.getStatus() == 4) {//未提审||被拒绝
                // mongo 操作
                HashMap<String, Object> map = new HashMap<>();
                map.put("updatedAt", updatedAt.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                map.put("status", -1);

                BasicDBObject object = new BasicDBObject("$set", mongoConverter.convertToMongoType(map));
                Document doc = mongoTemplate.getCollection(TicketPartnerVo.class.getSimpleName()).findOneAndUpdate(
                        Query.query(Criteria.where("ticketsId").is(ticketsId)).getQueryObject(),
                        object,
                        new FindOneAndUpdateOptions().returnDocument(ReturnDocument.AFTER)
                );
                return true;
            } else {
                return false;
            }
        } catch (Exception e) {
            return false;
        }
    }

    @Override
    public TicketPartnerVo copyTicket(String ticketsId) {

        // 获取 当前时间 -> 创建时间
        LocalDateTime createdAt = LocalDateTime.now();

        TicketPartnerVo ticketPartnerVo = mongoTemplate.findOne(Query.query(Criteria.where("ticketsId").is(ticketsId)), TicketPartnerVo.class, TicketPartnerVo.class.getSimpleName());
        ticketPartnerVo.setCreatedAt(createdAt.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        ticketPartnerVo.setTicketsId(IDGenerator.nextSnowId().toString());

        TicketPartnerVo data = mongoTemplate.insert(
                ticketPartnerVo, TicketPartnerVo.class.getSimpleName()
        );

        redisUtil.hset(KylinRedisConst.TICKET, ticketsId, ticketPartnerVo);
        return ticketPartnerVo;
    }

    @Override
    public boolean submitTicketByTimes(String timesId) {
        LocalDateTime updatedAt = LocalDateTime.now();

        HashMap<String, Object> map = new HashMap<>();
        map.put("status", 1);
        map.put("updatedAt", updatedAt.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        BasicDBObject object = new BasicDBObject("$set", mongoConverter.convertToMongoType(map));
        UpdateResult updateResult = mongoTemplate.getCollection(TicketPartnerVo.class.getSimpleName()).updateMany(
                Query.query(Criteria.where("timesId").is(timesId)).getQueryObject(),
                object
        );
        return updateResult.getModifiedCount() <= 0;
    }

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

    @Override
    public TicketPartnerVo getTicketsMongo(String ticketsId) {
        return mongoTemplate.findOne(Query.query(Criteria.where("ticketsId").is(ticketsId)), TicketPartnerVo.class, TicketPartnerVo.class.getSimpleName());
    }

    @Override
    public boolean onLine(String ticketsId) {
        LocalDateTime updatedAt = LocalDateTime.now();
        KylinTicketStatus ticketStatus = ticketStatusMapper.selectOne(new UpdateWrapper<KylinTicketStatus>().eq("ticket_id", ticketsId));
        if (ticketStatus.getStatus() >= 3 && ticketStatus.getStatus() != 4 && ticketStatus.getStatus() != 6) {//未提审||被拒绝
            //mysql
            KylinTicketStatus changeStatus = new KylinTicketStatus();
            changeStatus.setUpdatedAt(updatedAt);
            changeStatus.setStatus(6);
            ticketStatusMapper.update(changeStatus, new UpdateWrapper<KylinTicketStatus>().eq("ticket_id", ticketsId));

            // mongo 操作
            KylinTicketStatus ticketStatusMongo = ticketStatusMapper.selectOne(new UpdateWrapper<KylinTicketStatus>().eq("ticket_id", ticketsId).between("status", 1, 10).ne("status", 7));
            KylinTicketRelations ticketRelation = ticketRelationsMapper.selectOne(new UpdateWrapper<KylinTicketRelations>().eq("ticket_id", ticketsId));
            KylinTickets tickets = ticketsMapper.selectOne(
                    new UpdateWrapper<KylinTickets>().eq("tickets_id", ticketsId
                    )
            );

            TicketVo ticketVo = new TicketVo();
            ticketVo.setTimeId(ticketRelation.getTimesId());
            ticketVo.setTicket(tickets);
            ticketVo.setTicketStatus(ticketStatusMongo);

            boolean ticketExists =
                    mongoTemplate.exists(Query.query(Criteria.where("ticketsId").is(ticketVo.getTicketsId())), TicketVo.class, TicketVo.class.getSimpleName());
            if (!ticketExists) {
                mongoTemplate.insert(
                        ticketVo, TicketVo.class.getSimpleName()
                );
            }
            //TODO 修改misVo

            return true;
        } else {
            return false;
        }
    }

    @Override
    public boolean outLine(String ticketsId) {
        LocalDateTime updatedAt = LocalDateTime.now();
        KylinTicketStatus ticketStatus = ticketStatusMapper.selectOne(new UpdateWrapper<KylinTicketStatus>().eq("ticket_id", ticketsId));
        if (ticketStatus.getStatus() >= 3 && ticketStatus.getStatus() != 4 && ticketStatus.getStatus() != 7) {//未提审||被拒绝
            //mysql
            KylinTicketStatus changeStatus = new KylinTicketStatus();
            changeStatus.setUpdatedAt(updatedAt);
            changeStatus.setStatus(7);
            ticketStatusMapper.update(changeStatus, new UpdateWrapper<KylinTicketStatus>().eq("ticket_id", ticketsId));
            // mongo 操作
            TicketVo ticketVoItem = mongoTemplate.findOne(Query.query(Criteria.where("ticketsId").is(ticketsId)), TicketVo.class, TicketVo.class.getSimpleName());
            TicketIgnoreVo ticketIgnoreVo = new TicketIgnoreVo();
            BeanUtils.copyProperties(ticketVoItem, ticketIgnoreVo);
            mongoTemplate.remove(Query.query(Criteria.where("ticketsId").is(ticketVoItem.getTicketsId())), TicketIgnoreVo.class, TicketIgnoreVo.class.getSimpleName());
            mongoTemplate.insert(ticketIgnoreVo, TicketIgnoreVo.class.getSimpleName());
            mongoTemplate.remove(Query.query(Criteria.where("ticketsId").is(ticketVoItem.getTicketsId())), TicketVo.class, TicketVo.class.getSimpleName());
            //TODO 删除misVo
            return true;
        } else {
            return false;
        }
    }

}
