package com.jsowell.api.thirdparty;

import com.alibaba.fastjson2.JSONObject;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.collect.Maps;
import com.jsowell.common.annotation.Anonymous;
import com.jsowell.common.core.controller.BaseController;
import com.jsowell.common.exception.BusinessException;
import com.jsowell.common.util.JWTUtils;
import com.jsowell.common.util.StringUtils;
import com.jsowell.pile.thirdparty.CommonParamsDTO;
import com.jsowell.pile.vo.ThirdPartySecretInfoVO;
import com.jsowell.thirdparty.platform.util.Cryptos;
import com.jsowell.thirdparty.platform.util.GBSignUtils;
import com.jsowell.thirdparty.service.ThirdpartySecretInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RestController;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;

/**
 * 内蒙古接口
 */
@Anonymous
@RestController
public class ThirdPartyBaseController extends BaseController {

    // @Autowired
    // @Qualifier("zhongDianLianPlatformServiceImpl")
    // private ThirdPartyPlatformService platformLogic;

    @Autowired
    private ThirdpartySecretInfoService thirdpartySecretInfoService;

    /**
     * 获取token接口
     * http://localhost:8080/query_token
     */
    // @PostMapping("/query_token")
    // public CommonResult<?> queryToken(@RequestBody CommonParamsDTO dto) {
    //     logger.info("平台请求令牌 params:{}", JSON.toJSONString(dto));
    //     try {
    //         Map<String, String> map = platformLogic.queryToken(dto);
    //         logger.info("平台请求令牌 result:{}", JSON.toJSONString(map));
    //         return CommonResult.success(0, "请求令牌成功！", map.get("Data"), map.get("Sig"));
    //     } catch (Exception e) {
    //         logger.error("平台请求令牌接口 异常", e);
    //         return CommonResult.failed("获取token发生异常");
    //     }
    // }

    /**
     * 验证token
     */
    protected boolean verifyToken(String token) {
        if (StringUtils.equals(token, "jsowellTest")) {
            // 为了方便测试，token为jsowellTest校验通过
            return true;
        }
        boolean result;
        try {
            result = JWTUtils.checkThirdPartyToken(token);
        } catch (Exception e) {
            result = false;
        }
        return result;
    }

    /**
     * 解析DTO
     * @param dto
     * @param targetClass
     * @return
     * @param <T>
     */
    protected <T> T parseParamsDTO(CommonParamsDTO dto, Class<T> targetClass) throws NoSuchFieldException, IllegalAccessException {
        // 解密
        String operatorId = StringUtils.isNotBlank(dto.getOperatorID()) ? dto.getOperatorID() : dto.getPlatformID();
        // 通过operatorId 查出 operatorSecret
        ThirdPartySecretInfoVO secretInfoVO = thirdpartySecretInfoService.queryByOperatorId(operatorId);
        if (secretInfoVO == null) {
            throw new BusinessException("1", "无此对接平台");
        }

        String dataSecret = secretInfoVO.getOurDataSecret();
        String dataSecretIv = secretInfoVO.getOurDataSecretIv();

        // 解密data 获取参数中的OperatorSecret
        String decrypt = Cryptos.decrypt(dto.getData(), dataSecret, dataSecretIv);
        T t = JSONObject.parseObject(decrypt, targetClass);

        // 校验是否有operatorId, 没有就set
        verifyOperatorId(dto, t);

        return t;
    }

    /**
     * 获取OperatorId的值 verify
     * @param t
     * @return
     * @throws NoSuchFieldException
     * @throws IllegalAccessException
     */
    private <T> void verifyOperatorId(CommonParamsDTO dto, T t) throws NoSuchFieldException, IllegalAccessException {
        String targetFieldName = "operatorId";
        String operatorId = (String) getFieldValueByObject(t, targetFieldName);
        if (StringUtils.isBlank(operatorId)) {
            setFieldValueByFieldName(t, targetFieldName, dto.getOperatorID());
        }
    }

