package com.ms.biz.tool;

import java.io.IOException;
import java.math.BigDecimal;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.setting.dialect.Props;
import com.doudian.open.core.DoudianOpResponse;
import com.ms.biz.common.Ret;
import com.ms.biz.common.StrObjMap;
import com.ms.biz.consts.CommonConst;
import lombok.extern.slf4j.Slf4j;
import org.modelmapper.ModelMapper;

@Slf4j
public class CommonTool {

    private static final Props props;

    static {
        props = new Props("application.properties", CharsetUtil.CHARSET_UTF_8);
    }

    public static final Map<String, String> ADMIN_REAL_SELF_SHOP_MAP = new HashMap<>();

    static {
        ADMIN_REAL_SELF_SHOP_MAP.put("16700961", "漂亮毛衣");
        ADMIN_REAL_SELF_SHOP_MAP.put("16412356", "时尚喇叭裤");
        ADMIN_REAL_SELF_SHOP_MAP.put("4463798", "抖店开放平台测试专用店");
        ADMIN_REAL_SELF_SHOP_MAP.put("30450753", "我的滑板鞋");
        ADMIN_REAL_SELF_SHOP_MAP.put("30459766", "蕾丝袜");
    }

    public static Map<String, String> adminRealSelfShopList() {
        return ADMIN_REAL_SELF_SHOP_MAP;
    }

    /*
     * 订单id有没有以A结尾 没有则拼接上去
     */
    public static String rebuildDdorderIdSuffix(String orderId) {
        String suffix = "A";
        if (!orderId.endsWith(suffix)) {
            return orderId + suffix;
        }
        return orderId;
    }

    public static boolean checkDdApiRequestIsSuccess(DoudianOpResponse<?> response) {
        boolean isSuccess = false;
        if (response.isSuccess() || "50002".equals(response.getCode())) {
            // 请求成功 或业务处理失败
            isSuccess = true;
        }
        if ("isv.business-failed:10901".equals(response.getSubCode()) || "'isv.business-failed: 10801".equals(response.getSubCode())) {
            isSuccess = true;

        }
        return isSuccess;
    }

    public static String buildDdProductUrl(String productId) {
        return String.format("https://haohuo.jinritemai.com/views/product/detail?id=%s", productId);
    }

    public static String ensconceString(String string, String type) {
        if (string.isEmpty()) {
            return string;
        }
        if ("mobile".equals(type) && !string.matches("^[0-9-\\\\s]{6,}$")) {
            type = "";
        }
        String newString = "";
        switch (type) {
            case "mobile":
                newString = string.substring(0, 3) + "***" + string.substring(7);
                break;
            case "sensitiveName":
                int strlen = string.length();
                if (strlen <= 2) {
                    String strBegin = string.substring(0, 1);
                    newString = strBegin + "*";
                } else {
                    String strBegin = string.substring(0, 1);
                    String strEnd = string.substring(strlen - 1);
                    newString = strBegin + "*" + strEnd;
                }
                break;
            case "sensitiveAddress":
                HashMap<String, String> chineseNumAndNumMap = new HashMap<>();
                chineseNumAndNumMap.put("一", "1");
                chineseNumAndNumMap.put("二", "2");
                chineseNumAndNumMap.put("三", "3");
                chineseNumAndNumMap.put("四", "4");
                chineseNumAndNumMap.put("五", "5");
                chineseNumAndNumMap.put("六", "6");
                chineseNumAndNumMap.put("七", "7");
                chineseNumAndNumMap.put("八", "8");
                chineseNumAndNumMap.put("九", "9");
                chineseNumAndNumMap.put("壹", "1");
                chineseNumAndNumMap.put("贰", "2");
                chineseNumAndNumMap.put("叁", "3");
                chineseNumAndNumMap.put("肆", "4");
                chineseNumAndNumMap.put("伍", "5");
                chineseNumAndNumMap.put("陆", "6");
                chineseNumAndNumMap.put("柒", "7");
                chineseNumAndNumMap.put("捌", "8");
                chineseNumAndNumMap.put("玖", "9");
                chineseNumAndNumMap.put("零", "0");
                chineseNumAndNumMap.put("十", "10");
                for (Map.Entry<String, String> entry : chineseNumAndNumMap.entrySet()) {
                    string = string.replace(entry.getKey(), entry.getValue());
                }
                boolean hasNum = string.matches(".[0-9].");
                if (hasNum) {
                    newString = string.replaceAll("[0-9]", "*");
                } else {
                    newString = string;
                }
                break;
            case "sensitiveMobile":
                newString = string.substring(0, 2) + "*******" + string.substring(9);
                break;
            default:
                strlen = string.length();
                if (strlen >= 6) {
                    String strBegin = string.substring(0, 2);
                    String strEnd = string.substring(strlen - 2);
                    newString = strBegin + "**" + strEnd;
                } else if (strlen <= 2) {
                    String strBegin = string.substring(0, 1);
                    newString = strBegin + "*";
                } else {
                    String strBegin = string.substring(0, 1);
                    String strEnd = string.substring(strlen - 1);
                    newString = strBegin + "*" + strEnd;
                }
                break;
        }
        return newString;
    }

