package com.lightinit.hsdatagateway.modules.foreign.web;

import com.lightinit.hsdatagateway.common.exceptions.BaseException;
import com.lightinit.hsdatagateway.common.exceptions.RequestParamException;
import com.lightinit.hsdatagateway.modules.foreign.enums.HttpMethodEnum;
import com.lightinit.hsdatagateway.modules.foreign.exe.ServiceExe;
import com.lightinit.hsdatagateway.modules.foreign.model.RequestDto;
import com.lightinit.hsdatagateway.modules.foreign.model.ResponseModel;
import com.lightinit.hsdatagateway.modules.foreign.util.ApiEncryptUtil;
import com.lightinit.hsdatagateway.modules.foreign.util.HttpUtil;
import com.lightinit.hsdatagateway.modules.gateway.entity.BizSign;
import com.lightinit.hsdatagateway.modules.gateway.service.BizSignService;
import com.lightinit.hsdatagateway.modules.foreign.enums.HttpMethodEnum;
import com.lightinit.hsdatagateway.modules.foreign.model.RequestDto;
import com.lightinit.hsdatagateway.modules.foreign.model.ResponseModel;
import com.lightinit.hsdatagateway.modules.foreign.util.ApiEncryptUtil;
import com.lightinit.hsdatagateway.modules.foreign.util.HttpUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;

/**
 * @Author: yangrui
 * @Date: 2019/3/5 12:10
 */
@Slf4j
@Controller
@RequestMapping(value = "foreign", headers = "version=1.0")
public class ForeignWebController {
    @Autowired
    ServiceExe serviceExe;
    @Autowired
    BizSignService bizSignService;


    /**
     * 业务api调用
     *
     * @param request
     * @return
     */
    @RequestMapping(value = "search/**", method = {RequestMethod.GET, RequestMethod.DELETE, RequestMethod.POST, RequestMethod.PUT})
    public void searchGet(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String path = request.getRequestURI().substring(request.getContextPath().length() + 15);
        String method = request.getMethod();
        RequestDto requestDto = new RequestDto();
        String contentType = request.getContentType();
        if ((HttpMethodEnum.POST.method.equalsIgnoreCase(method) || HttpMethodEnum.PUT.method.equalsIgnoreCase(method)) && !HttpUtil.verifyIsFormData(contentType)) {
            try {
                getParameterMap(request);
                String body = IOUtils.toString(request.getInputStream(), "utf-8");
                String queryString = request.getQueryString();
                requestDto.setBody(body);
            } catch (IOException e) {
                throw new BaseException("获取请求体异常", "500");
            }
        } else {
            Map<String, String> parameterMap = getParameterMap(request);
            requestDto.setParam(parameterMap);
        }
        verifyIsBlank(path, requestDto, request);
        ResponseModel responseModel = serviceExe.execute(requestDto);
        response.setContentType(responseModel.getContentType());
        response.setCharacterEncoding("utf-8");
        response.setStatus(responseModel.getCode());
        try (ServletOutputStream outputStream = response.getOutputStream();) {
            IOUtils.write(responseModel.getBody(), outputStream, "utf-8");
        } catch (IOException e) {
            throw new BaseException("获得响应流异常", "500");
        }
//        return new ReturnResult<>(responseModel);
    }


    /**
     * 从request中获得参数Map，并返回可读的Map
     *
     * @param request
     * @return
     */
    private static Map<String, String> getParameterMap(HttpServletRequest request) {
        // 参数Map
        Map properties = request.getParameterMap();
        // 返回值Map
        Map<String, String> returnMap = new HashMap<>();
        Iterator entries = properties.entrySet().iterator();
        while (entries.hasNext()) {
            Map.Entry entry = (Map.Entry) entries.next();
            String name = String.valueOf(entry.getKey());
            Object value = entry.getValue();
            String buildValue = "";
            if (Objects.isNull(value)) {
                buildValue = "";
            } else if (value instanceof String[]) {
                String[] strings = (String[]) value;
                buildValue = StringUtils.join(strings, ",");
            } else {
                buildValue = String.valueOf(value);
            }
            returnMap.put(name, buildValue);
        }
        return returnMap;
    }

    /**
     * 验证参数
     *
     * @param path
     * @param requestDto
     * @param request
     */
    private void verifyIsBlank(String path, RequestDto requestDto, HttpServletRequest request) throws Exception {
        if (StringUtils.isBlank(path)) {
            throw new RequestParamException("path不能为空");
        }
        String appId = request.getHeader("appId");
        if (StringUtils.isBlank(appId)) {
            throw new RequestParamException("appId不能为空");
        }
        String userId = request.getHeader("userId");
        if (StringUtils.isBlank(userId)) {
            throw new RequestParamException("userId不能为空");
        }
        String timestamp = request.getHeader("timestamp");
        if (StringUtils.isBlank(timestamp)) {
            throw new RequestParamException("时间戳不能为空");
        }
        String summary = request.getHeader("summary");
        if (StringUtils.isBlank(summary)) {
            throw new RequestParamException("summary不能为空");
        }
        String heads = new StringBuilder().append(appId.trim())
                .append(userId.trim())
                .append(timestamp.trim())
                .toString();
        log.info("summary is {} ; headers is {} ", summary, heads);

        BizSign bizSign = bizSignService.getByAppIdAndUserId(appId, userId);
        if (Objects.isNull(bizSign)){
            throw new BaseException("没有授权信息","500");
        }
        if (StringUtils.isBlank(bizSign.getPrivateKey())){
            throw new BaseException("没有秘钥信息","500");
        }
        log.info("privateKey is {}", bizSign.getPrivateKey());
        String decrypt = ApiEncryptUtil.decrypt(summary, ApiEncryptUtil.getPrivateKey(bizSign.getPrivateKey()));
        if (!StringUtils.equals(decrypt, heads)) {
            log.warn("decrypt is {}", decrypt);
            throw new BaseException("请求内容被修改", "500");
        }

        requestDto.setPath(path);
        requestDto.setAppId(appId);
        requestDto.setUserId(userId);
        requestDto.setContentType(request.getContentType());
        requestDto.setMethod(request.getMethod());
    }

    /**
     * 测试获得加密summary
     *
     * @param appId
     * @param userId
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "getSummary/{appId}/{userId}", method = RequestMethod.POST)
    @ResponseBody
    public String getSummary(@PathVariable("appId") String appId, @PathVariable("userId") String userId, HttpServletRequest request) throws Exception {
        String timestamp = String.valueOf(System.currentTimeMillis());
        String publicKey = IOUtils.toString(request.getInputStream(), "utf-8").trim();
        String encrypt = ApiEncryptUtil.encrypt(StringUtils.join(appId.trim(), userId.trim(), timestamp), ApiEncryptUtil.getPublicKey(publicKey));
        return StringUtils.join(timestamp, "=", encrypt);
    }
}
