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

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.liquidnet.commons.lang.CommonConst;
import com.liquidnet.commons.lang.util.DateUtil;
import com.liquidnet.commons.lang.util.DistanceUtil;
import com.liquidnet.service.kylin.constant.KylinPerformanceStatusEnum;
import com.liquidnet.service.kylin.dao.PerformanceOrderStatisticalDao;
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.returns.PayDetailVo;
import com.liquidnet.service.kylin.entity.KylinPerformances;
import com.liquidnet.service.kylin.mapper.KylinPerformancesMapper;
import com.liquidnet.service.kylin.service.IKylinPerformancesService;
import com.liquidnet.service.kylin.timerTask.PerformanceVoTask;
import com.liquidnet.service.kylin.utils.DataUtils;
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 org.springframework.util.CollectionUtils;

import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

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

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private DataUtils dataUtils;

    @Autowired
    private PerformanceVoTask task;

    @Autowired
    private KylinPerformancesMapper performancesMapper;

    public HashMap<String, Object> localList(
            int days, String cityName, int type,
            Integer isDiscount, Integer isAdvance, Integer isExclusive,
            String orderBy, String sort
    ) {
        List<KylinPerformanceVo> performancesList = dataUtils.getPerformancesListOfcityName(cityName);

        // 判断搜索 处理新数据
        List<KylinPerformanceVo> performancesListNew = new ArrayList<>();
        List<String> performancesIds = new ArrayList<>();
        for (KylinPerformanceVo info : performancesList) {
            boolean isShow = true;
            if (type > 0) {
                if (info.getType() != type) {
                    isShow = false;
                }
            }
            if (null != isExclusive || null != isDiscount || null != isAdvance) {
                if (info.getIsExclusive() != isExclusive && info.getIsDiscount() != isDiscount && info.getIsAdvance() != isAdvance) {
                    isShow = false;
                }
            }
            if (isShow) {
                performancesIds.add(info.getPerformancesId());
                performancesListNew.add(info);
            }
        }


        // 推荐
        int is_native = 1;
        int recommend = performancesListNew.size();
        if (recommend <= 2) {
            List<KylinPerformanceVo> performancesListRecommend = dataUtils.getPerformancesListIsSystemRecommend();

            if (!CollectionUtils.isEmpty(performancesListRecommend)) {
                is_native = 0;
                if (recommend > 0) {// 去重
                    List<KylinPerformanceVo> collect = performancesListRecommend.stream().filter(r -> !performancesIds.contains(r.getPerformancesId())).collect(Collectors.toList());
                    performancesListNew.addAll(collect);
                } else {
                    performancesListNew.addAll(performancesListRecommend);
                }
            }
        }
        performancesListNew = checkAppStatus(performancesListNew);

        // 组合数据
        HashMap<String, Object> info = new HashMap<>();
        info.put("is_native", is_native); // 本地演出少是否推荐了其他演出 0有推荐 1没有
        info.put("recommend", recommend); // 从第几个开始是其他推荐演出 后台设置的那个推荐
        info.put("total", 0);
        info.put("list", performancesListNew);

        return info;
    }

    public HashMap<String, Object> noticeList() {
        /*if (-1 != DateUtil.compareStrDay(timeStart, toDayEndTimeStr) && -1 == DateUtil.compareStrDay(timeStart, threeDaysLaterStr)) {
            threeDaysList.add(info);
        }*/
        HashMap<String, Object> performancesListNotice = dataUtils.getPerformancesListNotice();
        List<KylinPerformanceVo> toDayList = (List<KylinPerformanceVo>) performancesListNotice.get("toDayList");
        List<KylinPerformanceVo> threeDaysList = (List<KylinPerformanceVo>) performancesListNotice.get("threeDaysList");

        toDayList = checkAppStatus(toDayList);
        threeDaysList = checkAppStatus(threeDaysList);

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

    public List<KylinPerformanceVo> recommendList() {
        List<KylinPerformanceVo> performancesListRecommend = dataUtils.getPerformancesListIsRecommend();
        performancesListRecommend = checkAppStatus(performancesListRecommend);
        return performancesListRecommend;
    }

    public List<KylinPerformanceVo> exclusiveList() {
        List<KylinPerformanceVo> performancesListExclusive = dataUtils.getPerformancesListIsExclusive();
        performancesListExclusive = checkAppStatus(performancesListExclusive);
        return performancesListExclusive;
    }

    public KylinPerformanceVo detail(String performancesId, double latitudeFrom, double longitudeFrom) {

        KylinPerformanceVo performancesInfo = dataUtils.getPerformanceVo(performancesId);

        performancesInfo = checkAppStatus(performancesInfo);

        performancesInfo.setMessage(KylinPerformanceStatusEnum.getName(performancesInfo.getAppStatus()));

        // 处理距离
        if (longitudeFrom != CommonConst.DFT_DOUBLE_VAL) {
            String diffDistance = DistanceUtil.getDistance(longitudeFrom, latitudeFrom, Double.parseDouble(performancesInfo.getLongitude()), Double.parseDouble(performancesInfo.getLatitude()));
            performancesInfo.setDiffDistance(diffDistance);
        }

        return performancesInfo;
    }

    public List<KylinPerformanceVo> roadList(String roadShowId) {
        List<KylinPerformanceVo> performancesList = dataUtils.getRoadList(roadShowId);
        performancesList = checkAppStatus(performancesList);
        return performancesList;
    }

    public HashMap<String, Object> ticketTimesPartner(String performancesId, Integer isAgent) {
        KylinPerformanceVo vo = dataUtils.getPerformanceVo(performancesId);

        List<KylinTicketTimesVo> ticketTimesList = vo.getTicketTimeList();
        for (KylinTicketTimesVo partner : ticketTimesList) {
            List<KylinTicketVo> ticketList = partner.getTicketList();
            for (KylinTicketVo ticket : ticketList) {
                int status = checkTicketStatus(ticket);
                ticket.setStatus(status);
                // 会员状态
                Integer isMemberStatus = getIsMemberStatus(ticket);
                ticket.setIsMemberStatus(isMemberStatus);
            }
            partner.setTicketList(ticketList);
        }

        KylinPerformanceVo performancesInfo = dataUtils.getPerformanceVo(performancesId);
        HashMap<String, Object> info = new HashMap();
        info.put("city_name", performancesInfo.getCityName());
        info.put("field_name", performancesInfo.getFieldName());
        info.put("title", performancesInfo.getTitle());

        HashMap result = new HashMap();
        result.put("performancesInfo", info);
        result.put("ticketTimesList", ticketTimesList);

        return result;
    }

    public List<KylinPerformanceVo> performanceList(String... performancesIds) {
        List<KylinPerformanceVo> performanceList = new ArrayList<>();
        for (String id : performancesIds) {
            KylinPerformanceVo info = dataUtils.getPerformanceVo(id);
            performanceList.add(info);
        }
        performanceList = checkAppStatus(performanceList);
        return performanceList;
    }

    public List performanceCalendar(String yearMonth, String cityName) {
        List<KylinPerformanceVo> performancesList = dataUtils.getPerformancesListOfcityName(cityName);

        // 获取此月开始结束时间
        String monthStart = DateUtil.getMonthFirst(yearMonth);
        String monthEnd = "";
        monthEnd = DateUtil.getMonthLast(monthStart);

        List date = new ArrayList();
        for (KylinPerformanceVo info : performancesList) {
            String timeStart = info.getTimeStart();
            if (-1 != DateUtil.compareStrDay(timeStart, monthStart) && 1 != DateUtil.compareStrDay(timeStart, monthEnd)) {
                String[] timeStartArr = timeStart.split(" ");
                date.add(timeStartArr[0]);
            }
        }
        //  去重
        List newList = (List) date.stream().distinct().collect(Collectors.toList());

        return newList;
    }

    public List calendarPerformances(String yearMonthDay, String cityName) {
        List<KylinPerformanceVo> performancesList = dataUtils.getPerformancesListOfcityName(cityName);

        String yearMonthDayStart = yearMonthDay.concat(" 00:00:00");
        String yearMonthDayEnd = yearMonthDay.concat(" 23:59:59");

        List<KylinPerformanceVo> performancesListNew = new ArrayList();
        for (KylinPerformanceVo info : performancesList) {
            String timeStart = info.getTimeStart();
            if (-1 != DateUtil.compareStrDay(timeStart, yearMonthDayStart) && 1 != DateUtil.compareStrDay(timeStart, yearMonthDayEnd)) {
                performancesListNew.add(info);
            }
        }

        performancesListNew = checkAppStatus(performancesListNew);

        return performancesListNew;
    }

    public HashMap performancesSearch(String title, int page, int size) {
        Document queryObject = new Document();
        queryObject.put("title", Pattern.compile(title, Pattern.CASE_INSENSITIVE));
        Query query = new BasicQuery(queryObject);
        String nowTimeStr = DateUtil.getNowTime();
        query.addCriteria(Criteria.where("timeEnd").gte(nowTimeStr));
        query.addCriteria(Criteria.where("appStatus").in(3, 6, 8, 9));

        long count = mongoTemplate.count(query, KylinPerformanceVo.class, KylinPerformanceVo.class.getSimpleName());

        query.fields().exclude("details");
        query.fields().exclude("noticeImage");
        query.fields().exclude("ticketTimeList");

        Sort sortName = Sort.by(Sort.Direction.ASC, "timeStart");
        Pageable pageable = PageRequest.of(page - 1, size, sortName);
        query.with(pageable);

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

        list = checkAppStatus(list);

        HashMap info = new HashMap();
        info.put("total", count);
        info.put("list", list);

        return info;
    }

    public PayDetailVo payDetail(String performancesId, String ticketsId) {
        KylinTicketVo ticketVo = null;
        KylinPerformanceVo performancesInfo = dataUtils.getPerformanceVo(performancesId);
        for (int i = 0; i < performancesInfo.getTicketTimeList().size(); i++) {
            for (int x = 0; x < performancesInfo.getTicketTimeList().get(i).getTicketList().size(); x++) {
                KylinTicketVo ticketItem = performancesInfo.getTicketTimeList().get(i).getTicketList().get(x);
                if (ticketItem.getTicketsId().equals(ticketsId)) {
                    int status = checkTicketStatus(ticketItem);
                    ticketItem.setStatus(status);
                    ticketVo = ticketItem;
                    Integer isMemberStatus = getIsMemberStatus(ticketItem);
                    ticketItem.setIsMemberStatus(isMemberStatus);
                }
            }
        }

        performancesInfo = checkAppStatus(performancesInfo);

        performancesInfo.setMessage(KylinPerformanceStatusEnum.getName(performancesInfo.getAppStatus()));

        PayDetailVo payDetailVo = new PayDetailVo();
        payDetailVo.setPerformanceInfo(performancesInfo);
        payDetailVo.setTicketInfo(ticketVo);
        return payDetailVo;
    }

    public List<KylinPerformanceVo> checkAppStatus(List<KylinPerformanceVo> list) {
        if (!CollectionUtils.isEmpty(list)) {
            String nowTimeStr = DateUtil.getNowTime();
            for (KylinPerformanceVo info : list) {
                String timeStart = info.getSellTime();
                String timeEnd = info.getStopSellTime();

                if (info.getAppStatus() != 8) {
                    if (1 == DateUtil.compareStrDay(timeStart, nowTimeStr)) {// 未开始
                        info.setAppStatus(9);
                    } else { // 已开始
                        info.setAppStatus(6);
                        if (1 == DateUtil.compareStrDay(nowTimeStr, timeEnd)) { // 已结束
                            info.setAppStatus(10);
                        }
                    }
                }
            }
        }
        return list;
    }

    public KylinPerformanceVo checkAppStatus(KylinPerformanceVo info) {
        if (null != info) {
            String nowTimeStr = DateUtil.getNowTime();
            String timeStart = info.getSellTime();
            String timeEnd = info.getStopSellTime();

            if (info.getAppStatus() != 8) {
                if (1 == DateUtil.compareStrDay(timeStart, nowTimeStr)) {// 未开始
                    info.setAppStatus(9);
                } else { // 已开始
                    info.setAppStatus(6);
                    if (1 == DateUtil.compareStrDay(nowTimeStr, timeEnd)) { // 已结束
                        info.setAppStatus(10);
                    }
                }
            }
        }
        return info;
    }

    public int checkTicketStatus(KylinTicketVo ticketItem) {
        int status = 0;
        int getStatus = ticketItem.getStatus();
        if (null != ticketItem) {
            if (6 == getStatus || 9 == getStatus || 10 == getStatus) {
                String timeStart = ticketItem.getTimeStart();
                String timeEnd = ticketItem.getTimeEnd();
                String nowTime = DateUtil.getNowTime();

                if (1 == DateUtil.compareStrDay(timeStart, nowTime)) {// 未开始
                    status = 9;
                } else { // 已开始
                    status = 6;
                    if (1 == DateUtil.compareStrDay(nowTime, timeEnd)) { // 已结束
                        status = 10;
                    }
                }
            }
        }
        return status;
    }

    public Integer getIsMemberStatus(KylinTicketVo ticket) {// 会员状态
        Integer isMemberStatus = 0;
        if (null != ticket) {
            if (1 == ticket.getIsMember()) { // 有会员
                String memberTimeStart = ticket.getMemberTimeStart();
                String nowTime = DateUtil.getNowTime();
                if (1 == DateUtil.compareStrDay(memberTimeStart, nowTime)) { // 还没到会员购买时间
                    isMemberStatus = 0;
                } else { // 可以购买
                    isMemberStatus = 1;
                }
            } else {
                isMemberStatus = 0;
            }
        }
        return isMemberStatus;
    }

    public String checkPerformanceTime(String performancesId) {
        try {
            task.performanceVoStatus(performancesId);
            return "成功";
        } catch (Exception e) {
            e.printStackTrace();
            return "失败";
        }
    }
}
