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 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.PrintWriter;
import java.util.HashMap;
import java.util.Map;

@Slf4j
public class PayInterceptor implements HandlerInterceptor {

    @Autowired
    MockMapper mockMapper;

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

    /**
     * 将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;
    }

    @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();
        log.info("打印请求参数：{}", parameterMap);
        QueryWrapper<Mock> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("url", uri);
        Mock mock = mockMapper.selectOne(queryWrapper);
        response.setHeader("Content-type", "application/json;charset=UTF-8");
        response.setCharacterEncoding("UTF-8");
        PrintWriter printWriter = response.getWriter();
        // 对request进行解密
        EncryptConvertor encryptConvertor = EncryptFactory.produce("yeebao");
        Map<String, Object> requestMap = JsonTransUtils.strToMap(encryptConvertor.decrypt(JsonTransUtils.mapToJson(requestMapTrans(parameterMap))));
        Map<String, Object> responseMap = new HashMap<>();
        if (uri.equals("/tzt-api/api/bankcard/check")) {
            String cardNo = requestMap.get("cardno").toString();
            String merchantno = requestMap.get("merchantno").toString();
            responseMap = getBankcardCheckResponse(cardNo, merchantno);
            printWriter.write(encryptConvertor.encrypt(JsonTransUtils.mapToJson(responseMap)));
            return true;
        }
        if (mock.getFlag().equals(1)) {
            responseMap = JsonTransUtils.strToMap(mock.getSuccess());
        } else if (mock.getFlag().equals(0)) {
            responseMap = JsonTransUtils.strToMap(mock.getFail());
        }
        // 如果response中存在变量，则使用requestMap中对应变量进行替换
        for (Map.Entry<String, Object> entry: responseMap.entrySet()) {
            String value = (String) entry.getValue();
            if (value.startsWith("$request")) {
                entry.setValue(requestMap.get(value.split("\\.")[1]));
            }
        }
        // 对response加密
        printWriter.write(encryptConvertor.encrypt(JsonTransUtils.mapToJson(responseMap)));
        return true;
    }

    @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 {
        log.info("calling afterCompletion");

    }

    public static void main(String[] args) {
    }
}
