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

import com.liquidnet.common.cache.redis.util.RedisUtil;
import com.liquidnet.commons.lang.util.DistanceUtil;
import com.liquidnet.service.kylin.constant.KylinPerformanceStatusEnum;
import com.liquidnet.service.kylin.constant.KylinRedisConst;
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.entity.KylinPerformances;
import com.liquidnet.service.kylin.mapper.KylinPerformancesMapper;
import com.liquidnet.service.kylin.service.IKylinPerformancesService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.bson.Document;
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.BasicQuery;
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.*;
import java.util.regex.Pattern;

/**
 * <p>
 * 前端 演出 服务实现类
 * </p>
 *
 * @author jiangxiulong
 * @since 2021-05-11
 */
@Service
public class KylinPerformancesServiceImpl extends ServiceImpl<KylinPerformancesMapper, KylinPerformances> implements IKylinPerformancesService {

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    RedisUtil redisUtil;

    public HashMap<String, Object> localList(
            String timeStart, int days, String title, String cityName, int type,
            Integer isDiscount, Integer isAdvance, Integer isExclusive,
            int page, int size,
            String orderBy, String sort
    ) {
        HashMap<String, Object> info = new HashMap<>();

        // 排序 分页
        Sort sortName = null; // 默认开票越早的在上面
        if (sort.equals("DESC")) {
            if (!orderBy.isEmpty()) {
                sortName = Sort.by(Sort.Direction.DESC, orderBy);
            }
        } else if (sort.equals("ASC")) {
            if (!orderBy.isEmpty()) {
                sortName = Sort.by(Sort.Direction.ASC, orderBy);
            }
        } else {
            sortName = Sort.by(Sort.Direction.ASC, "timeStart");
        }

        Pageable pageable = PageRequest.of(page - 1, size, sortName);

        //条件
        Document queryObject = new Document();

        if (!title.isEmpty()) {
            queryObject.put("title", Pattern.compile(title, Pattern.CASE_INSENSITIVE));
        }
        if (!cityName.isEmpty()) {
            queryObject.put("cityName", Pattern.compile(cityName, Pattern.CASE_INSENSITIVE));
        }
        if (type > 0) {
            queryObject.put("type", type);
        }
        if (isExclusive != null) {
            queryObject.put("isExclusive", isExclusive);
        }
        if (isDiscount != null) {
            queryObject.put("isDiscount", isDiscount);
        }
        if (isAdvance != null) {
            queryObject.put("isAdvance", isAdvance);
        }

        Query query = new BasicQuery(queryObject);
        if (!timeStart.isEmpty()) {
            String timeStartEnd = timeStart + " 23:59:59";
            query.addCriteria(Criteria.where("timeStart").gte(timeStart).lte(timeStartEnd));
        }
        if (days > 0) {
            LocalDateTime nowTime = LocalDateTime.now();
            String nowTimeStr = nowTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            LocalDateTime OtherTime = nowTime.plusDays(days);
            String OtherTimeStr = OtherTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            query.addCriteria(Criteria.where("timeStart").gte(nowTimeStr).lte(OtherTimeStr));
        }

        // 固定查询条件
        LocalDateTime nowTime = LocalDateTime.now();
        String nowTimeStr = nowTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        query.addCriteria(Criteria.where("timeEnd").gte(nowTimeStr));

        // 要查询的字段
//        query.fields().include();//包含该字段
//        query.fields().exclude();//不包含该字段

        // 查询总数
        long count = mongoTemplate.count(query, PerformanceVo.class, PerformanceVo.class.getSimpleName());
        query.getQueryObject();

        query.with(pageable);

        List<PerformanceVo> list = mongoTemplate.find(query, PerformanceVo.class, PerformanceVo.class.getSimpleName());

        // 组合数据
        info.put("total", count);
        info.put("list", list);
        info.put("is_native", 1);
        info.put("recommend", 0);

        return info;
    }

