package cn.qg.qaplatform.mock.interceptor;

import cn.qg.qaplatform.config.SwitchDataSource;
import cn.qg.qaplatform.mock.encrypt.factory.EncryptConvertor;
import cn.qg.qaplatform.mock.encrypt.factory.EncryptFactory;
import cn.qg.qaplatform.mock.entity.Mock;
import cn.qg.qaplatform.mock.mapper.MockMapper;
import cn.qg.qaplatform.mock.utils.BankCardUtils;
import cn.qg.qaplatform.utils.JsonTransUtils;
import cn.qg.qaplatform.utils.RedisUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.Nullable;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
public class YeebaoInterceptor implements HandlerInterceptor {

    @Autowired
    MockMapper mockMapper;

//    @Value("${namespace}")
    private String namespace = "pre";

    @Autowired
    RedisUtils redisUtils;

    /**
     * 将HttpServletRequest的parameterMap由Map<String, String[]>转换成Map<String, Object>
     * @param parameterMap
     * @return
     */
    public Map<String, Object> requestMapTrans(Map<String, String[]> parameterMap) {
        Map<String, Object> map = new HashMap<>();
        for (Map.Entry<String, String[]> entry: parameterMap.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue()[0];
            map.put(key, value);
        }
        return map;
    }

    /**
     * 接口/tzt-api/api/bankcard/check 请求的mock响应
     * @param cardNo 银行卡号
     * @param merchantno 商户号
     * @return 响应Map
     */
    public Map<String, Object> getBankcardCheckResponse(String cardNo, String merchantno) {
        Map<String, Object> map = new HashMap<>();
        String bankCode =  BankCardUtils.getCardCode(cardNo);
        String bankName = BankCardUtils.getBankName(bankCode);
        map.put("bankcode", bankCode);
        map.put("bankname", bankName);
        map.put("cardtop", cardNo.substring(0, 5));
        map.put("cardlast", cardNo.substring(cardNo.length()-4));
        map.put("cardtype", "DEBIT");
        map.put("errorcode", "");
        map.put("errormsg", "");
        map.put("isvalid", "VALID");
        map.put("merchantno", merchantno);
        return map;
    }

