package com.skyversation.poiaddr.util.net;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.skyversation.poiaddr.entity.PYToken;
import com.skyversation.poiaddr.entity.UserRecord;
import com.skyversation.poiaddr.entity.VerifyBean;
import com.skyversation.poiaddr.util.Constant;
import com.skyversation.poiaddr.util.MessageManage;
import com.skyversation.poiaddr.util.PYVerify;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.http.*;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.*;

public class NetTools {

    private static NetTools instance = new NetTools();

    private NetTools() {
    }

    public synchronized static NetTools getInstance() {
        if (instance == null) {
            instance = new NetTools();
        }
        return instance;
    }

    public List<String> tempToken = new ArrayList<>();
    public boolean isRun = false;

    private String userName = "user001";

    /**
     * Oauth 密码
     */
    private String password = "1234567890";

    public String getUserByToken(String token, String requestURI, HttpServletResponse response, HttpServletRequest request) throws IOException {
        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
        Map<String, String> header = new HashMap<>();
        header.put("token", token);
        params.put("strUrl", Collections.singletonList(requestURI));
        params.put("serviceId", Collections.singletonList("10"));
        JSONObject jsonObject = null;
        try {
            jsonObject = JSONObject.parseObject(requestPost(Constant.OAUTH_GET_USER_BY_TOKEN, params, header));
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }
        response.setCharacterEncoding("utf-8");
        response.setContentType("application/json; charset=utf-8");
        return MessageManage.getInstance().getResultContent(jsonObject.getInteger("code"), jsonObject.getString("content"), jsonObject.getString("message"));
    }

    public VerifyBean verifyToken(String token, String strUrl) {
        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
        Map<String, String> header = new HashMap<>();
        header.put("token", token);
        params.put("strUrl", Collections.singletonList(strUrl));
        params.put("serviceId", Collections.singletonList("8"));
        JSONObject jsonObject = JSONObject.parseObject(requestPost(Constant.OAUTH_URL_GETUSER, params, header));
        if (jsonObject.getInteger("code") == 200) {
            return new VerifyBean(true, null);
        } else {
            return new VerifyBean(false, jsonObject.toJSONString());
        }
    }

    /***
     * 验证PY token， 包含token合法验证、次数验证、失效验证
     * @param token
     * @return
     */
    public PYToken verifyPYToken(String token, String serverType) {
        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
        Map<String, String> header = new HashMap<>();
        params.put("token", Collections.singletonList(token));
        params.put("serverType", Collections.singletonList(serverType));
        JSONObject jsonObject =
                JSONObject.parseObject(requestPost(Constant.OAUTH_PY_URL, params, header));
        if (jsonObject.getInteger("code") == 200) {
            return JSON.parseObject(jsonObject.getJSONObject("content").toJSONString(), PYToken.class);
        } else {
            PYToken pyToken = new PYToken();
            pyToken.setErrorMsg(jsonObject.toJSONString());
            return pyToken;
        }
    }

    public VerifyBean isDefautUser(HttpServletRequest request, String token, String servertype) {
        if (Constant.getInstance().defaultToken.contains(token)) {
            UserRecord userRecord = Constant.getInstance().defaultTokenMap.get(token);
            if (userRecord != null) {
                MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
                params.add("userId", userRecord.getUserId() + "");
                params.add("accessToken", token);
                params.add("loginIp", getIpAddress(request));
                params.add("content", userRecord.getContent());
                params.add("userName", userRecord.getUserName());
                params.add("requestUrl", request.getRequestURI());
                params.add("serviceOrigin", userRecord.getServiceOrigin());
                params.add("state", servertype);
                requestPost(Constant.OAUTH_RECORD_URL, params, new HashMap<>());
            }
            return new VerifyBean(true, null);
        }
        return new VerifyBean(false,
                MessageManage.getInstance().getResultContent(Constant.FAILURE_TOKEN, "无效token", "无效token"));
    }

