package com.bohuikeji.frame.module.admin.service.impl;

import com.bohuikeji.frame.module.admin.service.IRoutingDelegate;
import com.bohuikeji.frame.module.admin.utils.StringUtils;
import jodd.http.HttpRequest;
import jodd.http.HttpResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.StreamUtils;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;

/**
 * 反向代理实现类
 * @author 孙劲辉
 */
@Slf4j
@Service
public class RoutingDelegate implements IRoutingDelegate {
    @Override
    public ResponseEntity<String> redirect(HttpServletRequest request,String url) {
        String contentType=request.getContentType();
        if (StringUtils.isBlank(contentType)){
            contentType="text/html";
        }
        try {
            HttpRequest req=HttpRequest.connect(url)
                    .body(parseRequestBody(request),contentType)
                    .method(request.getMethod())
                    .header(parseRequestHeader(request));
            //取消压缩，取消HOst头
            req.headerRemove("Accept-Encoding");
            req.headerRemove("Host");
            return convertToResponse(req.send());
        } catch (IOException e) {
            log.error("代理请求错误：",e);
            e.printStackTrace();
        }
        return new ResponseEntity<String>("REDIRECT ERROR", HttpStatus.INTERNAL_SERVER_ERROR);
    }

    /**
     * 转换jodd.http.HttpResponse 为 org.springframework.http.ResponseEntity
     * @param res
     * @return
     */
    private ResponseEntity<String> convertToResponse(HttpResponse res){
        return ResponseEntity.status(res.statusCode())
                .headers(parseResponseHeader(res)).body(res.bodyText());
    }

    /**
     * 读取 HttpServletRequest请求体BODY
     * @param request
     * @return
     * @throws IOException
     */
    private byte[] parseRequestBody(HttpServletRequest request) throws IOException {
        InputStream inputStream = request.getInputStream();
        return StreamUtils.copyToByteArray(inputStream);
    }

    /**
     * 读取HttpServletRequest中的header到map
     * @param request
     * @return
     */
    private Map<String,String> parseRequestHeader(HttpServletRequest request){
        List<String> headerNames = Collections.list(request.getHeaderNames());
        Map<String,String> headerMap=new HashMap<>(headerNames.size());
        for (String headerName : headerNames) {
            headerMap.put(headerName,request.getHeader(headerName));
        }
        return headerMap;
    }

    /**
     * 读取HttpResponse 中的Header到HttpHeaders
     * @param response
     * @return
     */
    private HttpHeaders parseResponseHeader(HttpResponse response) {
        HttpHeaders headers = new HttpHeaders();
        Collection<String> headerNames = response.headerNames();
        for (String headerName : headerNames) {
            List<String> headerValues = response.headers(headerName);
            for (String headerValue : headerValues) {
                headers.add(headerName, headerValue);
            }
        }
        return headers;
    }
}
