package com.jkcredit.invoice.credit;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jkcredit.invoice.common.ApiResult;
import com.jkcredit.invoice.common.DataResult;
import com.jkcredit.invoice.common.RequestApi;
import com.jkcredit.invoice.common.ResponseCode;
import com.jkcredit.invoice.model.entity.customer.Customer;
import com.jkcredit.invoice.service.customer.CustomerService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @Description: 跨域请求拦截器
 * @Author: mashengyi
 * @Date: 2021/9/12
 */
@Slf4j
public class SimpleCORSFilter implements Filter {

    @Autowired
    CustomerService customerService;

    @Autowired
    InterfaceCheckServer interfaceCheckServer;






    //全局定义ApiConstant
    private final static Map<String, String> apiMaps=new HashMap<String, String>(){
        {


            //无车、自有车 公共下游客户调用接口
            put( "COMPANY_ADD_V1" ,  "1");//自有车 无车、企业注册
            put( "COMPANY_QUERY_V1" ,  "1");//自有车 无车、企业查询
            put( "PROTOCOL_ADD_V1" ,  "1");//自有车 无车、协议上传

            //无车下游客户调用接口
            put( "VEHICLE_REGISTER" ,  "1");//车辆备案
            put( "VEHICLE_REGISTER_QUERY" ,  "1");//车辆备案查询
            put( "WAY_BILL_START" ,  "1");// 实时运单开始指令
            put( "WAY_BILL_END" ,  "1");//实时运单结束指令
            put( "WAY_BILL_HISTORY_START" ,  "1");//历史运单开始指令
            put( "WAY_BILL_HISTORY_END" ,  "1");// 历史运单结束指令
            put( "WAY_BILL_NUM_FIND_INVOICE" ,  "1");// 运单号查询发票数据
            put( "FIND_NO_SEARCH_NUM" ,  "1");//获取未查询过发票的运单编号
            put( "BALANCE_QUERY" ,  "1");//账号余额查询


            //自有车下游客户调用接口
            put( "CARD_BIND_QUERY_LIST_V1" ,  "1"); //用户卡列表查询
            put( "CARD_QUERY_CARD_V1" ,  "1");//卡信息查询
            put( "CARD_BINDING_V1" ,  "1");//下发短信验证码
            put( "CARD_VALID_CODE_V1" ,  "1");//自有车卡绑定接口、自有车输入参数接口
            put( "CARD_TRADE_V1" ,  "1");//交易查询
            put( "B2B_INVOICE_APPLY_V1" ,  "1");//申请开票
            put( "B2B_INVOICE_QUERY_V1" ,  "1");//已开发票查询
            put( "B2B_INVOICE_PACKAGE_V1" ,  "1");//发票下载
            put( "CARD_UNBIND_V1" ,  "1");//卡解绑
        }
    };



