package com.jeequan.jeepay.core.utils;

import cn.hutool.core.net.url.UrlBuilder;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.core.constants.CS;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;

/*
* String 工具类
*
* @author terrfly
*
* @date 2021/6/8 16:58
*/
@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class StringKit {

	public static String getUUID(){
		return UUID.randomUUID().toString().replace("-", "") + Thread.currentThread().getId();
	}

	public static String getUUID(int endAt){
		return getUUID().substring(0, endAt);
	}

	/** 拼接url参数 **/
	public static String appendUrlQuery(String url, Map<String, Object> map) {
		if (StringUtils.isEmpty(url) || map == null || map.isEmpty()) {
			return url;
		}

		StringBuilder sb = new StringBuilder(url);
		if (!url.contains("?")) {
			sb.append("?");
		}

		final boolean[] hasQueryCondition = {url.contains("=")};

		String query = map.entrySet().stream()
				.filter(entry -> Objects.nonNull(entry.getKey()) && Objects.nonNull(entry.getValue()))
				.map(entry -> {
					try {
						String encodedValue = URLEncoder.encode(entry.getValue().toString(), "UTF-8");
						return entry.getKey() + "=" + encodedValue;
					} catch (UnsupportedEncodingException e) {
						log.info("urlEncoding异常", e);
						return "";
					}
				})
				.filter(s -> !s.isEmpty())
				.reduce((s1, s2) -> s1 + "&" + s2)
				.orElse("");
		return sb.append(query).toString();
	}


	/** 拼接url参数: 旧版采用Hutool方式（当回调地址是 http://abc.com/#/abc 时存在位置问题） **/
	@Deprecated
	public static String appendUrlQueryWithHutool(String url, Map<String, Object> map){

		if(StringUtils.isEmpty(url) || map == null || map.isEmpty()){
			return url;
		}
		UrlBuilder result = UrlBuilder.of(url);
		map.forEach((k, v) -> {
			if(k != null && v != null){
				result.addQuery(k, v.toString());
			}
		});

		return result.build();
	}

	/** 是否 http 或 https连接 **/
	public static boolean isAvailableUrl(String url){

		if(StringUtils.isEmpty(url)){
			return false;
		}

		return url.startsWith("http://") ||url.startsWith("https://");
	}


	/**
	 * 对字符加星号处理：除前面几位和后面几位外，其他的字符以星号代替
	 *
	 * @param content 传入的字符串
	 * @param frontNum 保留前面字符的位数
	 * @param endNum 保留后面字符的位数
	 * @param starNum 指定star的数量
	 * @return 带星号的字符串
	 */
	@Deprecated
	public static String str2Star(String content, int frontNum, int endNum, int starNum) {

		// 兼容旧版的引用， 全部使用新的脱敏规则。
        return autoDesensitization(content);
    }


	/**
	 * 合并两个json字符串
	 * key相同，则后者覆盖前者的值
	 * key不同，则合并至前者
	 * @param originStr
	 * @param mergeStr
	 * @return 合并后的json字符串
	 */
	public static String marge(String originStr, String mergeStr, String ifCode) {

		if (StringUtils.isAnyBlank(originStr, mergeStr)) {
			return null;
		}

		JSONObject originJSON = JSON.parseObject(originStr);
		JSONObject mergeJSON = JSON.parseObject(mergeStr);

		if (originJSON == null || mergeJSON == null) {
			return null;
		}

		// 支付宝， 特殊判断
		if(CS.IF_CODE.ALIPAY.equals(ifCode)){
			JSONObject litePramsByOrigin = originJSON.getJSONObject("liteParams");
			JSONObject litePramsByMerge = mergeJSON.getJSONObject("liteParams");
			if(litePramsByOrigin != null && litePramsByMerge != null){
				originJSON.putAll(mergeJSON);
				litePramsByOrigin.putAll(litePramsByMerge);
				originJSON.put("liteParams", litePramsByOrigin);
				return originJSON.toJSONString();
			}
		}

		originJSON.putAll(mergeJSON);
		return originJSON.toJSONString();
	}


	/*
	 * 功能描述: 数据自动脱敏
	 * @param str
	 * @Return: java.lang.String
	 * @Author: terrfly
	 * @Date: 2021/7/20 17:07
	 */
	public static String autoDesensitization(String str){

		if(StringUtils.isEmpty(str)){
			return str;
		}

		int len = str.length();

		//小于等于三位 格式为：  **A
		if(len <= 3) {
			// 1位
			return len == 1 ? "*" : StringUtils.repeat("*", len - 1) + str.substring(len - 1);
		}

		// 公式： 脱敏数据占据2/3 的范围。
		// 假设： 采用6的倍数组进行循环（最少两组）  循环次数为：n, 原始位数为 x, 加密数据为原始数据的两倍即 2x ,
		// 即： 6x·n = len， 缩小范围使得x=n，即： 7X=len
		int groupSize  = len / 7 + (len % 7 == 0 ? 0 : 1);

		// 截取原始字符串的位置
		int startIndex = 0;
		StringBuilder result = new StringBuilder(); //最终结果

		for (int i = 0; i < groupSize; i++) {
			int endIndex = Math.min(startIndex + 7, len);
			int dataSize = endIndex - startIndex;

			result.append(i == 0 ? str.substring(startIndex, startIndex + dataSize) : StringUtils.repeat("*", dataSize));
			startIndex = endIndex;
		}

		return result.toString();
	}



}
