package ink.wgink.gateway.handler.route.request;

import ink.wgink.gateway.dao.route.request.IRequestParameterDao;
import ink.wgink.gateway.enums.FilterRequestResponseTypeEnum;
import ink.wgink.gateway.exception.ParamsException;
import ink.wgink.gateway.exception.SearchException;
import ink.wgink.gateway.handler.BaseHandler;
import ink.wgink.gateway.pojo.result.SuccessResult;
import ink.wgink.gateway.pojo.route.request.RequestParameter;
import ink.wgink.gateway.util.RequestFieldCheckUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.ExampleMatcher;
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.util.Arrays;
import java.util.List;
import java.util.Optional;

/**
 * When you feel like quitting. Think about why you started
 * 当你想要放弃的时候，想想当初你为何开始
 *
 * @ClassName: RequestParameterHeader
 * @Description: 请求参数
 * @Author: WangGeng
 * @Date: 2021/5/30 17:00
 * @Version: 1.0
 **/
@Service
public class RequestParameterHandler extends BaseHandler {

    private IRequestParameterDao requestParameterDao;

    public RequestParameterHandler(IRequestParameterDao requestParameterDao) {
        this.requestParameterDao = requestParameterDao;
    }

    public Mono<ServerResponse> save(ServerRequest serverRequest) {
        Mono<RequestParameter> requestParameterMono = serverRequest.bodyToMono(RequestParameter.class);
        return requestParameterMono.flatMap(requestParameter -> {
            RequestFieldCheckUtil.check(requestParameter);
            if (!StringUtils.equals(FilterRequestResponseTypeEnum.REMOVE.getValue(), requestParameter.getType()) && StringUtils.isBlank(requestParameter.getValue())) {
                return Mono.error(new ParamsException("值不能为空"));
            }
            setSave(requestParameter);

            RequestParameter requestParameterExample = new RequestParameter();
            requestParameterExample.setName(requestParameter.getName().trim());
            ExampleMatcher exampleMatcher = ExampleMatcher.matching().withMatcher("name", ExampleMatcher.GenericPropertyMatcher::exact).withIgnoreCase("id");
            Example example = Example.of(requestParameterExample, exampleMatcher);
            return requestParameterDao.findOne(example).flatMap(
                    r -> Mono.error(new SearchException("参数已经存在"))
            ).switchIfEmpty(requestParameterDao.save(requestParameter));
        }).then(ServerResponse.ok().contentType(MediaType.APPLICATION_JSON_UTF8).body(Flux.just(new SuccessResult()), SuccessResult.class));
    }

    public Mono<ServerResponse> delete(ServerRequest serverRequest) {
        String ids = serverRequest.pathVariable("ids");
        List<String> idList = Arrays.asList(ids.split(","));
        return requestParameterDao.findAllById(idList).flatMap(requestParameter -> requestParameterDao.delete(requestParameter)).then(ServerResponse.ok().contentType(MediaType.APPLICATION_JSON_UTF8).body(Mono.just(new SuccessResult()), SuccessResult.class));
    }

    public Mono<ServerResponse> list(ServerRequest serverRequest) {
        String routeId = serverRequest.pathVariable("routeId");
        Optional<String> keywords = serverRequest.queryParam("keywords");
        Optional<String> type = serverRequest.queryParam("type");

        RequestParameter requestParameterExample = new RequestParameter();
        requestParameterExample.setRouteId(routeId);
        ExampleMatcher exampleMatcher = ExampleMatcher.matching()
                .withMatcher("routeId", ExampleMatcher.GenericPropertyMatcher::exact)
                .withIgnoreCase("id");
        if (keywords.isPresent()) {
            requestParameterExample.setName(keywords.get().trim());
            exampleMatcher.withMatcher("name", ExampleMatcher.GenericPropertyMatcher::contains);
        }
        if (type.isPresent()) {
            requestParameterExample.setType(type.get().trim());
            exampleMatcher.withMatcher("type", ExampleMatcher.GenericPropertyMatcher::exact);
        }
        Example example = Example.of(requestParameterExample, exampleMatcher);
        return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON_UTF8).body(requestParameterDao.findAll(example), RequestParameter.class);
    }

    public Mono<ServerResponse> get(ServerRequest serverRequest) {
        String id = serverRequest.pathVariable("id");
        return requestParameterDao.findById(id).flatMap(
                requestParameter -> ServerResponse.ok().body(Mono.just(requestParameter), RequestParameter.class)
        ).switchIfEmpty(ServerResponse.notFound().build());
    }

}