    /**
     * 不需要 Token 校验的接口
     */
    private final static String[] NO_TOKEN_API_PATHS ={
            "/**/favicon.ico",
            "/favicon.ico",
            "/swagger-ui.html",
            "/webjars/**",
            "/webjars/springfox-swagger-ui/springfox.css",
            "/webjars/springfox-swagger-ui/springfox.js",
            "/webjars/springfox-swagger-ui/swagger-ui-bundle.js",
            "/webjars/springfox-swagger-ui/swagger-ui.css",
            "/webjars/springfox-swagger-ui/swagger-ui-standalone-preset.js",
            "/swagger-resources/configuration/ui",
            "/swagger-resources/configuration/security",
            "/swagger-resources",
            "/v2/api-docs",
            "/customer/findCustomer",
            "/customer/findCustomerRecharge",
            "/customer/findCustomerRechargeMoney",
            "/customer/findCustomerRecList",
            "/customer/findCustomerRecListExport",
            "/customer/addCustomer",
            "/customer/updateCustomer",
            "/customer/addCustomer",
            "/customer/customeRecStop",
            "/customer/customerRecAdd",
            "/customer/customRecharge",
            "/customer/customeRec",
            "/customer/contractAdd",
            "/customer/contractDownload",
            "/customer/generateWord",
            "/customer/findCustomerRecTimeList",
            "/customer/findCustomerMoney",
            "/customer/customeRecQueryListByPage",
            "/customer/customeRecQueryUpper",

            "/noCar/findCarRec",
            "/noCar/findBillWay",
            "/noCar/findBillWayCust",
            "/noCar/findImportBillWay",
            "/noCar/updateStatus",
            "/noCar/findBatchList",
            "/noCar/findNocarInvoicesStatic",
            "/noCar/batchImprotBillWay",
            "/noCar/batchImprotHistoryBillWay",
            "/noCar/batchImprotEndBillWay",
            "/noCar/findBillWayException",
            "/noCar/findNocarInvoices",
            "/noCar/findNocarInvoicesStatic",
            "/noCar/findNocarCalculateInfoStatis",
            "/noCar/findNocarCalculateInfo",
            "/noCar/templateDownload",
            "/noCar/batchImportNocarInvoices",
            "/noCar/batchImportNocarBillWay",


            "/selfCar/selfCarUnBind",
            "/selfCar/findTrades",
            "/selfCar/findSelfCarInvoices",
            "/selfCar/findSelfcarCalculateInfo",
            "/selfCar/findSelfcarCalculateInfoSta",
            "/selfCar/getTradeList",
            "/selfCar/applTradeList",
            "/selfCar/findSelfcarInvoiceByTime",
            "/selfCar/batchImportSelfcarInvoices",
            "/selfCar/batchImportSelfcarTrades",
            "/selfCar/updateTrades",

            "/param",
            "/param/page",
            "/param/updateParam",


            "/lowerService/customeRec",
            "/lowerService/customeRecQueryList",
            "/lowerService/customeRecQueryUpper",
            "/lowerService/customeRecQuery",

            "/noCarService/noCarBillStart",
            "/noCarService/noCarBillEnd",
            "/noCarService/noCarHisWaybillStart",
            "/noCarService/noCarHisWaybillEnd",
            "/noCarService/noCarVoiceQuery",
            "/noCarService/hCVoiceQuery",
            "/noCarService/monthAccQuery",
            "/noCarService/customerCarRec",
            "/noCarService/customeRecUpperQuery",
            "/noCarService/customerCarRecQuery",


            "/selfCarService/getTradeList",
            "/selfCarService/applInvoice",
            "/selfCarService/getSelfCarInvoicesByTime",
            "/selfCarService/getSelfCarInvoicePackage",
            "/selfCarService/getSelfCarInvoicesByAppl",
            "/selfCarService/customerETCQuery",
            "/selfCarService/queryEtcInfo",
            "/selfCarService/customerETCRec",
            "/selfCarService/customerETCRecValid",
            "/selfCarService/customerCarUnRec",

            "/auth/login",
            "/role/list",
            "/user",
            "/user/updateUser",
            "/user/page",
            "/user/restPassword",
            "/user/lock"
    };

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
        HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;
        // *表示允许所有域名跨域
        //httpResponse.addHeader("Access-Control-Allow-Origin", "'*");
        //httpResponse.addHeader("Access-Control-Allow-Headers","*");
        // 允许跨域的Http方法
        httpResponse.addHeader("Access-Control-Allow-Methods", "GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS,TRACE");
        // 允许浏览器访问 Token 认证响应头
        //httpResponse.addHeader("Access-Control-Expose-Headers", TokenConst.TOKEN_HEADERS_FIELD);
        // 默认返回原 Token
        //httpResponse.setHeader(TokenConst.TOKEN_HEADERS_FIELD, httpRequest.getHeader(TokenConst.TOKEN_HEADERS_FIELD));
        // 应对探针模式请求(OPTIONS)
        String methodOptions = "OPTIONS";
        if (httpRequest.getMethod().equals(methodOptions)) {
            httpResponse.setStatus(HttpServletResponse.SC_ACCEPTED);
            return;
        }
        /**
         * 校验用户 Token
         */

        boolean flag = (!Arrays.asList(NO_TOKEN_API_PATHS).contains(httpRequest.getRequestURI()));
        if(httpRequest.getRequestURI().contains("/user/") || "/".equals(httpRequest.getRequestURI()) || httpRequest.getRequestURI().contains("/static/") || httpRequest.getRequestURI().contains("/jkcredit/")){
            flag = false;
        }
        if (flag) {

            // 创建客户唯一标识ID，以当前时间作为前缀，uuid为后缀
            String requestid = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date()) + ","
                    + UUID.randomUUID().toString();

