//package com.nantian.sc.cloud.common.gateway.filter;
//
//import com.alibaba.fastjson.JSON;
//import com.alibaba.fastjson.JSONObject;
//import com.nantian.sc.cloud.common.gateway.utils.AesUtil;
//import com.nantian.sc.cloud.common.gateway.utils.GatewayContext;
//import io.netty.buffer.ByteBufAllocator;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.cloud.gateway.filter.GatewayFilterChain;
//import org.springframework.cloud.gateway.filter.GlobalFilter;
//import org.springframework.cloud.gateway.filter.factory.rewrite.CachedBodyOutputMessage;
//import org.springframework.cloud.gateway.support.BodyInserterContext;
//import org.springframework.core.Ordered;
//import org.springframework.core.io.ByteArrayResource;
//import org.springframework.core.io.buffer.DataBuffer;
//import org.springframework.core.io.buffer.DataBufferUtils;
//import org.springframework.core.io.buffer.NettyDataBufferFactory;
//import org.springframework.http.HttpHeaders;
//import org.springframework.http.HttpMethod;
//import org.springframework.http.MediaType;
//import org.springframework.http.codec.ServerCodecConfigurer;
//import org.springframework.http.server.RequestPath;
//import org.springframework.http.server.reactive.ServerHttpRequest;
//import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
//import org.springframework.stereotype.Component;
//import org.springframework.util.MultiValueMap;
//import org.springframework.web.reactive.function.BodyInserter;
//import org.springframework.web.reactive.function.BodyInserters;
//import org.springframework.web.reactive.function.server.ServerRequest;
//import org.springframework.web.server.ServerWebExchange;
//import reactor.core.publisher.Flux;
//import reactor.core.publisher.Mono;
//
//import java.io.UnsupportedEncodingException;
//import java.net.URLEncoder;
//import java.nio.charset.Charset;
//import java.nio.charset.StandardCharsets;
//import java.util.List;
//import java.util.Map;
///**
// * @author hzp
// * @title: GlobalRequestBodyDecodeFilter
// * @projectName cloud2020
// * @description: TODO
// * @date 2022/09/01,0001下午 23:12
// */
//@Component
//public class GlobalRequestBodyDecodeFilter implements GlobalFilter, Ordered {
//
//    @Autowired
//    ServerCodecConfigurer codecConfigurer;
//
//    @Override
//    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//        ServerHttpRequest request = exchange.getRequest();
//
//        // TODO 如果请求的后台管理系统，则直接放行，不做加解密处理
//
//        if (request.getMethod() != HttpMethod.PATCH) {
//            // 如果不是post（新增）、put（全量修改）、patch（部分字段修改）操作，则直接放行
//            return chain.filter(exchange);
//        }
//        //如果是监察文件下载，直接放行
////        String path = request.getPath().toString();
////        if (path.contains("poi/")){
////            return chain.filter(exchange);
////        }
//        // 对增/改操作，实现入参解密操作
//        return operationExchange(exchange, chain);
//    }
//
//    @Override
//    public int getOrder() {
//        return -26;
//    }
//
//    private Mono<Void> operationExchange(ServerWebExchange exchange, GatewayFilterChain chain) {
//
//        // 缓存请求路径
//        ServerHttpRequest request = exchange.getRequest();
//        String path = request.getPath().pathWithinApplication().value();
//        GatewayContext gatewayContext = new GatewayContext();
//        gatewayContext.setPath(path);
//        // 保存网关上下文到exchange中
//        exchange.getAttributes().put(GatewayContext.CACHE_GATEWAY_CONTEXT, gatewayContext);
//
//        HttpHeaders headers = request.getHeaders();
//        MediaType contentType = headers.getContentType();
//
//        Mono<Void> voidMono = null;
//        if (MediaType.APPLICATION_JSON.equals(contentType) || MediaType.APPLICATION_JSON_UTF8.equals(contentType)) {
//            // 对applicationjson类型数据做解密操作
//            voidMono = readBody(exchange, chain);
//        }
//        if (MediaType.APPLICATION_FORM_URLENCODED.equals(contentType)
//                || (contentType != null && contentType.toString().startsWith(MediaType.MULTIPART_FORM_DATA_VALUE)) ) {
//            // form data
//            voidMono = readFormData(exchange, chain, gatewayContext);
//        }
//        if(voidMono == null){
//            voidMono = chain.filter(exchange);
//        }
//        return voidMono;
//    }
//
//    private Mono<Void> readFormData(
//            ServerWebExchange exchange,
//            GatewayFilterChain chain,
//            GatewayContext gatewayContext) {
//        final ServerHttpRequest request = exchange.getRequest();
//        HttpHeaders headers = request.getHeaders();
//
//        return exchange.getFormData()
//                .doOnNext(multiValueMap -> {
//                    gatewayContext.setFormData(multiValueMap);
//                })
//                .then(Mono.defer(() -> {
//                    Charset charset = headers.getContentType().getCharset();
//                    charset = charset == null ? StandardCharsets.UTF_8 : charset;
//                    String charsetName = charset.name();
//                    MultiValueMap<String, String> formData =
//                            gatewayContext.getFormData();
//                    /** formData is empty just return */
//                    if (null == formData || formData.isEmpty()) {
//                        return chain.filter(exchange);
//                    }
//                    StringBuilder formDataBodyBuilder = new StringBuilder();
//                    String entryKey;
//                    List<String> entryValue;
//                    try {
//                        /* repackage form data */
//                        for (Map.Entry<String, List<String>> entry : formData
//                                .entrySet()) {
//                            entryKey = entry.getKey();
//                            entryValue = entry.getValue();
//                            if (entryValue.size() > 1) {
//                                for (String value : entryValue) {
//                                    formDataBodyBuilder.append(entryKey).append("=")
//                                            .append(
//                                                    URLEncoder.encode(value, charsetName))
//                                            .append("&");
//                                }
//                            } else {
////                                formDataBodyBuilder
////                                        .append(entryKey);
//                                formDataBodyBuilder
//                                        .append(entryKey).append("=")
//                                        .append(URLEncoder.encode(entryValue.get(0), charsetName))
//                                        .append("&");
//                            }
//                        }
//                    } catch (UnsupportedEncodingException e) {
//                        // ignore URLEncode Exception
//                    } catch (Exception e) {
//                        e.printStackTrace();
//                    }
//                    /* substring with the last char '&' */
//                    String formDataBodyString = "";
//                    if (formDataBodyBuilder.length() > 0) {
//                        formDataBodyString = formDataBodyBuilder.substring(0,
//                                formDataBodyBuilder.length() - 1);
//                    }
//                    String newBody = "";
//                    try {
////                        newBody = decodeBody(formDataBodyString);
//                    } catch (Exception e) {
//                        e.printStackTrace();
//                    }
//                    // date data bytes
//                    byte[] bodyBytes = formDataBodyString.getBytes(charset);
//                    int contentLength = bodyBytes.length;
//                    ServerHttpRequestDecorator decorator =
//                            new ServerHttpRequestDecorator(
//                                    request) {
//
//                                @Override
//                                public HttpHeaders getHeaders() {
//                                    HttpHeaders httpHeaders = new HttpHeaders();
//                                    httpHeaders.putAll(super.getHeaders());
//                                    if (contentLength > 0) {
//                                        httpHeaders.setContentLength(contentLength);
//                                    } else {
//                                        httpHeaders.set(HttpHeaders.TRANSFER_ENCODING,
//                                                "chunked");
//                                    }
//                                    return httpHeaders;
//                                }
//
//                                @Override
//                                public Flux<DataBuffer> getBody() {
//                                    return DataBufferUtils
//                                            .read(new ByteArrayResource(bodyBytes),
//                                                    new NettyDataBufferFactory(
//                                                            ByteBufAllocator.DEFAULT),
//                                                    contentLength);
//                                }
//                            };
//                    ServerWebExchange mutateExchange =
//                            exchange.mutate().request(decorator).build();
//                /*   log.info("[GatewayContext]Rewrite Form Data :{}",
//                       formDataBodyString);*/
//
//                    return chain.filter(mutateExchange);
//                }));
//    }
//
//    private Mono<Void> readBody(ServerWebExchange exchange, GatewayFilterChain chain) {
//        final ServerHttpRequest request = exchange.getRequest();
//        MediaType mediaType = request.getHeaders().getContentType();
//        // 修改响应体
////        ServerRequest serverRequest = new DefaultServerRequest(exchange);
//        ServerRequest serverRequest = ServerRequest.create(exchange, codecConfigurer.getReaders());
//        Mono<String> modifiedBody = serverRequest.bodyToMono(String.class)
//                .flatMap(body -> {
//				if (MediaType.APPLICATION_JSON.isCompatibleWith(mediaType)) {
//					// 拿到公钥加密后的数据
//                    try {
//                        JSONObject bodyObj = JSON.parseObject(body);
//                        return Mono.just(decodeBody(bodyObj.getString("encryptBody")));
//                    } catch (Exception e) {
//                        e.printStackTrace();
//                    }
//                }
//				return Mono.empty();
//                });
//        BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, String.class);
//        HttpHeaders headers = new HttpHeaders();
//        headers.putAll(request.getHeaders());
//        headers.remove(HttpHeaders.CONTENT_LENGTH);
//        //创建CachedBodyOutputMessage并且把请求param加入
//        CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(exchange, headers);
//        return bodyInserter.insert(outputMessage, new BodyInserterContext())
//                .then(Mono.defer(() -> {
//                    ServerHttpRequestDecorator decorator = new ServerHttpRequestDecorator(
//                            request) {
//                        @Override
//                        public HttpHeaders getHeaders() {
//                            long contentLength = headers.getContentLength();
//                            HttpHeaders httpHeaders = new HttpHeaders();
//                            httpHeaders.putAll(super.getHeaders());
//                            if (contentLength > 0) {
//                                httpHeaders.setContentLength(contentLength);
//                            } else {
//                                httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked");
//                            }
//                            return httpHeaders;
//                        }
//
//                        @Override
//                        public Flux<DataBuffer> getBody() {
//                            return outputMessage.getBody();
//                        }
//                    };
//                    return chain.filter(exchange.mutate().request(decorator).build());
//                }));
//    }
//
//    private String decodeBody(String body) throws Exception {
//        String decoded = AesUtil.decrypt(body, "MP5v0^zee5Qlgq5V");
//        return decoded;
//    }
//}