    public static String encrypt(String plaintext, Long shopId) {
        if (plaintext.isEmpty()) {
            return plaintext;
        }
        String key = props.getProperty("shop.encrypt.key");
        String password = String.format("%s*%s", key, (int) (shopId / 19));
        try {
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            SecretKeySpec secretKey = new SecretKeySpec(password.getBytes(StandardCharsets.UTF_8), "AES");
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
            byte[] encryptedBytes = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));
            return Base64.getEncoder().encodeToString(encryptedBytes);
        } catch (Exception ex) {
            return null;
        }
    }

    public static String decrypt(String encrypted, Long shopId) {
        if (encrypted.isEmpty()) {
            return encrypted;
        }
        String key = props.getProperty("shop.encrypt.key");
        String password = String.format("%s*%s", key, (int) (shopId / 19));
        try {
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            SecretKeySpec secretKey = new SecretKeySpec(password.getBytes(StandardCharsets.UTF_8), "AES");
            cipher.init(Cipher.DECRYPT_MODE, secretKey);
            byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(encrypted));
            return new String(decryptedBytes, StandardCharsets.UTF_8);
        } catch (Exception ex) {
            return null;
        }
    }

    public static String[] toStrArray(String str) {
        return toStrArray(",", str);
    }

    public static String[] toStrArray(String split, String str) {
        return StrUtil.isBlank(str) ? new String[0] : str.split(split);
    }

    public static List<String> toStrList(String str) {
        return Arrays.asList(toStrArray(str));
    }

    public static List<String> toStrList(String split, String str) {
        return Arrays.asList(toStrArray(split, str));
    }

    public static String getStrNow() {
        return DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(LocalDateTime.now());
    }

    public static Ret successResult() {
        Ret ret = new Ret();
        ret.setResult(CommonConst.SUCCESS);
        return ret;
    }

    public static Ret successResult(String key, Object value) {
        Ret ret = new Ret();
        ret.setResult(CommonConst.SUCCESS);
        StrObjMap strObjMap = new StrObjMap();
        strObjMap.put(key, value);
        ret.setData(strObjMap);
        return ret;
    }

    public static Ret failResult() {
        Ret ret = new Ret();
        ret.setResult(CommonConst.FAIL);
        return ret;
    }

    public static Ret failResult(String reason) {
        Ret ret = new Ret();
        ret.setResult(CommonConst.FAIL);
        ret.setReason(reason);
        return ret;
    }
    public static Ret failCodeResult(String code, String msg) {
        Ret ret = new Ret();
        ret.setResult(CommonConst.FAIL);
        ret.setCode(code);
        ret.setReason(msg);
        return ret;
    }
    public static Ret failCodeResult(String code, String msg,Map data) {
        Ret ret = new Ret();
        ret.setResult(CommonConst.FAIL);
        ret.setCode(code);
        ret.setReason(msg);
        ret.setData(data);
        return ret;
    }

    public static Ret failCodeResult(String code, String msg, String subMsg, String logId) {
        Ret ret = new Ret();
        ret.setResult(CommonConst.FAIL);
        ret.setCode(code);
        ret.setReason(msg);
        ret.setSolution(subMsg);
        ret.setLogId(logId);
        return ret;
    }

    public static Ret failResult(String key, Object value) {
        Ret ret = new Ret();
        ret.setResult(CommonConst.FAIL);
        StrObjMap strObjMap = new StrObjMap();
        strObjMap.put(key, value);
        ret.setData(strObjMap);
        return ret;
    }

    public static boolean isSuccessRet(Ret ret) {
        return ret.getResult().equals(CommonConst.SUCCESS);
    }

    public static boolean isFailRet(Ret ret) {
        return ret.getResult().equals(CommonConst.FAIL);
    }

    public static Date curDate() {
        return new Date();
    }

    public static List<String> convertValToArray(Object val) {
        if (val instanceof String) {
            return splitWithComma(val.toString());
        }
        return new ArrayList<>();
    }

    public static String stringToSQLLike(String keyword) {
        return "'%".concat(keyword).concat("%'");
    }

    public static String stringToSQLIN(List<String> list) {
        return "'".concat(StrUtil.join("','", list)).concat("'");
    }

    public static String intToSQLIN(List<Integer> list) {
        return StrUtil.join(",", list);
    }

    public static String smd5Value(String value) {
        if (ObjectUtil.isNull(value)) {
            return null;
        }
        if (StrUtil.isBlank(value)) {
            return "";
        }
        String smd5Key1 = props.getProperty("smd5.key1");
        String smd5Key2 = props.getProperty("smd5.key2");
        return SecureUtil.md5(SecureUtil.md5(smd5Key1.concat(value)).concat(smd5Key2));
    }

    public static double correctCentToYuan(Double price) {
        if (ObjectUtil.isNull(price)) {
            return 0;
        }
        return price == 0 ? 0 : Math.round((price / 100) * 100.0) / 100.0;
    }

    public static double correctCentToYuan(Integer price) {
        if (ObjectUtil.isNull(price)) {
            return 0;
        }
        return price == 0 ? 0 : Math.round((price / 100.0) * 100.0) / 100.0;
    }

    public static double correctCentToYuan(Long price) {
        if (ObjectUtil.isNull(price)) {
            return 0;
        }
        return price == 0 ? 0 : Math.round((price / 100.0) * 100.0) / 100.0;
    }

    public static String removeQuotes(String input) {
        if (input.startsWith("\"") && input.endsWith("\"")) {
            return input.substring(1, input.length() - 1);
        }
        return input;
    }

    /**
     * 翻译route把大字字母转换成下划线加小写字母
     */
    public static String transLateRoute(String string) {
        StringBuilder translateString = new StringBuilder();
        for (int i = 0; i < string.length(); i++) {
            if (string.charAt(i) >= 65 && string.charAt(i) <= 90) {
                translateString.append((i != 0) ? ("_" + (char) (string.charAt(i) + 32)) : (char) (string.charAt(i) + 32)); // 将大写字母转换成小写，且非首字母转换的加个下划线
            } else {
                translateString.append(string.charAt(i));
            }
        }
        return translateString.toString();
    }

    public static List<String> splitWithComma(String keywordString) {
        if (keywordString == null || keywordString.isEmpty()) {
            return new ArrayList<>();
        }

        String[] splitArray = keywordString.split("[,，\\s\\|；]");
        return Arrays.stream(splitArray)
            .map(String::trim)
            .filter(s -> !s.isEmpty())
            .collect(Collectors.toList());
    }

    public static List<Long> arrayDiff(List<Long> list1, List<Long> list2) {
        List<Long> diff = new ArrayList<>(list1);
        diff.removeAll(list2);
        return diff;
    }

    public static String getCurMonthLastTime() {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime lastTime = LocalDateTime.of(now.getYear(), now.getMonth(), 1, 0, 0, 0);
        return lastTime.plusMonths(1).minusSeconds(1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
    }

    /**
     * 把list中对象的某个属性作为key，对象作为value，转换成map
     *
     * @param list
     * @param keyFunction
     * @param <T>
     * @param <K>
     * @return
     */
    public static <T, K> Map<K, T> convertListToMap(List<T> list, Function<T, K> keyFunction) {
        Map<K, T> resultMap = new HashMap<>();
        for (T item : list) {
            resultMap.put(keyFunction.apply(item), item);
        }
        return resultMap;
    }

    /**
     * 把大Map切成多个小Map
     *
     * @param original
     * @param chunkSize
     * @param <K>
     * @param <V>
     * @return
     */
    public static <K, V> List<Map<K, V>> chunkMap(Map<K, V> original, int chunkSize) {
        List<Map<K, V>> chunkedList = new ArrayList<>();
        Map<K, V> chunk = new LinkedHashMap<>(chunkSize);  // 使用LinkedHashMap以保持顺序

        int count = 0;
        for (Map.Entry<K, V> entry : original.entrySet()) {
            chunk.put(entry.getKey(), entry.getValue());

            if (++count % chunkSize == 0) {
                chunkedList.add(chunk);
                chunk = new LinkedHashMap<>(chunkSize);
            }
        }

        if (!chunk.isEmpty()) {
            chunkedList.add(chunk);
        }

        return chunkedList;
    }

    /**
     * 把大List切成多个小List
     *
     * @param original
     * @param chunkSize
     * @param <T>
     * @return
     */
    public static <T> List<List<T>> chunkList(List<T> original, int chunkSize) {
        List<List<T>> chunkedList = new ArrayList<>();

        for (int i = 0; i < original.size(); i += chunkSize) {
            int end = Math.min(i + chunkSize, original.size());  // 确保不超过原始列表的大小
            chunkedList.add(new ArrayList<>(original.subList(i, end)));
        }

        return chunkedList;
    }

    /**
     * 将一个实体的属性值复制到另一个实体
     *
     * @param source
     * @param destinationType
     * @param <D>
     * @return
     */
    public static <D> D modelMapper(Object source, Class<D> destinationType) {
        ModelMapper modelMapper = new ModelMapper();
        return modelMapper.map(source, destinationType);
    }

    public static Ret checkDdApiRetStatus(DoudianOpResponse responseMap) {
        int code = Integer.valueOf(responseMap.getCode());
        String msg = responseMap.getMsg();
        String subMsg = responseMap.getSubMsg();
        String logId = responseMap.getLogId();

        if (code == 10000) {
            return CommonTool.successResult();
        } else if (code == 504 || code == 400 || code == 505 || code == 0) {
            return CommonTool.failCodeResult(responseMap.getCode(), responseMap.getMsg() + responseMap.getSubMsg(), responseMap.getSubMsg(), responseMap.getLogId());
        } else {
            return CommonTool.failCodeResult(responseMap.getCode(), responseMap.getMsg() + responseMap.getSubMsg(), responseMap.getSubMsg(), responseMap.getLogId());
        }
    }

    public static long getTimeStampByDateStr(String dateStr) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            Date date = sdf.parse(dateStr);
            return date.getTime();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }

    public static boolean checkIsFrequencyLimitReason(String reason) {
        return reason.contains("限流");
    }

    public static boolean checkIsSystemBusyReason(String reason) {
        return reason.contains("系统繁忙，请稍后再试");
    }

    public static void randomSleep() {
        try {
            int randomMicroseconds = ThreadLocalRandom.current().nextInt(1000000, 5000000 + 1);
            int randomMilliseconds = randomMicroseconds / 1000;
            Thread.sleep(randomMilliseconds);
        } catch (Throwable e) {
            log.error("randomSleep 异常");
        }
    }

    /**
     * 格式化价格
     *
     * @param number
     * @param decimals
     * @return
     */
    public static double numFormat(double number, int decimals) {
        StringBuilder pattern = new StringBuilder("#.");
        for (int i = 0; i < decimals; i++) {
            pattern.append("#");
        }

        DecimalFormat decimalFormat = new DecimalFormat(pattern.toString());
        String formattedString = decimalFormat.format(number);
        return Double.parseDouble(formattedString);
    }

    /**
     * 去除价格末尾的0
     *
     * @param price
     * @return
     */
    public static String[] splitAndTrim(String price) {
        String trimmedPrice;
        while (price.endsWith("0")) {
            trimmedPrice = price.substring(0, price.length() - 1);
            price = trimmedPrice;
        }

        return price.split("\\.");
    }

    /**
     * 计算字符串长度，汉字算2，英文数字算1
     *
     * @param str
     * @return
     */
    public static int countStrLen(String str) {
        int length = 0;
        for (char c : str.toCharArray()) {
            if (Character.UnicodeScript.of(c) == Character.UnicodeScript.HAN) {
                length += 2;
            } else {
                length += 1;
            }
        }
        return length;
    }

    /**
     * 截取字符串，汉字算2，英文数字算1
     *
     * @param str
     * @param len
     * @return
     */
    public static String substringByLen(String str, int len) {
        int length = 0;
        StringBuilder result = new StringBuilder();

        for (char c : str.toCharArray()) {
            if (Character.UnicodeScript.of(c) == Character.UnicodeScript.HAN) {
                if (length + 2 > len) {
                    break;
                }
                length += 2;
            } else {
                if (length + 1 > len) {
                    break;
                }
                length += 1;
            }
            result.append(c);
        }

        return result.toString();
    }

    /**
     * 判断是否有空值
     *
     * @param objs
     * @return
     */
    public static boolean anyEmpty(Object... objs) {
        for (Object obj : objs) {
            if (obj == null) {
                return true;
            }
            if (obj instanceof String && ((String) obj).isEmpty()) {
                return true;
            }
        }
        return false;
    }

    /**
     * 数组转List
     *
     * @param array
     * @param <T>
     * @return
     */
    public static <T> List<T> convertArrayToList(T[] array) {
        return Arrays.stream(array).collect(Collectors.toList());
    }

    public static boolean isTrue(int input) {
        return input == 1;
    }

    /**
     * 获取html中的图片url
     *
     * @param input
     * @return
     */
    public static List<String> getUrlsFromHtml(String input) {
        List<String> matchUrls = new ArrayList<>();
        Pattern pattern = Pattern.compile("<img[^>]*src=[\"']([^\"']+)[\"'][^>]*>");
        Matcher matcher = pattern.matcher(input);
        while (matcher.find()) {
            matchUrls.add(matcher.group(1));
        }
        return matchUrls;
    }

    public static void main(String[] args) {

        System.out.println(splitWithComma("6921394317136631525|6921399584322230185|6921393247513351270|6921412710844995353"));
    }

    public static int getRandom(int x, int y) {
        int num = -1;
        //两个数在合法范围内，并不限制输入的数哪个更大一些
        if (x < 0 || y < 0) {
            return num;
        } else {
            int max = Math.max(x, y);
            int min = Math.min(x, y);
            int mid = max - min;//求差
            //产生随机数
            num = (int) (Math.random() * (mid + 1)) + min;
        }
        return num;
    }

    public static String updateProductImgDomain(String imgUrl) {
        String newImgUrl = imgUrl;

        if (imgUrl.contains("cdn-tos.pstatp.com/obj")) {
            String[] parts = imgUrl.split("/obj");
            newImgUrl = imgUrl.replace(parts[1], "lf3-cm.ecombdstatic.com");
        }

        if (imgUrl.contains("cdn-tos.pstatp.com/img")) {
            String[] parts = imgUrl.split("/img");
            newImgUrl = imgUrl.replace(parts[1], "p3-aio.ecombdimg.com");
        }

        if (imgUrl.contains("p3.pstatp.com")) {
            newImgUrl = imgUrl.replace("p3.pstatp.com", "p3-aio.ecombdimg.com");
        }

        if (imgUrl.contains("p3a.pstatp.com")) {
            newImgUrl = imgUrl.replace("p3a.pstatp.com", "p3-aio.ecombdimg.com");
        }

        if (LocalDate.now().isAfter(LocalDate.of(2021, 11, 1))) {
            // 用于抖店202110月修改图片域名，讲道理11月之后可以删除此方法,后续如果没有以下log可以删除此方法及其调用
        }

        if (!imgUrl.matches("^http(s)?://.+")) {
            newImgUrl = "https:" + imgUrl;
        }

        return newImgUrl;
    }

    public static String clearAliasSpechars(String subject) {
        subject = subject.replace("（", "(")
            .replace("）", ")")
            .replace("—", "-")
            .replace("－", "-")
            .replace("×", "x");

        String filterSubject = subject.replaceAll("[^a-zA-Z0-9\\u4e00-\\u9fa5\\s@#\\\\$%&+\\-\\/\\\\\\\\_()=.*!]", "");
        return filterSubject.isEmpty() ? subject : filterSubject;
    }

    public static <K, V> Map<K, V> sliceMap(Map<K, V> inputMap, int count) {
        Map<K, V> resultMap = new LinkedHashMap<>();

        int i = 0;
        for (Map.Entry<K, V> entry : inputMap.entrySet()) {
            if (i++ == count) break;
            resultMap.put(entry.getKey(), entry.getValue());
        }

        return resultMap;
    }

    public static String unifiedDateFormat(String date, String format) {
        try {
            LocalDate parsedDate = LocalDate.parse(date);
            return parsedDate.format(DateTimeFormatter.ofPattern(format));
        } catch (DateTimeParseException e) {
            DateTimeFormatter originalFormat = null;

            if (date.contains(".")) {
                originalFormat = DateTimeFormatter.ofPattern("yyyy.MM.dd");
            } else if (date.contains("年") && date.contains("月") && date.contains("日")) {
                originalFormat = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
            }

            if (originalFormat != null) {
                try {
                    LocalDate parsedDate = LocalDate.parse(date, originalFormat);
                    return parsedDate.format(DateTimeFormatter.ofPattern(format));
                } catch (DateTimeParseException ex) {
                }
            }
        }
        return null;
    }

    public static boolean checkHasOtherKeyword(String word) {
        if (word.contains("其它") || word.contains("其他") || word.contains("通用")) {
            return true;
        } else {
            return false;
        }
    }

    public static boolean checkNeedUploadOssImgUrl(String imageUrl) {
        String[] needles = {
            "k3cdn",
            "t.shuaishou.com"
        };
        boolean isNeedUploadOss = false;
        for (String needle : needles) {
            if (imageUrl.contains(needle)) {
                isNeedUploadOss = true;
                break;
            }
        }

        return isNeedUploadOss;
    }

    public static boolean isGifImage(String imgUrls) {
        if (imgUrls == null || imgUrls.length() == 0) {
            return false;
        }

        Ret fileTypeAndSize = getFileTypeAndSize(imgUrls);
        if (CommonTool.isFailRet(fileTypeAndSize)){
            return false;
        }else {
            if (fileTypeAndSize.getData().containsKey("type") && "gif".equals(fileTypeAndSize.getData().get("type"))) {
                return true;
            }
        }
        return false;
    }

    public static Ret getFileTypeAndSize(String urlStr) {
        StrObjMap result = new StrObjMap();
        try {
            URL url = new URL(urlStr);
            URLConnection conn = url.openConnection();
            String contentType = conn.getContentType();
            if (contentType != null) {
                result.put("type", contentType);
            } else {
                System.out.println("无法确定文件类型");
            }

            int contentLength = conn.getContentLength();

            if (contentLength != -1) {
                result.put("contentLength", contentLength);
            } else {
                System.out.println("无法确定文件大小");
            }
        } catch (IOException e) {
            e.printStackTrace();
            return Ret.fail(e.getMessage());
        }
        return Ret.success(result);
    }

    public static boolean isAnimatedGif (byte[] imageData) {
        boolean animated = false;
        String imageDataString = new String(imageData);
        Pattern pattern = Pattern.compile("(\\x00\\x21\\xF9\\x04.{4}\\x00\\x2C.*){2,}");

        Matcher matcher = pattern.matcher(imageDataString);
        if(matcher.find()) {
            animated = true;
        } else {
            if(imageDataString.contains(String.valueOf((char) 0x21) + String.valueOf((char) 0xff) + String.valueOf((char) 0x0b) + "NETSCAPE2.0")) {
                animated = true;
            }
        }
        return animated;
    }

    public static String replaceOuterTagString(String search, String replace, String inputString) {
        List<String> matchStringList = new ArrayList<>();
        Pattern pattern = Pattern.compile("<[^<>]*>|[^<>]+?", Pattern.DOTALL);
        Matcher matcher = pattern.matcher(inputString);

        while (matcher.find()) {
            matchStringList.add(matcher.group());
        }

        StringBuilder outputString = new StringBuilder();
        for (String string : matchStringList) {
            if (string.matches("^<.*>$")) {
                outputString.append(string);
            } else {
                outputString.append(replaceIgnoreCase(search, replace,inputString));
            }
        }
        return outputString.toString();
    }

    public static String replaceIgnoreCase(String source, String target, String replacement){
        String lcsource = source.toLowerCase();
        String lctarget = target.toLowerCase();
        if(lcsource.contains(lctarget)){
            int i = lcsource.indexOf(lctarget);
            return source.substring(0, i) + replacement + replaceIgnoreCase(source.substring(i + target.length()), target, replacement);
        }
        return source;
    }

    public static String filterContent(Object filterWords, String needFilterString) {
        if (filterWords instanceof List<?>) {
            List<String> filterArray = new ArrayList<>(new HashSet<>((List<String>) filterWords));
            for (String filterWord : filterArray) {
                String filterWordPattern = getFilterWordPattern(filterWord);
                needFilterString = needFilterString.replaceAll(filterWordPattern, "");
            }
        } else {
            String filterWordPattern = getFilterWordPattern((String) filterWords);
            needFilterString = needFilterString.replaceAll(filterWordPattern, "");
        }
        return needFilterString;
    }

    private static String getFilterWordPattern(String filterString) {
        Pattern pattern = Pattern.compile(".");
        Matcher matcher = pattern.matcher(filterString);
        StringBuilder patternBuilder = new StringBuilder();

        while (matcher.find()) {
            String filterWord = matcher.group();
            if (filterWord.trim().isEmpty()) {
                continue;
            }
            filterWord = Pattern.quote(filterWord);
            filterWord = filterWord.replace("/", "\\/");
            patternBuilder.append("\\s*").append(filterWord);
        }

        return String.format("/%s/", patternBuilder.toString());
    }



    public static int calChineseStockNum(String stockNum) {
        if (stockNum.matches("^[0-9]*$")) {
            return Integer.parseInt(stockNum);
        }
        if (stockNum.matches("[\\d\\s]百$")) {
            return Integer.parseInt(stockNum.replaceAll("[\\D]", "")) * 100;
        }
        if (stockNum.matches("[\\d\\s]千$")) {
            return Integer.parseInt(stockNum.replaceAll("[\\D]", "")) * 1000;
        }
        if (stockNum.matches("[\\d\\s]万$")) {
            return Integer.parseInt(stockNum.replaceAll("[\\D]", "")) * 10000;
        }

        return -1; // 表示失败或无效输入
    }

    public static String cutTitle(String title, int cutLen, boolean cutHead) {
        int titleLen = countStringLength(title);
        if (cutLen >= titleLen) {
            return title;
        }
        int cNum = 0;
        StringBuilder tmpTitle = new StringBuilder();

        if (cutHead) {
            List<String> tempStrArr = new ArrayList<>();
            for (char c : new StringBuilder(title).reverse().toString().toCharArray()) {
                tempStrArr.add(String.valueOf(c));
            }
            title = String.join("", tempStrArr);
        }

        for (char c : title.toCharArray()) {
            int len = countStringLength(String.valueOf(c));
            cNum += len;
            if (cNum > cutLen) {
                break;
            }
            tmpTitle.append(c);
        }

        if (cutHead) {
            List<String> tempStrArr = new ArrayList<>();
            for (char c : new StringBuilder(tmpTitle.toString()).reverse().toString().toCharArray()) {
                tempStrArr.add(String.valueOf(c));
            }
            tmpTitle = new StringBuilder(String.join("", tempStrArr));
        }

        return tmpTitle.toString();
    }

    public static int countStringLength(String str) {
        int len = 0;
        for (char c : str.toCharArray()) {
            if (Character.UnicodeScript.of(c) == Character.UnicodeScript.HAN) {
                len += Character.charCount(c);
            } else {
                ++len;
            }
        }
        return len;
    }

    public static Object convertToNumericType(String value) {
        try {
            return Integer.parseInt(value);
        } catch (NumberFormatException e1) {
            try {
                return Long.parseLong(value);
            } catch (NumberFormatException e2) {
                try {
                    return Float.parseFloat(value);
                } catch (NumberFormatException e3) {
                    try {
                        return Double.parseDouble(value);
                    } catch (NumberFormatException e4) {
                        return null;
                    }
                }
            }
        }
    }

    public static boolean isMatch(String regex, String str) {
        return Pattern.compile(regex).matcher(str).find();
    }

    public static String mbSubString(String s, int length) throws Exception {
        byte[] bytes = s.getBytes("Unicode");
        int n = 0; // 表示当前的字节数
        int i = 2; // 要截取的字节数，从第3个字节开始
        for (; i < bytes.length && n < length; i++)
        {
            // 奇数位置，如3、5、7等，为UCS2编码中两个字节的第二个字节
            if (i % 2 == 1) {
                n++; // 在UCS2第二个字节时n加1
            } else {
                // 当UCS2编码的第一个字节不等于0时，该UCS2字符为汉字，一个汉字算两个字节
                if (bytes[i] != 0)
                {
                    n++;
                }
            }
        }
        // 如果i为奇数时，处理成偶数
        if (i % 2 == 1) {
            // 该UCS2字符是汉字时，去掉这个截一半的汉字
            if (bytes[i - 1] != 0) {
                i = i - 1;
            } else {
                // 该UCS2字符是字母或数字，则保留该字符
                i = i + 1;
            }
        }
        return new String(bytes, 0, i, "Unicode");
    }

    public static int convertStringToInt(String s) {
        if (s == null || s.isEmpty()) {
            return 0;
        }

        try {
            // 如果字符串表示的是整数
            return Integer.parseInt(s);
        } catch (NumberFormatException e) {
            try {
                // 如果字符串表示的是浮点数，舍去小数部分
                return (int) Double.parseDouble(s);
            } catch (NumberFormatException e2) {
                return 0;
            }
        }
    }

    public static Double noZeros(Double num) {
        BigDecimal value = new BigDecimal(num);
        //去除多余0
        BigDecimal noZeros = value.stripTrailingZeros();
        //BigDecimal => double
        return noZeros.doubleValue();
    }

    public static String doubleTrans(double d){
        double eps = 1e-10;
        //判断是否为整数
        if(d-Math.floor(d) < eps){
            return String.valueOf((long)d);
        }
        DecimalFormat df = new DecimalFormat("#.#####");
        return df.format(d);
    }

    public static Date parseDate(String timeStr) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date;
        try {
            date = dateFormat.parse(timeStr);
        } catch (java.text.ParseException e) {
            throw new RuntimeException("时间格式错误");
        }
        return date;
    }
}
