package com.union.ai.api.controller;


import com.alibaba.fastjson.JSON;
import com.union.ai.api.dao.mapper.ApiLogMapper;
import com.union.ai.api.dao.mapper.ApiMapper;
import com.union.ai.api.dao.mapper.AppApiMapper;
import com.union.ai.api.dao.mapper.AppMapper;
import com.union.ai.api.dao.model.Api;
import com.union.ai.api.dao.model.ApiLog;
import com.union.ai.api.dao.model.App;
import com.union.ai.api.dao.model.AppApi;
import com.union.ai.api.util.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Date;
import java.util.Enumeration;

@Slf4j
@RestController
@RequestMapping("/")
public class CgiController {

    @Autowired
    ApiMapper apiMapper;
    @Autowired
    ApiLogMapper apiLogMapper;
    @Autowired
    AppMapper appMapper;
    @Autowired
    AppApiMapper appApiMapper;

    //cgi/a461f3f77e774105b1f02abe5aec6ba8/67
    @RequestMapping("cgi/{uuid}/{id}")
    public String liveness33(@PathVariable("uuid") String uuid, @PathVariable("id") Integer id, HttpServletRequest request, HttpServletResponse response) throws Exception {
        ApiLog apiLog = new ApiLog();
        apiLog.setInvokeDate(new Date());
        apiLog.setInvokeTime(System.currentTimeMillis() + "");
        Api api = apiMapper.selectById(id);
        apiLog.setResponseTime(System.currentTimeMillis() + "");
        apiLog.setApiId(api.getApiId());
//        log.info("cgi api = {}", api);
        String token = request.getHeader("access_token");
        if(StringUtils.isBlank(token)) {
            return "无效的token";
        }
        String appIdStr = RedisUtil.get(token);
        App app = appMapper.selectById(Integer.parseInt(appIdStr));
        if (app == null) {
            return "应用不存在";
        }
        if (app.getStatus() != 1) {
            return "应用已停用";
        }
        AppApi appApi = appApiMapper.selectByAppIdAndApiId(app.getAppId(), api.getApiId());
        if(appApi == null) {
            return "接口信息不存在";
        }
        if(appApi.getEnable() == 1) {
            return "接口已停用";
        }
        /*int count = apiLogMapper.selectCountByAppIdAndApiId(app.getAppId(), api.getApiId());
        if(count >= Integer.valueOf(appApi.getCallLimit())){
            return "该接口已超过调用量限制";
        }*/
        String key = token+":"+app.getAppId()+":"+appApi.getApiId();
        String qps = RedisUtil.get(key);
        if(StringUtils.isBlank(qps)){
            RedisUtil.set(key,"1",1);
        }else if(StringUtils.isNotBlank(qps) && appApi.getQpsLimit() != null && Integer.valueOf(qps) >= Integer.valueOf(appApi.getQpsLimit())){
            return "该接口已超过qps限制";
        }else {
            RedisUtil.incr(key);
//            Integer res = Integer.valueOf(qps) + 1;
//            RedisUtil.set(key, res.toString(), 1);
        }
        apiLog.setAppId(Integer.parseInt(appIdStr));
        apiLog.setUserId(app.getUserId());
        String result = "";
        if (request.getMethod().equals("POST")) {
            result = postHttp(apiLog, request, api.getUrl());
        } else {
            result = getHttp(apiLog, request, api.getUrl());
        }
         /*String res = getIp(request);
         if(StringUtils.isNotBlank(res)){
             apiLog.setProvince(res);
         }*/
        apiLogMapper.insertSelective(apiLog);
        return result;

    }

    /*private String getIp(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        try {
            String ipJson = CityUtil.getIpAddress(ip);
            JSONObject json = JSON.parseObject(ipJson);
            String location = json.getString("region_name");
            log.info("ip: {},location: {}", ip, location);
            return location;
        } catch (Exception e) {
            log.error("获取ip地址失败", e);
            throw new RuntimeException(e);
        }
    }*/

    private String getHttp(ApiLog apiLog, HttpServletRequest request, String redirectUrl) throws IOException {
        String params = request.getQueryString();
        if (params != null && !params.trim().isEmpty()) {
            redirectUrl = redirectUrl + "?" + params;
            apiLog.setParams(params);
        }
        CloseableHttpClient httpClient = HttpClients.createDefault();

        HttpGet httpGet = new HttpGet(redirectUrl);
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            String headerValue = request.getHeader(headerName);
            log.info("headerName =" + headerName +" - "+ "headerValue = " + headerValue);
            if(headerName.equals("host")){
                continue;
            }
            if(headerName.equals("content-length")){
                continue;
            }
            httpGet.addHeader(headerName,headerValue);
        }
        CloseableHttpResponse closeableHttpResponse = httpClient.execute(httpGet);
        String result = EntityUtils.toString(closeableHttpResponse.getEntity());
        log.info("getHttp-result:" + result);
        apiLog.setErrCode(closeableHttpResponse.getStatusLine().getStatusCode() + "");
        if (closeableHttpResponse.getStatusLine().getStatusCode() == 200) {
            apiLog.setCallResult(1);
        } else {
            apiLog.setCallResult(0);
        }
        return result;

    }

    private String postHttp(ApiLog apiLog, HttpServletRequest request, String redirectUrl) throws IOException {
        String params = request.getQueryString();
        if (params != null && !params.trim().isEmpty()) {
            redirectUrl = redirectUrl + "?" + params;
            apiLog.setParams(params);
        }
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(redirectUrl);
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            String headerValue = request.getHeader(headerName);
            log.info("headerName =" + headerName +" - "+ "headerValue = " + headerValue);
            if(headerName.equals("host")){
                continue;
            }
            if(headerName.equals("content-length")){
                continue;
            }
            httpPost.addHeader(headerName,headerValue);
        }
        StringBuffer jsonParams = new StringBuffer();
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(request.getInputStream()));
        String line = "";
        while ((line = bufferedReader.readLine()) != null) {
            jsonParams.append(line);
        }
        log.info("postHttp-params: " + jsonParams.toString());
        httpPost.setEntity(new StringEntity(jsonParams.toString(), ContentType.APPLICATION_JSON));
        CloseableHttpResponse closeableHttpResponse = httpClient.execute(httpPost);
        String result = EntityUtils.toString(closeableHttpResponse.getEntity());

        log.info("getHttp-result:" + result);

        apiLog.setErrCode(closeableHttpResponse.getStatusLine().getStatusCode() + "");
        if (closeableHttpResponse.getStatusLine().getStatusCode() == 200) {
            apiLog.setCallResult(1);
        } else {
            apiLog.setCallResult(0);
        }
        return result;

    }
}
