<?php

namespace Application\Service\Extension\Helper;


use Application\Service\Exceptions\InvalidArgumentException;
use Application\Service\Extension\Validator\customer\NumberValidator;

class StringHelper
{
    /**
     * 生成哈希
     * @return string
     */
    public static function generateHashValue(): string
    {
        $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()+-';
        $random = $chars[mt_rand(0, 73)] .
            $chars[mt_rand(0, 73)] .
            $chars[mt_rand(0, 73)] .
            $chars[mt_rand(0, 73)] .
            $chars[mt_rand(0, 73)];//Random 5 times
        $content = uniqid() . $random;  // 类似 5443e09c27bf4aB4uT
        return sha1($content);
    }

    /**
     * 生成Uuid
     * @return string
     */
    public static function generateUuid(): string
    {
        return sprintf( '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',

            mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ),

            mt_rand( 0, 0xffff ),

            mt_rand( 0, 0x0fff ) | 0x4000,

            mt_rand( 0, 0x3fff ) | 0x8000,

            mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff )

        );
    }

    public static function normalizeNumber($value)
    {
        $value = (string) $value;

        $localeInfo = localeconv();
        $decimalSeparator = $localeInfo['decimal_point'] ?? null;

        if ($decimalSeparator !== null && $decimalSeparator !== '.') {
            $value = str_replace($decimalSeparator, '.', $value);
        }

        return $value;
    }

    public static function floatToString($number)
    {
        return str_replace(',', '.', (string) $number);
    }

    /**
     * 字符串转浮点数
     * @param string $string
     * @param int $decimalPoint
     * @return mixed|string
     */
    public static function stringToFloat(string $string, int $decimalPoint)
    {
        $normalize = self::normalizeNumber($string);

        $v = new NumberValidator();
        $v->integerOnly = false;

        if ($v->isValid($string, '') || !is_numeric($normalize)) {
            return '请填写正确的数字。';
        }

        $isMatched = preg_match("/^[-+]?[0-9]*\.?([0-9]){1,$decimalPoint}/", $string, $matches);

        if (!$matches || count($matches) < 1) {
            return '无法转换成浮点数。';
        }

        return sprintf("%01.{$decimalPoint}f", current($matches));
    }

    /**
     * 解析json
     * @param string $jsonString json字符串
     * @param bool $isThrowException 是否抛出异常
     * @return false|mixed
     */
    public static function jsonDecode($jsonString, bool $isThrowException = true)
    {
        if (is_array($jsonString)) {
            return $jsonString;
        }

        if ($jsonString === '' || $jsonString === null) {
            $jsonString = '[]';
        }

        if (!is_string($jsonString)) {
            if ($isThrowException) {
                throw new InvalidArgumentException("json 解析失败。无法解析的数据类型。");
            }
            return false;
        }

        // 化验单json数据
        $jsonData = json_decode($jsonString, true);

        if (json_last_error() != JSON_ERROR_NONE) {
            if ($isThrowException) {
                throw new \Exception("json 解析失败!");
//                throw new InvalidArgumentException("json 解析失败!");
            }
            return false;
        }

        return $jsonData;
    }

    public static function basename($path, $suffix = '')
    {
        $len = mb_strlen($suffix);
        if ($len > 0 && mb_substr($path, -$len) === $suffix) {
            $path = mb_substr($path, 0, -$len);
        }

        $path = rtrim(str_replace('\\', '/', $path), '/');
        $pos = mb_strrpos($path, '/');
        if ($pos !== false) {
            return mb_substr($path, $pos + 1);
        }

        return $path;
    }

    /**
     * 判断是否为空字符串
     * @param $str // 字符串
     * @param array|string[] $invalidStr 定义为空字符串的字符串
     * @return bool
     */
    public static function isEmpty($str, array $invalidStr = ['null', 'undefined']): bool
    {
        return $str === '' || $str === [] || $str === null || in_array($str, $invalidStr);
    }

    public static function generatetradeno():string
    {
        return time() . mt_rand(1000, 9999);
    }

    public static function generateTerminalTable($headers, $data): string
    {
        $row = [];
        foreach ($data as $key => $rowData) {
            $res = [];
            foreach ($rowData as $rowKey => $rowItem) {
                $res[] = "{$headers[$rowKey]}: <span style='color: red'>$rowItem</span>";
            }
            if ($res) {
                $row[] = implode(' | ', $res);
            }
        }

        return implode('</br>', $row);
    }

    /**
     * Notes : 获取数据库库名，字符串正则匹配
     * @param string $dsn
     * @return string|null
     * Author:唐伯虎不虎
     * Date:2024/11/18 11:02
     */
    public static function getDatabaseNameFromDsn(string $dsn): ?string
    {
        preg_match('/dbname=([^;]+)/', $dsn, $matches);
        return $matches[1] ?? null;
    }

    public static function jaccard_similarity($str1, $str2) {
        $set1 = str_split($str1);
        $set2 = str_split($str2);
        $intersection = count(array_intersect($set1, $set2));
        $union = count(array_unique(array_merge($set1, $set2)));
        return $intersection / $union;
    }

    /**
     * 将字符串数字转换为合适的 number 类型（int 或 float）
     * 严格保留原始小数格式，包括尾随零
     * @param mixed $value 输入值（通常是字符串）
     * @return int|float|string 转换后的数字（浮点数以字符串形式保留格式）
     */
    /**
     * 将字符串数字转换为Number类型，尽可能保留原始格式
     * @param mixed $value 输入值
     * @return int|float 转换后的数字
     */
    public static function convertToNumber($value) {
        // 如果已经是数字类型，直接返回
        if (is_int($value) || is_float($value)) {
            return $value;
        }

        // 如果不是字符串，尝试转换为字符串
        if (!is_string($value)) {
            $value = (string)$value;
        }

        // 移除千位分隔符（如逗号）
        $cleanedValue = str_replace(',', '', $value);

        // 检查是否是纯整数
        if (preg_match('/^-?\d+$/', $cleanedValue)) {
            return (int)$cleanedValue;
        }

        // 检查是否是浮点数格式（包括 30.0、30.50、科学计数法等）
        if (preg_match('/^-?\d+\.\d+$/', $cleanedValue) ||
            preg_match('/^-?\d+\.?\d*[eE][+-]?\d+$/', $cleanedValue)) {
            // 转换为浮点数
            $floatValue = (float)$cleanedValue;

            $decimalPlaces = 0;
            if (preg_match('/^-?\d+\.(\d+)/', $cleanedValue, $matches)) {
                $decimalPlaces = strlen($matches[1]);
            }

            if (preg_match('/^-?\d*\.(\d+)(?:0+)?$/', rtrim($value, '0'), $matches)) {
                // 返回格式化后的浮点数（仅在显示时保留小数位）
                return $floatValue;
            }else{
                return number_format($floatValue, $decimalPlaces, '.', '');

            }
        }

        // 尝试基本转换
        if (is_numeric($cleanedValue)) {
            return $cleanedValue + 0; // 强制转换为数字类型
        }

        return 0; // 非数字字符串返回0
    }

    /**
     * @note 字符转换成数组
     * @param $str
     * @param string $separator
     * @return false|mixed|string[]
     */
    public static function toArray($str, string $separator = ',') {
        if(is_string($str)) {
            return explode($separator, $str);
        }

        return $str;
    }

}