    public HashMap<String, Object> noticeList() {
        // 固定条件
        Query query = new Query();
        LocalDateTime nowTime = LocalDateTime.now();
        String nowTimeStr = nowTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        query.addCriteria(Criteria.where("timeEnd").gte(nowTimeStr));

        // 今天的
        LocalDateTime toDayTime = LocalDateTime.now();
        String toDayTimeStr = toDayTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        LocalDateTime toDayEndTime = toDayTime.plusDays(1);
        String toDayEndTimeStr = toDayEndTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        query.addCriteria(Criteria.where("timeStart").gte(toDayTimeStr).lt(toDayEndTimeStr));
        List<PerformanceVo> toDayList = mongoTemplate.find(query, PerformanceVo.class, PerformanceVo.class.getSimpleName());

        // 三天的
        Query queryT = new Query();
        LocalDateTime nowTimeT = LocalDateTime.now();
        String nowTimeStrT = nowTimeT.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        queryT.addCriteria(Criteria.where("timeEnd").gte(nowTimeStrT));

        LocalDateTime threeDaysLater = toDayTime.plusDays(3);
        String threeDaysLaterStr = threeDaysLater.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        queryT.addCriteria(Criteria.where("timeStart").gte(toDayEndTimeStr).lt(threeDaysLaterStr));
        List<PerformanceVo> threeDaysList = mongoTemplate.find(queryT, PerformanceVo.class, PerformanceVo.class.getSimpleName());

        HashMap<String, Object> info = new HashMap<>();
        info.put("toDayList", toDayList);
        info.put("threeDaysList", threeDaysList);
        return info;
    }

    public List<PerformanceVo> recommendList() {
        // 固定条件
        Query query = new Query();
        LocalDateTime nowTime = LocalDateTime.now();
        String nowTimeStr = nowTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        query.addCriteria(Criteria.where("timeEnd").gte(nowTimeStr));
        // 推荐
        query.addCriteria(Criteria.where("isRecommend").is(1));
        List<PerformanceVo> recommendList = mongoTemplate.find(query, PerformanceVo.class, PerformanceVo.class.getSimpleName());

        return recommendList;
    }

    public HashMap<String, Object> detail(String performancesId, double latitudeFrom, double longitudeFrom) {
        HashMap<String, Object> info = new HashMap<>();

        PerformanceVo performancesInfo = (PerformanceVo) redisUtil.hget(KylinRedisConst.PERFORMANCES, performancesId);
        String roadShowId = "";
        if (null == performancesInfo) {
            performancesInfo = mongoTemplate.findOne(
                    Query.query(Criteria.where("performancesId").is(performancesId)),
                    PerformanceVo.class,
                    PerformanceVo.class.getSimpleName()
            );
            roadShowId = performancesInfo.getRoadShowId();

            redisUtil.hset(KylinRedisConst.PERFORMANCES, performancesId, performancesInfo);
        } else {
            roadShowId = performancesInfo.getRoadShowId();
        }

        List<PerformanceVo> roadList = new ArrayList();
        if (Integer.parseInt(roadShowId) > 0) {
            roadList = mongoTemplate.find(
                    Query.query(Criteria.where("roadShowId").is(roadShowId)),
                    PerformanceVo.class,
                    PerformanceVo.class.getSimpleName()
            );
        }

        // 处理状态 购买 未开始 结束可更改   下架 售馨不可更改
        if (performancesInfo.getAppStatus() == 6 || performancesInfo.getAppStatus() == 9 || performancesInfo.getAppStatus() == 10) {
            String stopSellTime = performancesInfo.getStopSellTime();
            String sellTime = performancesInfo.getSellTime();
            DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            LocalDateTime stopSellTimeL = LocalDateTime.parse(stopSellTime, df);
            LocalDateTime sellTimeL = LocalDateTime.parse(sellTime, df);

            LocalDateTime nowTime = LocalDateTime.now();
            String nowTimeStr = nowTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            LocalDateTime nowTimeStrL = LocalDateTime.parse(nowTimeStr, df);

            if (sellTimeL.isAfter(nowTimeStrL)) {// 未开始
                performancesInfo.setAppStatus(9);
            } else { // 购买
                performancesInfo.setAppStatus(6);
            }
            if (stopSellTimeL.isBefore(nowTimeStrL)) { // 已结束
                performancesInfo.setAppStatus(10);
            } else { // 购买
                performancesInfo.setAppStatus(6);
            }
        }
        performancesInfo.setMessage(KylinPerformanceStatusEnum.getName(performancesInfo.getAppStatus()));

        // 处理距离
        String diffDistance = DistanceUtil.getDistance(longitudeFrom, latitudeFrom, Double.parseDouble(performancesInfo.getLongitude()), Double.parseDouble(performancesInfo.getLatitude()));
        performancesInfo.setDiffDistance(diffDistance);
        for (PerformanceVo road : roadList) {
            String diffDistanceRoad = DistanceUtil.getDistance(longitudeFrom, latitudeFrom, Double.parseDouble(performancesInfo.getLongitude()), Double.parseDouble(performancesInfo.getLatitude()));
            road.setDiffDistance(diffDistanceRoad);
        }

        info.put("performancesInfo", performancesInfo);
        info.put("roadList", roadList);

        return info;
    }

