<?php
/**
 * Created by PhpStorm.
 * User: Leo
 * Date: 2017/9/3
 * Time: 下午10:05
 */

namespace common\helpers;


use common\models\AlarmCall;
use common\models\ApproachOrderCall;
use common\models\Countries;
use common\models\Order;
use Faker\Provider\Uuid;
use Yii;
use yii\helpers\Url;
use yii\httpclient\Client;
use yii\mongodb\Exception;

class Tool {

    /**
     * 获取无限级树形分类
     * @param array $cate
     * @param int $pid
     * @param int $level
     * @param string $html
     * @return array
     */
    public static function categoryTree(array $cate, $pid=0, $level=0, $html='--') {
        $tree = [];
        foreach ($cate as $key=>$value){
            if($value['pid'] == $pid) {
                $value['level'] = $level + 1;
                $html = str_repeat($html,$value['level']);
                $tree[] = $value;
                $tree = array_merge($tree, self::categoryTree($cate,$value['id'],$level+1,$html));
            }
        }
        return $tree;
    }

    /**
     * 解析数据
     * @param $args
     * @param null $defaults
     * @return array
     */
    public static function deepParse($args, $defaults = NULL){
        $result = array();
        if (is_object($args)){
            $result = get_object_vars( $args );
        } elseif (is_array($args)){
            $result =& $args;
        }else{
            parse_str($args, $result);
        }
        if (is_array($defaults))
            return array_merge($defaults, $result);
        return $result;
    }

    /**
     * 格式化金额,保留两位小数
     * @param $price
     * @param int $auto  是否自动四舍五入
     * @return string
     */
    public static function formatPrice($price ,$auto = 1){
        if(!$price) return '0.00';
        if($auto==1){
            return sprintf("%.2f", $price);
        }else{
            return substr(sprintf("%.3f",$price),0,-1);
        }
    }

    /**
     * 格式化金额,保留2位小数,千分位分割
     * @param $amount
     * @param string $decimals
     */
    public static function formatAmount($amount, string $decimals = '2')
    {
        return (number_format($amount,$decimals));
    }

    /**
     * 计算商品税额
     * @param $amount
     * @param $taxRate
     * @param mixed $buyNo
     * @return float
     */
    public static function calculateTax($amount, $taxRate, $buyNo = 1): float
    {
        if (is_null($amount) || is_null($taxRate) || is_null($buyNo)) {
            return 0.0;
        }

        $taxAmount = ($amount - $amount / (1 + $taxRate / 100)) * $buyNo;
        return floatval(self::formatPrice($taxAmount));
    }

    /**
     * 前台业绩格式化
     * @param $perf
     * @param int $auto
     * @param int $zoom
     * @return bool|string
     */
    public static function formatFrontPerf($perf, $auto = 0, $zoom = 100) {
        if (!$perf) return '0.00';
        $perf = $perf / $zoom;
        if ($auto == 1) {
            return sprintf("%.2f", $perf);
        } else {
            return substr(sprintf("%.3f", $perf), 0, -1);
        }
    }

    /**
     * 格式化结算奖金
     * @param $calcBonus
     * @return string
     */
    public static function formatCalcBonus($calcBonus) {
        return sprintf("%.3f", $calcBonus);
    }

    /**
     * 获得文件扩展名
     * @param $file
     * @return string
     */
    public static function getExt($file) {
        $ext = pathinfo($file ,PATHINFO_EXTENSION);
        return strtolower($ext);
    }

    /**
     * 获取文件上传的地址
     * @return string
     */
    public static function getUploadUrl(){
        return \Yii::getAlias('@frontendUrl').'/'.\Yii::$app->params['upload']['dir'];
    }

    /**
     * 对二维数组排序
     *
     * @param $arrays
     * @param $sortField
     * @param int $sortOrder
     * @param int $sortType
     * @return bool
     */
    public static function sortMultiArray($arrays, $sortField, $sortOrder = SORT_ASC, $sortType = SORT_NUMERIC){
        if(is_array($arrays)){
            foreach ($arrays as $array){
                if(is_array($array)){
                    $key_arrays[] = $array[$sortField];
                }else{
                    return false;
                }
            }
        }else{
            return false;
        }
        array_multisort($key_arrays,$sortOrder,$sortType,$arrays);
        return $arrays;
    }

    /**
     * 清除字符串中的所有空格
     * @param $string
     * @return mixed
     */
    public static function trimAll($string){
        $waitClean=array(" ","　");
        $cleaned=array("","");
        return str_replace($waitClean,$cleaned,$string);
    }