    /**
     * 解析从数据库获取的响应，赋对应的值
     * @param requestMap
     * @param responseMap
     * @return
     */
    public Map<String, Object> handleResponseMap(Map<String, Object> requestMap, Map<String, Object> responseMap) {
        for (Map.Entry<String, Object> entry: responseMap.entrySet()) {
            if (entry.getValue() instanceof List) {
                List<Map> list = (List) entry.getValue();
                for (Map<String, Object> map: list) {
                    for (Map.Entry<String, Object> entry2: map.entrySet()) {
                        String value2 = entry2.getValue().toString();
                        if (value2.startsWith("$request")) {
                            entry2.setValue(requestMap.get(value2.split("\\.")[1]));
                        }
                    }
                }
            } else if (entry.getValue() instanceof String) {
                String value = entry.getValue().toString();
                if (value.startsWith("$request")) {
                    entry.setValue(requestMap.get(value.split("\\.")[1]));
                }
                if (value.equals("true")) {
                    entry.setValue(true);
                }
                if (value.equals("false")) {
                    entry.setValue(false);
                }
            }
        }
        return responseMap;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        SwitchDataSource.dataSourceSwitch(namespace, "qa");
        String uri = request.getRequestURI().substring(5);
        Map<String, String[]> parameterMap = request.getParameterMap();
        QueryWrapper<Mock> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("url", uri);
        Mock mock = mockMapper.selectOne(queryWrapper);
        Map<String, Object> requestMap;
        Map<String, Object> responseMap = new HashMap<>();
        String responseStr = null;
        if (mock.getFlag().equals(1)) {
            if (mock.getType() == 1) {
                responseMap = JsonTransUtils.strToMap(mock.getSuccess());
            } else if (mock.getType() == 2) {
                responseStr = mock.getSuccess();
            }
        } else if (mock.getFlag().equals(0)) {
            if (mock.getType() == 1) {
                responseMap = JsonTransUtils.strToMap(mock.getSuccess());
            } else if (mock.getType() == 2) {
                responseStr = mock.getSuccess();
            }
        }
        if (mock.getEncrypt() == 1) {
            EncryptConvertor encryptConvertor = EncryptFactory.produce("yeebao");
            requestMap = JsonTransUtils.strToMap(encryptConvertor.decrypt(JsonTransUtils.mapToJson(requestMapTrans(parameterMap))));
            // 针对 /tzt-api/api/bankcard/check 接口特殊处理
            if (uri.equals("/tzt-api/api/bankcard/check")) {
                String cardNo = requestMap.get("cardno").toString();
                String merchantno = requestMap.get("merchantno").toString();
                responseMap = getBankcardCheckResponse(cardNo, merchantno);
                modifyResponse(response, encryptConvertor.encrypt(JsonTransUtils.mapToJson(responseMap)));
                redisUtils.set(requestMap.get("requestno").toString(), responseMap);
                log.info("保存redis值, key: {}, value: {}", requestMap.get("requestno"), responseMap);
                return true;
            }
            // 判断返回是字符串还是json,1-json，2-字符串
            if (mock.getType() == 1) {
                responseMap = handleResponseMap(requestMap, responseMap);
                if (uri.equals("/tzt-api/api/bindcard/request")) {
                    responseMap.put("yborderid", "TZAUba0c7b8" + requestMap.get("requestno") + "95c929ca802e");
                }

                if (uri.equals("/tzt-api/api/bindcard/confirm")) {
                    Map bindcardCheckRedisValue = (Map) redisUtils.get(requestMap.get("requestno").toString());
                    responseMap.put("bankcode", bindcardCheckRedisValue.get("bankcode"));
                    responseMap.put("bankname", bindcardCheckRedisValue.get("bankname"));
                    responseMap.put("cardlast", bindcardCheckRedisValue.get("cardlast"));
                    responseMap.put("cardtop", bindcardCheckRedisValue.get("cardtop"));
                }
                modifyResponse(response, encryptConvertor.encrypt(JsonTransUtils.mapToJson(responseMap)), "application/json; charset=utf-8");
                return true;
            } else if (mock.getType() == 2) {
                modifyResponse(response, encryptConvertor.encrypt(responseStr));
                return true;
            }
        } else if (mock.getEncrypt() == 0) {
            requestMap = requestMapTrans(parameterMap);
            // 针对 /balance-board/transfer 接口特殊处理
            if (uri.equals("/balance-board/transfer")) {
                BufferedReader br = request.getReader();
                String str="";
                StringBuilder requestData = new StringBuilder();
                while((str = br.readLine()) != null){
                    requestData.append(str);
                }
                br.close();
                String cmd = requestData.toString().split("<cmd>")[1].split("</cmd>")[0];
                log.info("yeepay-transfer cmd-------- {}", cmd);
                String transferResponse = null;
                if("AccountBalanaceQuery".equals(cmd)){
                    //查询余额的返回值
                    transferResponse = "<data><cmd>AccountBalanaceQuery</cmd><hmac>MIIE6QYJKoZIhvcNAQcCoIIE2jCCBNYCAQExCzAJBgUrDgMCGgUAMC8GCSqGSIb3DQEHAaAiBCAxYTcyYmQwZWVmMWIyNDRkNTFlNmEzYTAwMjk1Mjk1OKCCA7EwggOtMIIDFqADAgECAhAuyfCgPbMcigfvVyGazeQRMA0GCSqGSIb3DQEBBQUAMCQxCzAJBgNVBAYTAkNOMRUwEwYDVQQKEwxDRkNBIFRFU1QgQ0EwHhcNMTExMTI4MDcwOTUzWhcNMTMxMTI4MDcwOTUzWjBzMQswCQYDVQQGEwJDTjEVMBMGA1UEChMMQ0ZDQSBURVNUIENBMQ8wDQYDVQQLEwZZRUVQQVkxEjAQBgNVBAsTCUN1c3RvbWVyczEoMCYGA1UEAxQfMDQxQFoxMjNxd2VAemhpd2VuLm1laUAwMDAwMDAwMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAzrITNElBaFF7xPXtPguWeTnGOI1gVMMkUDI57ZQz+Gg9PPcfF+ExrtDgMQEOwfRs7X4XiraPE2l6ub0Xkpl0ftu8ELnii91wUKAqsvp88NIdAdLQnC7PeveWlquVSAf//2WtAkdBI7xnhXaL/ObUkhHheT0aR5miYmDyLAkTBj8CAwEAAaOCAY8wggGLMB8GA1UdIwQYMBaAFEZy3CVynwJOVYO1gPkL2+mTs/RFMB0GA1UdDgQWBBS0k6A7ZSwLRwbIhFsgcChrYd27PDALBgNVHQ8EBAMCBaAwDAYDVR0TBAUwAwEBADA7BgNVHSUENDAyBggrBgEFBQcDAQYIKwYBBQUHAwIGCCsGAQUFBwMDBggrBgEFBQcDBAYIKwYBBQUHAwgwgfAGA1UdHwSB6DCB5TBPoE2gS6RJMEcxCzAJBgNVBAYTAkNOMRUwEwYDVQQKEwxDRkNBIFRFU1QgQ0ExDDAKBgNVBAsTA0NSTDETMBEGA1UEAxMKY3JsMTI2XzE5NDCBkaCBjqCBi4aBiGxkYXA6Ly90ZXN0bGRhcC5jZmNhLmNvbS5jbjozODkvQ049Y3JsMTI2XzE5NCxPVT1DUkwsTz1DRkNBIFRFU1QgQ0EsQz1DTj9jZXJ0aWZpY2F0ZVJldm9jYXRpb25MaXN0P2Jhc2U/b2JqZWN0Y2xhc3M9Y1JMRGlzdHJpYnV0aW9uUG9pbnQwDQYJKoZIhvcNAQEFBQADgYEAKX4CXCPQEE4RWGsZTXZXLBct2gcPYEjqpgPZ5ERiUrYLTDGuIT90ECfSoxCrcTJEeY7EJBojig9gLRoMn/4xXW/XscGarQ3XxyZw8VxTMFkotuUkAPoaacYlIrc34t2DR0DqvU6umgFL3yTMYxl5WLjOh47OH7Aw7VPscmrtzEIxgd0wgdoCAQEwODAkMQswCQYDVQQGEwJDTjEVMBMGA1UEChMMQ0ZDQSBURVNUIENBAhAuyfCgPbMcigfvVyGazeQRMAkGBSsOAwIaBQAwDQYJKoZIhvcNAQEBBQAEgYBW4+qU8lVs4gEk/o+ln33umTlBDViDf+VMA/6vDhfECTy1fbBHqqr84QFBagMqEXGHzXzzP8qGRRAhmKLhn4RimcrvRh3BRbcQig6OEL/Zz1SphFEH0+BRAN+jhLYRt7+zQZvBx65rE52ivMqCpmEQ+6F4BbNCWwJ+0/xbCE4m5Q==</hmac><ret_Code>1</ret_Code><balance_Amount>291227.76</balance_Amount><valid_Amount>291227.76</valid_Amount></data>";
                }else if("TransferBatch".equals(cmd)){
                    String batchNo = requestData.toString().split("<batch_No>")[1].split("</batch_No>")[0];
                    //申请易宝放款的返回值
                    transferResponse = "<?xml version='1.0' encoding='GBK'?><data><cmd>TransferBatch</cmd><hmac>MIIE6QYJKoZIhvcNAQcCoIIE2jCCBNYCAQExCzAJBgUrDgMCGgUAMC8GCSqGSIb3DQEHAaAiBCAyYjM0NGJiNmVlZDliYmY1Mjk3MGNkMGFjMjNlMTA5NqCCA7EwggOtMIIDFqADAgECAhAuyfCgPbMcigfvVyGazeQRMA0GCSqGSIb3DQEBBQUAMCQxCzAJBgNVBAYTAkNOMRUwEwYDVQQKEwxDRkNBIFRFU1QgQ0EwHhcNMTExMTI4MDcwOTUzWhcNMTMxMTI4MDcwOTUzWjBzMQswCQYDVQQGEwJDTjEVMBMGA1UEChMMQ0ZDQSBURVNUIENBMQ8wDQYDVQQLEwZZRUVQQVkxEjAQBgNVBAsTCUN1c3RvbWVyczEoMCYGA1UEAxQfMDQxQFoxMjNxd2VAemhpd2VuLm1laUAwMDAwMDAwMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAzrITNElBaFF7xPXtPguWeTnGOI1gVMMkUDI57ZQz+Gg9PPcfF+ExrtDgMQEOwfRs7X4XiraPE2l6ub0Xkpl0ftu8ELnii91wUKAqsvp88NIdAdLQnC7PeveWlquVSAf//2WtAkdBI7xnhXaL/ObUkhHheT0aR5miYmDyLAkTBj8CAwEAAaOCAY8wggGLMB8GA1UdIwQYMBaAFEZy3CVynwJOVYO1gPkL2+mTs/RFMB0GA1UdDgQWBBS0k6A7ZSwLRwbIhFsgcChrYd27PDALBgNVHQ8EBAMCBaAwDAYDVR0TBAUwAwEBADA7BgNVHSUENDAyBggrBgEFBQcDAQYIKwYBBQUHAwIGCCsGAQUFBwMDBggrBgEFBQcDBAYIKwYBBQUHAwgwgfAGA1UdHwSB6DCB5TBPoE2gS6RJMEcxCzAJBgNVBAYTAkNOMRUwEwYDVQQKEwxDRkNBIFRFU1QgQ0ExDDAKBgNVBAsTA0NSTDETMBEGA1UEAxMKY3JsMTI2XzE5NDCBkaCBjqCBi4aBiGxkYXA6Ly90ZXN0bGRhcC5jZmNhLmNvbS5jbjozODkvQ049Y3JsMTI2XzE5NCxPVT1DUkwsTz1DRkNBIFRFU1QgQ0EsQz1DTj9jZXJ0aWZpY2F0ZVJldm9jYXRpb25MaXN0P2Jhc2U/b2JqZWN0Y2xhc3M9Y1JMRGlzdHJpYnV0aW9uUG9pbnQwDQYJKoZIhvcNAQEFBQADgYEAKX4CXCPQEE4RWGsZTXZXLBct2gcPYEjqpgPZ5ERiUrYLTDGuIT90ECfSoxCrcTJEeY7EJBojig9gLRoMn/4xXW/XscGarQ3XxyZw8VxTMFkotuUkAPoaacYlIrc34t2DR0DqvU6umgFL3yTMYxl5WLjOh47OH7Aw7VPscmrtzEIxgd0wgdoCAQEwODAkMQswCQYDVQQGEwJDTjEVMBMGA1UEChMMQ0ZDQSBURVNUIENBAhAuyfCgPbMcigfvVyGazeQRMAkGBSsOAwIaBQAwDQYJKoZIhvcNAQEBBQAEgYAC38fZ2TRB7Myf2VWcQSmGMCO2lGcuAtUfA2m9pHiZ1CZ/cUd/Jj1bmN94QT+7IcPOXw2ZPBbCufeClYHSZRLy3hk3P+WhpGQenlp5zTkJjGvKFKxOdDp6ymlruCE/wQRwH9rMrxhuLkyEauAOQEAeE8EtBsKtBhVanSxEWYlSug==</hmac><ret_Code>1</ret_Code><mer_Id>10000449592</mer_Id><batch_No>" + batchNo + "</batch_No><total_Amt>0.01</total_Amt><total_Num>1</total_Num><r1_Code>0025</r1_Code></data>";
                }else if("BatchDetailQuery".equals(cmd)){
                    String batchNo = requestData.toString().split("<batch_No>")[1].split("</batch_No>")[0];
                    //放款结果查询的返回值
                    transferResponse = "<data><cmd>BatchDetailQuery</cmd><hmac>MIIE6QYJKoZIhvcNAQcCoIIE2jCCBNYCAQExCzAJBgUrDgMCGgUAMC8GCSqGSIb3DQEHAaAiBCA2ZWU1ODE3Y2UwNDg4NDczNmJlNWFlNGM0MDViZGNlYaCCA7EwggOtMIIDFqADAgECAhAuyfCgPbMcigfvVyGazeQRMA0GCSqGSIb3DQEBBQUAMCQxCzAJBgNVBAYTAkNOMRUwEwYDVQQKEwxDRkNBIFRFU1QgQ0EwHhcNMTExMTI4MDcwOTUzWhcNMTMxMTI4MDcwOTUzWjBzMQswCQYDVQQGEwJDTjEVMBMGA1UEChMMQ0ZDQSBURVNUIENBMQ8wDQYDVQQLEwZZRUVQQVkxEjAQBgNVBAsTCUN1c3RvbWVyczEoMCYGA1UEAxQfMDQxQFoxMjNxd2VAemhpd2VuLm1laUAwMDAwMDAwMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAzrITNElBaFF7xPXtPguWeTnGOI1gVMMkUDI57ZQz+Gg9PPcfF+ExrtDgMQEOwfRs7X4XiraPE2l6ub0Xkpl0ftu8ELnii91wUKAqsvp88NIdAdLQnC7PeveWlquVSAf//2WtAkdBI7xnhXaL/ObUkhHheT0aR5miYmDyLAkTBj8CAwEAAaOCAY8wggGLMB8GA1UdIwQYMBaAFEZy3CVynwJOVYO1gPkL2+mTs/RFMB0GA1UdDgQWBBS0k6A7ZSwLRwbIhFsgcChrYd27PDALBgNVHQ8EBAMCBaAwDAYDVR0TBAUwAwEBADA7BgNVHSUENDAyBggrBgEFBQcDAQYIKwYBBQUHAwIGCCsGAQUFBwMDBggrBgEFBQcDBAYIKwYBBQUHAwgwgfAGA1UdHwSB6DCB5TBPoE2gS6RJMEcxCzAJBgNVBAYTAkNOMRUwEwYDVQQKEwxDRkNBIFRFU1QgQ0ExDDAKBgNVBAsTA0NSTDETMBEGA1UEAxMKY3JsMTI2XzE5NDCBkaCBjqCBi4aBiGxkYXA6Ly90ZXN0bGRhcC5jZmNhLmNvbS5jbjozODkvQ049Y3JsMTI2XzE5NCxPVT1DUkwsTz1DRkNBIFRFU1QgQ0EsQz1DTj9jZXJ0aWZpY2F0ZVJldm9jYXRpb25MaXN0P2Jhc2U/b2JqZWN0Y2xhc3M9Y1JMRGlzdHJpYnV0aW9uUG9pbnQwDQYJKoZIhvcNAQEFBQADgYEAKX4CXCPQEE4RWGsZTXZXLBct2gcPYEjqpgPZ5ERiUrYLTDGuIT90ECfSoxCrcTJEeY7EJBojig9gLRoMn/4xXW/XscGarQ3XxyZw8VxTMFkotuUkAPoaacYlIrc34t2DR0DqvU6umgFL3yTMYxl5WLjOh47OH7Aw7VPscmrtzEIxgd0wgdoCAQEwODAkMQswCQYDVQQGEwJDTjEVMBMGA1UEChMMQ0ZDQSBURVNUIENBAhAuyfCgPbMcigfvVyGazeQRMAkGBSsOAwIaBQAwDQYJKoZIhvcNAQEBBQAEgYCD/g83n6KyattYAEPqff/9z613+4AaZDHVxY9xEb3lBGRRosVQptgkZItEc9cM2Em/o9GfV/mqj5T6CP5glvbbtFnrz2Z0GGNbDR/gqOIPhpACRZozZipwUeQESVhRCiCJa4sPuoEkgSSq5XvL5nIvAxc59DeKWIv/LGqYq9dK8Q==</hmac><ret_Code>1</ret_Code><batch_No>' + batchNo + '</batch_No><total_Num>1</total_Num><end_Flag>Y</end_Flag><list><items><item><remarksInfo></remarksInfo><amount>0.01</amount><fee></fee><abstractInfo>提现打款</abstractInfo><note/><order_Id>PAYMENT78162155286528</order_Id><payee_Bank_Account>1506213009022200623</payee_Bank_Account><refund_Date></refund_Date><real_pay_amount>0.01</real_pay_amount><payee_BankName>工商银行</payee_BankName><complete_Date>2020-01-16 18:20:09</complete_Date><request_Date>2020-01-16 18:20:08</request_Date><payee_Name>蒋素霞</payee_Name><bank_Status>S</bank_Status><r1_Code>0026</r1_Code><fail_Desc></fail_Desc></item></items></list></data>";
                }
                modifyResponse(response, transferResponse);
                return false;
            }
            if (mock.getType() == 1) {
                responseMap = handleResponseMap(requestMap, responseMap);
                modifyResponse(response, JsonTransUtils.mapToJson(responseMap));
                return true;
            } else if (mock.getType() == 2) {
                modifyResponse(response, responseStr);
                return true;
            }
        }
        return true;
    }

    /**
     * 修改返回响应
     * @param response HttpServletResponse
     * @param result 返回的json或字符串
     */
    private void modifyResponse(HttpServletResponse response, String result) {
        PrintWriter writer = null;
        response.setCharacterEncoding("UTF-8");
//        response.setContentType("application/json; charset=utf-8");
        try {
            writer = response.getWriter();
            writer.print(result);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (writer != null) {
                writer.close();
            }
        }
    }

    /**
     * 修改返回响应
     * @param response HttpServletResponse
     * @param result 返回的json或字符串
     * @param contentType content-type
     */
    private void modifyResponse(HttpServletResponse response, String result, String contentType) {
        PrintWriter writer = null;
        response.setCharacterEncoding("UTF-8");
        response.setContentType(contentType);
        try {
            writer = response.getWriter();
            writer.print(result);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (writer != null) {
                writer.close();
            }
        }
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                            @Nullable ModelAndView modelAndView) throws Exception {
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
                                 @Nullable Exception ex) throws Exception {
    }
}