    public List<TicketTimesVo> ticketTimesPartner(String performancesId, Integer isAgent) {
        HashMap<String, Object> info = new HashMap<>();

        List<TicketTimesVo> ticketTimesList = mongoTemplate.find(
                Query.query(Criteria.where("performanceId").is(performancesId)),
                TicketTimesVo.class,
                TicketTimesVo.class.getSimpleName()
        );
        for (TicketTimesVo partner : ticketTimesList) {
            Query query = Query.query(Criteria.where("timeId").is(partner.getTimeId()));
            if (isAgent > 0) {
                query.addCriteria(Criteria.where("isAgent").is(isAgent));
            }
            List<TicketVo> ticketList = mongoTemplate.find(
                    query,
                    TicketVo.class,
                    TicketVo.class.getSimpleName()
            );

            for (TicketVo ticket : ticketList) {
                // 处理状态 购买 未开始 结束可更改   下架 售馨不可更改
                if (ticket.getStatus() == 6 || ticket.getStatus() == 9 || ticket.getStatus() == 10) {
                    String timeEnd = ticket.getTimeEnd();
                    String timeStart = ticket.getTimeStart();
                    DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                    LocalDateTime timeEndL = LocalDateTime.parse(timeEnd, df);
                    LocalDateTime timeStartL = LocalDateTime.parse(timeStart, df);

                    LocalDateTime nowTime = LocalDateTime.now();
                    String nowTimeStr = nowTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                    LocalDateTime nowTimeStrL = LocalDateTime.parse(nowTimeStr, df);

                    if (timeStartL.isAfter(nowTimeStrL)) {// 未开始
                        ticket.setStatus(9);
                    } else { // 购买
                        ticket.setStatus(6);
                    }
                    if (timeEndL.isBefore(nowTimeStrL)) { // 已结束
                        ticket.setStatus(10);
                    } else { // 购买
                        ticket.setStatus(6);
                    }
                }
                // 会员状态
                Integer isMemberStatus = 0;
                if (1 == ticket.getIsMember()) { // 有会员
                    String memberTimeStart = ticket.getMemberTimeStart();
                    DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                    LocalDateTime memberTimeStartL = LocalDateTime.parse(memberTimeStart, df);

                    LocalDateTime nowTimeTicket = LocalDateTime.now();
                    String nowTimeTicketStr = nowTimeTicket.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                    LocalDateTime nowTimeTicketStrL = LocalDateTime.parse(nowTimeTicketStr, df);
                    if (memberTimeStartL.isBefore(nowTimeTicketStrL)) { // 可以购买
                        isMemberStatus = 1;
                    } else { // 还没到会员购买时间
                        isMemberStatus = 0;
                    }
                } else {
                    isMemberStatus = 0;
                }
                ticket.setIsMemberStatus(isMemberStatus);
            }

            partner.setTicketList(ticketList);
        }

        return ticketTimesList;
    }

    public List<PerformanceVo> performanceList(String... performancesIds) {
        Query query = new Query();
        query.addCriteria(Criteria.where("performancesId").in(performancesIds));

        List<PerformanceVo> list = mongoTemplate.find(query, PerformanceVo.class, PerformanceVo.class.getSimpleName());

        return list;
    }

}