    /**
     * 去除两端的逗号和所有空格
     * @param $string
     * @return mixed|string
     */
    public static function trimCommaAndSpace($string){
        $result = self::trimAll($string);
        $result = trim($result, ',');
        return $result;
    }

    /**
     * 页面跳转
     * @param string $url
     * @param string $err
     * @param bool $parent
     * @return string
     */
    public static function jsJump($url = 'back' ,$err = '' ,$parent = false) {
        $output = '<script type="text/javascript">';
        if (!empty($err)) $output .= "alert('{$err}');";
        ('back' == $url)
            ? $output .= 'window.history.go(-1);'
            : ($output .= ($parent == true ? 'parent.' : '') . 'location.href="' . $url . '";');
        $output .= '</script>';
        return $output;
    }

    /**
     * 发送Curl请求
     * @param $method
     * @param $url
     * @param array $data
     * @return \yii\httpclient\Response
     * @throws \yii\httpclient\Exception
     */
    public static function sendCurlRequest($method, $url, $data = []){
        $client = new Client();
        $request = $client->createRequest()
            ->setHeaders(['content-type' => 'application/json'])
            ->addHeaders(['user-agent' => 'bonusSystem'])
            ->setFormat(Client::FORMAT_JSON)
            ->setMethod($method)
            ->setUrl($url);
        if(!empty($data)){
            $request->setData($data);
        }
        return $request->send();
    }

    /**
     * 数字补齐
     * @param $num
     * @param int $bit
     * @param string $fixStr
     * @return string
     */
    public static function numFix($num, $bit = 2, $fixStr = '0'){
        return str_pad(intval($num),$bit,$fixStr,STR_PAD_LEFT);
    }

    /**
     * 替换手机号为隐藏格式
     * @param $str
     * @return null|string|string[]
     */
    public static function hideMobile($str){
        return preg_replace('/^(\d{3})\d{4}(\d{4})$/', '${1}****${2}', $str);
    }

    /**
     * 替换身份证为隐藏格式
     * @param $str
     * @return null|string|string[]
     */
    public static function hideIdCard($str){
        return preg_replace('/^(\d{3})\d{3}(\d{4})\d{8}$/', '${1}***${2}********', $str);
    }

    /**
     * 替换银行卡号隐藏格式
     * @param $str
     * @return null|string|string[]
     */
    public static function hideBankNo($str){
        if(preg_match('/^(\d{4})\d{11}(\d{4})$/', $str)){
            return preg_replace('/^(\d{4})\d{11}(\d{4})$/', '${1}***********${2}', $str);
        } elseif(preg_match('/^(\d{4})\d{8}(\d{4})$/', $str)){
            return preg_replace('/^(\d{4})\d{8}(\d{4})$/', '${1}********${2}', $str);
        } else {
            return $str;
        }
    }

    /**
     * 清空目录下的所有文件
     * @param $dir
     * @throws Exception
     */
    public static function clearDir($dir){
        $dirHandle = opendir( $dir );
        if($dirHandle === false){
            throw new Exception('打开目录失败');
        }
        while( ($file = readdir( $dirHandle )) !== false ){
            if ( $file != '.' && $file != '..' && $file != '.gitignore' ) {
                unlink( $dir . '/' . $file );
            }
        }
    }

    /**
     * 过滤特殊字符
     * @param $strParam
     * @return string|string[]|null
     */
    public static function filterSpecialChar($strParam){
        $regex = "/\/|\～|\，|\。|\！|\？|\“|\”|\【|\】|\『|\』|\：|\；|\《|\》|\’|\‘|\ |\·|\~|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\+|\{|\}|\:|\<|\>|\?|\[|\]|\.|\/|\;|\'|\`|\-|\=|\\\|\|/";
        return preg_replace($regex,"",$strParam);
    }

    public static function allow_area($area, $search) {
        $result = false;
        foreach ($search as $key => $value) {
            $count = count($value);
            //不够三项的，补充到三项
            if ($count < 3) {
                $num = 3 - $count;
                $value += array_fill($count, $num, '');
            }
            if ($value[0] == '') {  //说明地区选的全部
                $result = true;
                break;
            }
            if ($value[0] == $area[0] && ($value[1] == '' || $value[1] == $area[1]) && ($value[2] == '' || $value[2] == $area[2])) {
                $result = true;
                break;
            }
        }
        return $result;
    }

