package ink.wgink.gateway.handler.count;

import ink.wgink.gateway.consts.ISystemConst;
import ink.wgink.gateway.dao.log.IRequestLogDao;
import ink.wgink.gateway.dao.route.IRouteDao;
import ink.wgink.gateway.dao.routetype.IRouteTypeDao;
import ink.wgink.gateway.handler.BaseHandler;
import ink.wgink.gateway.pojo.count.HomeCount;
import ink.wgink.gateway.pojo.count.RequestLogLineChat;
import ink.wgink.gateway.pojo.log.RequestLog;
import ink.wgink.gateway.pojo.result.SuccessResultData;
import ink.wgink.gateway.util.DateUtil;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.ExampleMatcher;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.time.Duration;

/**
 * When you feel like quitting. Think about why you started
 * 当你想要放弃的时候，想想当初你为何开始
 *
 * @ClassName: CountHandler
 * @Description: 统计
 * @Author: wanggeng
 * @Date: 2021/5/15 3:01 下午
 * @Version: 1.0
 */
@Service
public class CountHandler extends BaseHandler {

    private IRouteTypeDao routeTypeDao;
    private IRouteDao routeDao;
    private IRequestLogDao requestLogDao;
    private MongoTemplate mongoTemplate;

    public CountHandler(IRouteTypeDao routeTypeDao, IRouteDao routeDao, IRequestLogDao requestLogDao, MongoTemplate mongoTemplate) {
        this.routeTypeDao = routeTypeDao;
        this.routeDao = routeDao;
        this.requestLogDao = requestLogDao;
        this.mongoTemplate = mongoTemplate;
    }

    /**
     * 所有路由类型
     *
     * @param serverResponse
     * @return
     */
    public Mono<ServerResponse> countHome(ServerRequest serverResponse) {
        return ServerResponse.ok().contentType(MediaType.TEXT_EVENT_STREAM).body(
                Flux.interval(Duration.ofSeconds(0), Duration.ofSeconds(15))
                        .flatMap(second -> {
                            Long routeTypeCount = mongoTemplate.count(new Query(), IRouteTypeDao.COLLECTION_NAME);
                            Long routeCount = mongoTemplate.count(new Query(), IRouteDao.COLLECTION_NAME);
                            Long requestCount = mongoTemplate.count(new Query(), IRequestLogDao.COLLECTION_NAME);
                            Long requestDayCount = mongoTemplate.count(Query.query(Criteria.where("gmtCreate").regex(DateUtil.getDay() +".*")), IRequestLogDao.COLLECTION_NAME);

                            HomeCount homeCount = new HomeCount();
                            homeCount.setRouteTypeCount(routeTypeCount);
                            homeCount.setRouteCount(routeCount);
                            homeCount.setRequestCount(requestCount);
                            homeCount.setRequestTodayCount(requestDayCount);
                            return Mono.just(homeCount);
                        }),
                HomeCount.class);
    }

    /**
     * 最新请求数量列表
     * 按分钟统计访问次数
     *
     * @param serverRequest
     * @return
     */
    public Mono<ServerResponse> listLastCount(ServerRequest serverRequest) {
        return ServerResponse.ok().contentType(MediaType.TEXT_EVENT_STREAM).body(
                Flux.interval(Duration.ofMinutes(0), Duration.ofSeconds(15)).flatMap(second ->
                        requestLogDao.count().flatMap(count -> {
                            DateTime nowDateTime = DateTime.now();
                            DateTime startDateTime = nowDateTime.minusMinutes(60);
                            String now = nowDateTime.toString(DateTimeFormat.forPattern(ISystemConst.DATE_YYYY_MM_DD_HH_MM));
                            String start = startDateTime.toString(DateTimeFormat.forPattern(ISystemConst.DATE_YYYY_MM_DD_HH_MM));
                            // 这个条件类似
                            // SELECT gmtCreate, count(gmtCreate) FROM log_request WHERE LEFT('gmtCreate', 16) >= '' and LEFT('gmtCreate', 16) <= '' GROUP BY gmtCreate
                            Aggregation aggregation = Aggregation.newAggregation(
                                    Aggregation.project().andExpression("{substr(gmtCreate,0,16)}").as("gmtMinute"),
                                    Aggregation.match(Criteria.where("gmtMinute").gte(start).lte(now)),
                                    Aggregation.group("gmtMinute").count().as("count"),
                                    Aggregation.sort(Sort.by("_id").ascending())
                            );
                            AggregationResults<RequestLogLineChat> aggregate = mongoTemplate.aggregate(aggregation, IRequestLogDao.COLLECTION_NAME, RequestLogLineChat.class);
                            return Mono.just(new SuccessResultData(aggregate.getMappedResults()));
                        })), SuccessResultData.class);
    }

}