    public String requestPost(String url, MultiValueMap<String, String> params, Map<String, String> headerMap) {
        SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
        requestFactory.setConnectTimeout(10 * 1000);
        requestFactory.setReadTimeout(10 * 1000);
        RestTemplate client = new RestTemplate(requestFactory);
        client.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
        HttpHeaders headers = new HttpHeaders();
        //请勿轻易改变此提交方式，大部分的情况下，提交方式都是表单提交
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        if (headerMap != null) {
            Set<String> sets = headerMap.keySet();
            for (String key : sets) {
                headers.add(key, headerMap.get(key));
            }
        }

        HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(params, headers);//执行HTTP请求
        ResponseEntity<String> response = client.exchange(url, HttpMethod.POST, requestEntity, String.class);
        return response.getBody();
    }

    public ResponseEntity requestGet(String url, MultiValueMap<String, String> params, Map<String, String> headerMap) {
        SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
        requestFactory.setConnectTimeout(10 * 1000);
        requestFactory.setReadTimeout(10 * 1000);
        RestTemplate client = new RestTemplate(requestFactory);
        client.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
        HttpHeaders headers = new HttpHeaders();
        //请勿轻易改变此提交方式，大部分的情况下，提交方式都是表单提交
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        if (headerMap != null) {
            Set<String> sets = headerMap.keySet();
            for (String key : sets) {
                headers.add(key, headerMap.get(key));
            }
        }

        HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(params, headers);//执行HTTP请求
        ResponseEntity<String> response = client.exchange(url, HttpMethod.GET, requestEntity, String.class);
        return response;
    }

    public static String sendGetRequest(String urlString) throws Exception {
        HttpClient httpClient = HttpClients.createDefault();
        HttpGet httpGet = new HttpGet(urlString);
        HttpResponse response = httpClient.execute(httpGet);
        HttpEntity entity = (HttpEntity) response.getEntity();
        return EntityUtils.toString((org.apache.http.HttpEntity) entity);
    }

    /**
     * Oauth 登录获取token
     *
     * @return
     */
    public String loginForToken() {
        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
        params.add("userName", userName);
        params.add("password", password);
        params.add("clientId", "8");
        String response = NetTools.getInstance().requestPost(Constant.OAUTH_LOGIN_URL, params, new HashMap<>());
        JSONObject jsonObject = JSON.parseObject(response);
        return jsonObject.getString("message");
    }

    /**
     * 获取请求主机IP地址,如果通过代理进来，则透过防火墙获取真实IP地址;
     *
     * @param request
     * @return
     * @throws IOException
     */
    public final static String getIpAddress(HttpServletRequest request) {
        String ip = "";
        try {
            // 获取请求主机IP地址,如果通过代理进来，则透过防火墙获取真实IP地址
            ip = request.getHeader("X-Forwarded-For");
            if (ip != null && ip.length() > 0 && !"unKnown".equalsIgnoreCase(ip)) {
                // 多次反向代理后会有多个ip值，第一个ip才是真实ip
                int index = ip.indexOf(",");
                if (index != -1) {
                    return ip.substring(0, index);
                } else {
                    return ip;
                }
            }
            ip = request.getHeader("X-Real-IP");
            if (ip != null && ip.length() > 0 && !"unKnown".equalsIgnoreCase(ip)) {
                return ip;
            }
            ip = request.getRemoteAddr();
        } catch (Exception e) {
            // TODO: handle exception
        }
        return ip;
    }

    public static boolean verifyToken(HttpServletRequest request, String token, String servertype){
        // TODO 正常代理服务
        VerifyBean verifyBean = null;
        if(token.length() == 36){
            verifyBean = NetTools.getInstance().isDefautUser(request, token, servertype);
        } else {
            verifyBean = NetTools.getInstance().verifyToken(token, servertype);
            if(!verifyBean.isVerify()){
                verifyBean = PYVerify.getInstance().verify(request, token, servertype);
            }
        }

        if(!verifyBean.isVerify()){
            return false;
        }

        return true;
    }

}