    /**
     * 转驼峰
     * @param $words
     * @param string $separator
     * @return string
     */
    public static function toCamelize( $words , $separator = '_') {
        if(!$words){
            return '';
        }
        $words = $separator. str_replace($separator, " ", strtolower($words));
        return ltrim(str_replace(" ", "", ucwords($words)), $separator );
    }

    public static function isConsoleApp(){
        return (\Yii::$app->id == 'app-console');
    }

    /**
     * 根据KEY合并两个数组
     * @param $arr1
     * @param $arr2
     * @param array $keyArr
     * @param string $keyField
     * @return mixed
     */
    public static function mergeArrayWithKey($arr1,$arr2,$keyArr=[],$keyField='ID'){
        foreach ($arr1 as $key=>$value){
            $arr1[$key]=array_merge($arr1[$key],$arr2[$key]??[]);
            if($keyArr){
                $arr1[$key][$keyField] = $keyArr[$key]??'';
            }
        }
        return $arr1;
    }

    /**
     * 中文UTF8 转 gbk
     * @param $text
     * @return false|string|string[]|null
     */
    public static function textConvert($text) {
        if ($text==='') {
            return '';
        }
        if (preg_match('/\,/', $text)){
            $text = preg_replace('/\,/', '|', $text);
        }
        // 只有是中文时才需要转码
//        if (!preg_match('/[\x{4e00}-\x{9fa5}]/u', $text)) {
//            return $text;
//        }
//        return mb_convert_encoding($text, 'gbk', 'utf-8');

        $text = mb_convert_encoding($text, 'GBK', 'UTF-8');
        $text = preg_replace("/(\+|%2A|%A3%A8|%A3%A9|%A1%A4)+/",'', urlencode($text));

        return urldecode($text);
    }

    /**
     * 数组里面的中文字符串全部转为GBK
     * @param array $arr
     * @return array
     */
    public static function arrTextConvert(array $arr){
        foreach($arr as $key => $str){
            $arr[$key] = self::textConvert($str);
        }
        return $arr;
    }

    public static function mbSignConvert($string) {
        if (false !== mb_strpos($string, '（') || false !== mb_strpos($string, '）')) {
            $new = str_replace('（', '(', $string);
            return str_replace('）', ')', $new);
        }

        return $string;
    }

    /**
     * 获取目录内的所有文件
     * @param $dirPath
     * @return array
     */
    public static function dirFiles($dirPath){
        $files = [];
        //检测是否存在文件
        if (is_dir($dirPath)) {
            //打开目录
            if ($handle = opendir($dirPath)) {
                //返回当前文件的条目
                while (($file = readdir($handle)) !== false) {
                    //去除特殊目录
                    if ($file != "." && $file != "..") {
                        //判断子目录是否还存在子目录
                        if (!is_dir($dirPath . "/" . $file)) {
                            $files[] = $dirPath . "/" . $file;
                        } else {
                            $files[$file] = self::dirFiles($dirPath . "/" . $file);
                        }
                    }
                }
                //关闭文件夹
                closedir($handle);
            }
        }
        //返回文件夹内文件的数组
        return $files;
    }

    /**
     * 获取审核状态tag颜色
     * @param $val
     * @return string
     */
    public static function statusType($val) {
        switch ($val) {
            case '0':
                return 'info';
                break;
            case '1':
                return 'success';
                break;
            case '2':
                return 'warning';
                break;
            case '3':
                return 'danger';
                break;
            default:
                return '';
        }
    }

    /**
     * 转换语言标识符
     * @param $lang
     * @return string
     */
    public static function langConvert($lang): string
    {
//        $map = [
//            '620713695651307520' => 'en-US',
//            '620713695718416384' => 'zh-CN',
//            '620713695718416385' => 'ar-EG',
//            '620713695722610688' => 'fr-FR',
//            '620713695722610689' => 'pt-PT',
//            '620713695722610690' => 'es-ES',
//            '620713695722610691' => 'sw-KE',
//        ];

        $map = [
            'en' => 'en-US',
            'zh' => 'zh-CN',
            'ar' => 'ar-EG',
            'fr' => 'fr-FR',
            'pt' => 'pt-PT',
            'es' => 'es-ES',
            'sw' => 'sw-KE',
        ];

        return $map[$lang] ?? 'en-US';
    }