            long startTime = System.currentTimeMillis();
            String flagUuid = UUID.randomUUID().toString();
            RequestApi requestApi = new RequestApi();
            ResponseCode responseCode = checkToken(httpRequest, httpResponse,startTime,flagUuid,requestApi);
            if (!Objects.equals(responseCode, ResponseCode.SUCCESS)) {
                log.error("FILE - SimpleCORSFilterError = {}", responseCode + " ,requestURI = {" + httpRequest.getRequestURI() +"}");
                //httpResponse.setStatus(HttpServletResponse.SC_BAD_REQUEST);
                httpResponse.setContentType("application/json; charset=utf-8");
                httpResponse.setCharacterEncoding("utf-8");
                PrintWriter writer = httpResponse.getWriter();
                writer.write(new ObjectMapper().writeValueAsString(ApiResult.failure(responseCode,requestid)));
                log.error("[FILE - SimpleCORSFilter-] return result=" + responseCode.toString() + " , param is api="+  requestApi.getApi() + " , data=" + requestApi.getData() + " , appKey=" + requestApi.getAppKey() + " , appSecret=" + requestApi.getAppSecret() +  " ,timeCost=" +(System.currentTimeMillis()-startTime) + "ms" +" , flag=" + flagUuid);
                return;
            }else{
                log.info("SUCCESS - SimpleCORSFilterWarn = {}", responseCode + " ,requestURI = {" + httpRequest.getRequestURI() +"}");


                DataResult dataResult =  interfaceCheckServer.doJumpHandler(requestApi.getAppKey(),requestApi.getApi(),requestApi.getData(),requestid);
                if(null == dataResult){
                    dataResult = new DataResult();
                    dataResult.setData(3);
                    dataResult.setCode(200);
                    dataResult.setRequestid(requestid);
                    dataResult.setMsg("无法认证");
                }
                //httpResponse.setStatus(HttpServletResponse.SC_BAD_REQUEST);
                httpResponse.setContentType("application/json; charset=utf-8");
                httpResponse.setCharacterEncoding("utf-8");
                PrintWriter writer = httpResponse.getWriter();
                writer.write(new ObjectMapper().writeValueAsString(ApiResult.failure(dataResult)));
                log.info("[SUCCESS - SimpleCORSFilter-] return result=" + dataResult.toString() + " , param is api="+  requestApi.getApi() + " , data=" + requestApi.getData() + " , appKey=" + requestApi.getAppKey() + " , appSecret=" + requestApi.getAppSecret() +  " ,timeCost=" +(System.currentTimeMillis()-startTime) + "ms" +" , flag=" + flagUuid);
                return;
            }
        }

        filterChain.doFilter(httpRequest, servletResponse);
    }



    @Override
    public void destroy() {

    }

    private String getApi(String request){
        String api = "";
        Pattern p=Pattern.compile("api=(\\w+)&");
        Matcher m=p.matcher(request);
        while(m.find()){
            api = m.group(1);
        }
        if(StringUtils.isEmpty(api)){
            api = JSONObject.parseObject(request.substring(0, request.length()-1)).getString("api");
        }
        return  api;
    }
    private String getAppKey(String request){
        String appkey = "";
        Pattern p=Pattern.compile("appKey=(\\w+)&");
        Matcher m=p.matcher(request);
        while(m.find()){
            appkey = m.group(1);
        }

        if(StringUtils.isEmpty(appkey)){
            appkey = JSONObject.parseObject(request.substring(0, request.length()-1)).getString("appKey");

        }
        return  appkey;
    }
    private String getAppSecret(String request){
        String appSecret = "";
        Pattern p=Pattern.compile("appSecret=(\\w+)&");
        Matcher m=p.matcher(request);
        while(m.find()){
            appSecret = m.group(1);
        }

        if(StringUtils.isEmpty(appSecret)){
            appSecret = JSONObject.parseObject(request.substring(0, request.length()-1)).getString("appSecret");

        }

        return  appSecret;
    }
    private String getData(String request){
        String data = "";
        Pattern p=Pattern.compile("data=([^&]*)&");
        Matcher m=p.matcher(request);
        while(m.find()){
            data = m.group(1);

        }

        if(StringUtils.isEmpty(data)){
           // data = getsrt("\"data\":", ",", request).trim();;
            data = JSONObject.parseObject(request.substring(0, request.length()-1)).getString("data");
        }
        return  data;
    }
    /**
     * 用户 Token 校验
     *
     * @param request
     * @param response
     * @return
     */
    private ResponseCode checkToken(HttpServletRequest request, HttpServletResponse response,long startTime,String flag,RequestApi requestApi) {
        try {


            if(null != request && null != request.getQueryString() && !request.getQueryString().equals("api=credit.sec.data")){
                return ResponseCode.UNKNOWN_ERROR;
            };

            if(null != request && null != request.getQueryString() && !request.getRequestURI().equals("/gateway")){
                return ResponseCode.UNKNOWN_ERROR;
            }


            if(null != request && null == request.getQueryString() && !request.getRequestURI().equals("/api/rest")){
                return ResponseCode.UNKNOWN_ERROR;
            }

            if(null == request ){
                return ResponseCode.UNKNOWN_ERROR;
            }

            if(null != request  && null == request.getQueryString() && null == request.getRequestURI()  ){
                return ResponseCode.UNKNOWN_ERROR;
            }

            String jsonObject1 = getOpenApiRequestData(request);
            String api = getApi(jsonObject1);
            String appKey = getAppKey(jsonObject1);
            String appSecret = getAppSecret(jsonObject1);
            String data = getData(jsonObject1);
            requestApi.setApi(api);
            requestApi.setData(data);
            requestApi.setAppSecret(appSecret);
            requestApi.setAppKey(appKey);
            log.info("[-SimpleCORSFilter-] query param api=" + api + " , data=" + data + " , appKey=" + appKey + " , appSecret=" + appSecret + " , flag=" + flag);
            if (StringUtils.isEmpty(api) || StringUtils.isEmpty(data) || StringUtils.isEmpty(appKey) || StringUtils.isEmpty(appSecret)) {
                return ResponseCode.UNKNOWN_ERROR;
            }


            Customer customer = new Customer();
            customer.setCustomerName(appKey);
            customer.setAppSecret(appSecret);
            Customer customer1 = customerService.getCustomerByAppKeyAndAppSecret(customer);

            if (null == customer1 || customer1.getAccstatus() != 0) {
                return ResponseCode.ACCOUNT_NOT_EXIST;
            }
            if(null != customer1 && ! appSecret.equals(customer1.getAppSecret())){
                return ResponseCode.SIGN_ERROR;
            }
            if (0 >= new BigDecimal(customer1.getAccountBalance()).compareTo(new BigDecimal(0.0))) {
                return ResponseCode.BALANCE_QUERY_ERROR;
            }
            if(!apiMaps.containsKey(api)){
                return ResponseCode.CUSTOMER_QUERY_ERROR;
            }

        } catch (Exception e) {
            log.error("Token 校验失败,{}:{}", e.getClass().getName(), e.getMessage());
            return ResponseCode.MEDIA_TYPE_NOT_SUPPORT_ERROR;
        }
        return ResponseCode.SUCCESS;
    }




    public  String getOpenApiRequestData(HttpServletRequest request){
        String str = "";
        try {

            request.setCharacterEncoding("UTF-8");

            int contentLength = request.getContentLength();

            if (contentLength < 0) {
                return null;
            }
            byte buffer[] = new byte[contentLength];
            for (int i = 0; i < contentLength;) {

                int readlen = request.getInputStream().read(buffer, i, contentLength - i);
                if (readlen == -1) {
                    break;
                }
                i += readlen;
            }

            String charEncoding = request.getCharacterEncoding();
            if (charEncoding == null) {
                charEncoding = "UTF-8";
            }
            str = new String(buffer, charEncoding)+"&";
            str = URLDecoder.decode(str, "UTF-8");


            return str;

        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }


    public static String getsrt(String startkeystr, String endstr, String str) {
        int customerindex = str.indexOf(startkeystr);
        String temp = str.substring(customerindex + startkeystr.length());
        int endindex = temp.indexOf(endstr);
        String sss = temp.substring(0, endindex);
        return sss;
    }

    public static String getsrt1(String startkeystr, String str) {
        int customerindex = str.indexOf(startkeystr);
        String temp = str.substring(customerindex + startkeystr.length());
        return temp;
    }

}