    private <T> void setFieldValueByFieldName(T t, String targetFieldName, Object value) {
        // 获取该对象的class
        Class<? extends Object> tClass = t.getClass();
        // 获取所有的属性数组
        Field[] fields = tClass.getDeclaredFields();

        for (Field field : fields) {
            // 属性名称
            String currentFieldName = "";
            try {
                boolean has_JsonProperty = field.isAnnotationPresent(JsonProperty.class);
                if (has_JsonProperty) {
                    currentFieldName = field.getAnnotation(JsonProperty.class).value();
                } else {
                    currentFieldName = field.getName();
                }
                // 忽略大小写对比
                if (currentFieldName.equalsIgnoreCase(targetFieldName)) {
                    // 取消语言访问检查
                    field.setAccessible(true);
                    // 给变量赋值
                    field.set(t, value);
                    return;
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * 使用反射获取字段值
     */
    private <T> Object getFieldValueByObject(T t, String targetFieldName) throws NoSuchFieldException, IllegalAccessException {
        // 获取该对象的class
        Class<? extends Object> tClass = t.getClass();
        // 获取所有的属性数组
        Field[] fields = tClass.getDeclaredFields();
        /**
         * 这里只需要 id 这个属性，所以直接取 fields[0] 这
         * 一个，如果id不是排在第一位，自己取相应的位置，
         * 如果有需要，可以写成for循环，遍历全部属性
         */

        for (Field field : fields) {
            // 属性名称
            String currentFieldName = "";
            // 获取属性上面的注解 import com.fasterxml.jackson.annotation.JsonProperty;
            /**
             * 举例： @JsonProperty("roleIds")
             * private String roleIds;
             */

            try {
                boolean has_JsonProperty = field.isAnnotationPresent(JsonProperty.class);

                if (has_JsonProperty) {
                    currentFieldName = field.getAnnotation(JsonProperty.class).value();
                } else {
                    currentFieldName = field.getName();
                }

                // 忽略大小写对比
                if (currentFieldName.equalsIgnoreCase(targetFieldName)) {
                    field.setAccessible(true);
                    currentFieldName = currentFieldName.replaceFirst(currentFieldName.substring(0, 1), currentFieldName.substring(0, 1).toUpperCase());
                    //整合出 getId() 属性这个方法
                    Method m = tClass.getMethod("get" + currentFieldName);
                    return m.invoke(t);
                }

            } catch (SecurityException e) {
                // 安全性异常
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                // 非法参数
                e.printStackTrace();
            } catch (IllegalAccessException | NoSuchMethodException e) {
                // 无访问权限
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                throw new RuntimeException(e);
            }
        }

        return null;
    }

    /**
     * 校验签名
     *
     * verifySignature
     */
    protected boolean verifySignature(CommonParamsDTO dto) {
        // 查询密钥
        String operatorId = StringUtils.isNotBlank(dto.getOperatorID()) ? dto.getOperatorID() : dto.getPlatformID();
        ThirdPartySecretInfoVO secretInfoVO = thirdpartySecretInfoService.queryByOperatorId(operatorId);
        if (secretInfoVO == null) {
            throw new BusinessException("1", "无此对接平台");
        }
        // 校验签名，使用响应方的密钥
        String signSecret = secretInfoVO.getOurSigSecret();

        Map<String, String> map = Maps.newLinkedHashMap();
        String operatorID = dto.getOperatorID();
        if (StringUtils.isNotBlank(operatorID)) {
            map.put("OperatorID", operatorID);
        }
        String platformID = dto.getPlatformID();
        if (StringUtils.isNotBlank(platformID)) {
            map.put("PlatformID", platformID);
        }
        String data = dto.getData();
        if (StringUtils.isNotBlank(data)) {
            map.put("Data", data);
        }
        String timeStamp = dto.getTimeStamp();
        if (StringUtils.isNotBlank(timeStamp)) {
            map.put("TimeStamp", timeStamp);
        }
        String seq = dto.getSeq();
        if (StringUtils.isNotBlank(seq)) {
            map.put("Seq", seq);
        }

        // 计算sign
        String sign = GBSignUtils.sign(map, signSecret);
        return StringUtils.equals(dto.getSig(), sign);
    }

}
