package ink.wgink.gateway.handler.routetype;

import ink.wgink.gateway.dao.routetype.IRouteTypeDao;
import ink.wgink.gateway.exception.SearchException;
import ink.wgink.gateway.handler.BaseHandler;
import ink.wgink.gateway.pojo.result.SuccessResult;
import ink.wgink.gateway.pojo.routetype.RouteType;
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: RouteTypeHandler
 * @Description: 路由类型
 * @Author: WangGeng
 * @Date: 2021/5/8 12:09
 * @Version: 1.0
 **/
@Service
public class RouteTypeHandler extends BaseHandler {

    private IRouteTypeDao routeTypeDao;

    public RouteTypeHandler(IRouteTypeDao routeTypeDao) {
        this.routeTypeDao = routeTypeDao;
    }

    /**
     * 保存
     *
     * @param serverRequest
     * @return
     */
    public Mono<ServerResponse> save(ServerRequest serverRequest) {
        Mono<RouteType> routeTypeMono = serverRequest.bodyToMono(RouteType.class);
        return routeTypeMono.flatMap(routeType -> {
            RequestFieldCheckUtil.check(routeType);
            setSave(routeType);

            RouteType routeTypeExample = new RouteType();
            routeTypeExample.setTitle(routeType.getTitle().trim());
            ExampleMatcher exampleMatcher = ExampleMatcher.matching().withMatcher("title", ExampleMatcher.GenericPropertyMatcher::exact).withIgnoreCase("id");
            Example example = Example.of(routeTypeExample, exampleMatcher);
            return routeTypeDao.findOne(example).flatMap(
                    r -> Mono.error(new SearchException("类型已经存在"))
            ).switchIfEmpty(routeTypeDao.save(routeType));
        }).then(ServerResponse.ok().contentType(MediaType.APPLICATION_JSON_UTF8).body(Flux.just(new SuccessResult()), SuccessResult.class));
    }

    /**
     * 删除
     *
     * @param serverRequest
     * @return
     */
    public Mono<ServerResponse> delete(ServerRequest serverRequest) {
        String ids = serverRequest.pathVariable("ids");
        List<String> idList = Arrays.asList(ids.split(","));
        return routeTypeDao.findAllById(idList).flatMap(route -> routeTypeDao.delete(route)).then(ServerResponse.ok().contentType(MediaType.APPLICATION_JSON_UTF8).body(Mono.just(new SuccessResult()), SuccessResult.class));
    }

    /**
     * 修改
     *
     * @param serverRequest
     * @return
     */
    public Mono<ServerResponse> update(ServerRequest serverRequest) {
        String id = serverRequest.pathVariable("id");
        Mono<RouteType> routeTypeMono = serverRequest.bodyToMono(RouteType.class);

        // 查询ID是否存在
        return routeTypeDao.findById(id).flatMap(routeType -> {
            setUpdate(routeType);
            return routeTypeMono.flatMap(rt -> {
                RequestFieldCheckUtil.check(rt);
                routeType.setTitle(rt.getTitle());
                routeType.setSummary(rt.getSummary());

                RouteType routeTypeExample = new RouteType();
                routeTypeExample.setTitle(rt.getTitle());
                ExampleMatcher exampleMatcher = ExampleMatcher.matching()
                        .withMatcher("title", ExampleMatcher.GenericPropertyMatcher::exact)
                        .withIgnoreCase("id");
                Example example = Example.of(routeTypeExample, exampleMatcher);
                // 查询title是否存在
                return routeTypeDao.findOne(example).flatMap(ert -> {
                    RouteType existRouteType = (RouteType) ert;
                    // 如果已经存在
                    if (!StringUtils.equals(existRouteType.getUuid(), id)) {
                        return Mono.error(new SearchException("类型已经存在"));
                    }
                    return routeTypeDao.save(routeType);
                }).switchIfEmpty(routeTypeDao.save(routeType));
            });
        }).switchIfEmpty(ServerResponse.notFound().build()).then(ServerResponse.ok().contentType(MediaType.APPLICATION_JSON_UTF8).body(Mono.just(new SuccessResult()), SuccessResult.class));
    }

    /**
     * 列表
     *
     * @param serverRequest
     * @return
     */
    public Mono<ServerResponse> list(ServerRequest serverRequest) {
        Optional<String> keywords = serverRequest.queryParam("keywords");

        RouteType routeType = new RouteType();
        Example example = Example.of(routeType);
        if (keywords.isPresent()) {
            String keywordTrim = keywords.get().trim();
            routeType.setTitle(keywordTrim);
            routeType.setSummary(keywordTrim);

            ExampleMatcher exampleMatcher = ExampleMatcher.matchingAny()
                    .withMatcher("title", ExampleMatcher.GenericPropertyMatcher::contains)
                    .withMatcher("summary", ExampleMatcher.GenericPropertyMatcher::contains)
                    .withIgnoreCase("id", "summary");
            example = Example.of(routeType, exampleMatcher);
        }
        return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON_UTF8).body(routeTypeDao.findAll(example), RouteType.class);
    }

    /**
     * 详情
     *
     * @param serverRequest
     * @return
     */
    public Mono<ServerResponse> get(ServerRequest serverRequest) {
        String id = serverRequest.pathVariable("id");
        return routeTypeDao.findById(id).flatMap(
                routeType -> ServerResponse.ok().body(Mono.just(routeType), RouteType.class)
        ).switchIfEmpty(ServerResponse.notFound().build());
    }
}