    /**
     * 参数转换
     * @param $params
     * @return mixed
     */
    public static function paramConvert($params)
    {
        foreach ($params as &$item) {
            if (isset($item['title']) && $item['title']) {
                $item['title'] = Yii::t('ctx', $item['languageKey']);
            }
            if (isset($item['label']) && $item['label']) {
                $item['label'] = Yii::t('ctx', $item['languageKey']);
            }
        }

        return $params;
    }

    /**
     * 格式化筛选
     * @param $selData
     * @param $id
     * @param $name
     * @return array
     */
    public static function formatFilter($selData, $id, $name) {
        $arr=[];
        foreach ($selData as $key=>$value){
            $arr[$key]['id']=$value[$id];
            $arr[$key]['name']=$value[$name];
        }
        return $arr;
    }

    /**
     * 随机字符串
     * @param int $length
     * @param string $prefix
     * @param string $type
     * @return string
     */
    public static function randomString($length = 10, $prefix = '', $type = 'digit') {
        if ($type == 'digit') {
            $chars = "0123456789";
        } else {
            $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        }
        if ($length - strlen($prefix) < 1) {
            return false;
        }
        $random_string = '';
        for ($i = 0; $i < $length - strlen($prefix); $i++) {
            $random_string .= $chars [mt_rand(0, strlen($chars) - 1)];
        }
        return $prefix.$random_string;
    }

    /**
     * 生成UUID
     * @param $upper boolean 是否大写
     * @param $symbol string 替换符号
     * @return string|string[]
     */
    public static function generateId(bool $upper = true, string $symbol = '')
    {
        $uuid = !$upper ? Uuid::uuid() : strtoupper(Uuid::uuid());
        return str_replace('-', $symbol, $uuid);
    }

    /**
     * 生成userPerformance ID
     * @param string $iso
     * @return string
     */
    public static function generateUserPerformanceNo(string $iso = ''): string
    {
        $rid = self::generateId();
        return $iso . Date::today('Ymd') . substr($rid, 0, 6);
    }

    /**
     * PayStack订单写入MongoDB.
     * @param $call
     * @return void
     * @throws \Exception
     */
    public static function approachOrderCall($call)
    {
        try {
            $model = new ApproachOrderCall();
            $model->sn = $call['data']['metadata']['custom_fields'][0]['value'] ?? '';
            $model->reference = $call['data']['reference'] ?? '';
            $model->event = $call['event'];
            $model->data = $call['data'];
            $model->insert();
        } catch (Exception $e) {
            LoggerTool::info($call);
            LoggerTool::error(sprintf('[%s] [%s] [%s]', $e->getFile(), $e->getLine(), $e->getMessage()));
        }
    }

    /**
     * 预警日志入库
     * @param $call
     * @return void
     */
    public static function alarmCall($call)
    {
        try {
            $model = new AlarmCall();
            $model->brand = $call['brand'];
            $model->stance = $call['stance'];
            $model->trace_id = $call['trace-id'];
            $model->content = $call;
            $model->insert();
        } catch (Exception $e) {
            LoggerTool::error($call);
            LoggerTool::error(sprintf('[%s] [%s] [%s]', $e->getFile(), $e->getLine(), $e->getMessage()));
        } catch (\Exception $e) {
        }
    }

    /**
     * @param $amount
     * @param $beforeRate
     * @param $afterRate
     * @return float|int
     */
    public static function convertAmount($amount, $beforeRate, $afterRate)
    {
        if ($amount == 0 || $beforeRate == $afterRate) {
            return $amount;
        }

        return ($amount / $beforeRate) * $afterRate;
    }

    /**
     * 生成发票号
     * @param $countryId
     * @return string
     */
    public static function generateInvoiceNo()
    {
        $prefix = 'Inv';
        $currentDate = date('dmY');
        
        // 查询今天生成的最新发票号（包含当天日期格式的）
        $order = Order::find()
            ->where(['STATUS' => 1, 'IS_DELETE' => 0])
            ->andWhere(['like', 'INVOICE_NO', $prefix . $currentDate])
            ->orderBy(['INVOICE_NO' => SORT_DESC])
            ->one();

        if ($order && !empty($order->INVOICE_NO)) {
            $invoiceNo = $order->INVOICE_NO;
            // 截取最后5位数字部分并+1
            $no = sprintf('%05d', intval(substr($invoiceNo, -5)) + 1);
        } else {
            // 如果今天没有生成过发票号或没有符合条件的订单，从00001开始
            $no = '00001';
        }

        return $prefix . $currentDate . $no;
    }
}