<?php

namespace util;
use app\apicom\model\Member;
use util\TradingRedis;
use util\TradingUtil;
use util\QuotationRedis;
class RedisUtil
{

    // redis实例
    private static $redis = null;

    /**
     * 返回redis的静态实例
     *
     * @return \Redis
     */
    public static function redis()
    {
        if (is_null(self::$redis)) {
            self::$redis = new \Redis();
            self::$redis->connect(REDIS_SERVER_IP, REDIS_SERVER_PORT);
        }

        return self::$redis;
    }
    /**
     * 缓存token及对应的用户数据
     *
     * @param string $token
     * @param array $data 用户数据
     */
    public static function cacheToken($token, $data)
    {
        // 切换redis数据库
        self::redis()->select(1);
        // 缓存数据
        $key = $token;
        self::redis()->hMSet($key, $data);
        // 默认一个小时过期
        self::redis()->expire($key, TOKEN_EXPIRE_TIME);
        // 切换数据库
        self::redis()->select(0);
    }
    /**
     * 根据token获取用户数据
     * - 返回空数组时表示未登录
     *
     * @param $token
     *
     * @return array
     */
    public static function getToken($token)
    {
        // 切换redis数据库
        self::redis()->select(1);
        if (self::redis()->exists($token)) {
            $user = self::redis()->hMGet($token, ['uid', 'name', 'mobile', 'pid', 'agent_id', 'agent_far', 'id_card']);
            $ret  = Member::where(['id'=> $user['uid'],'status'=>1,'is_del'=>0])->find();
            if(!$ret) return [];
            // 用户每次操作时刷新超时时间
            self::redis()->expire($token, TOKEN_EXPIRE_TIME);
            // 切换数据库
            self::redis()->select(0);
            return $user;
        } else {
            self::redis()->select(0);// 切换数据库
            return [];
        }
    }
    /**
     * 删除token
     * - 此操作会使用户退出登录
     *
     * @param $token
     */
    public static function deleteToken($token)
    {
        // 切换redis数据库
        self::redis()->select(1);
        self::redis()->del($token);
        self::redis()->select(0);// 切换数据库
    }
    /**
     * 缓存管理员token及对应的数据
     *
     * @param string $token
     * @param array $data 用户数据
     */
    public static function cacheAdminToken($token, $data)
    {
        // 切换redis数据库
        self::redis()->select(2);
        // 缓存数据
        $key = $token;
        self::redis()->hMSet($key, $data);
        // 默认一个小时过期
        self::redis()->expire($key, TOKEN_EXPIRE_TIME);
        // 切换数据库
        self::redis()->select(0);
    }
    /**
     * 根据token获取用户数据
     * - 返回空数组时表示未登录
     *
     * @param $token
     *
     * @return array
     */
    public static function getAdminToken($token)
    {
        // 切换redis数据库
        self::redis()->select(2);
        if (self::redis()->exists($token)) {
            $user = self::redis()->hMGet($token, ['aid', 'name', 'nick', 'pid', 'role']);
            // 用户每次操作时刷新超时时间
            self::redis()->expire($token, TOKEN_EXPIRE_TIME);
            // 切换数据库
            self::redis()->select(0);
            return $user;
        } else {
            // 切换数据库
            self::redis()->select(0);
            return [];
        }
    }
    /**
     * 生成午夜时间戳
     * -- 用于在午夜过期的KEY
     * -- 午夜向后浮动 10 ~ 120 秒，防止大量KEY同时过期
     * @param bool $delay
     *
     * @return int
     */
    public static function midnight($delay = true)
    {
        $delayTime = $delay ? intval(mt_rand(10, 120)) : 0;
        $time = intval(strtotime('tomorrow'));
        //print_r(date('Y-m-d H:i:s', strtotime('tomorrow')));exit;
        return $time + $delayTime;
    }
    /*
     *查询股票实时行情
     * $alive == true 时为持仓数据，直接从缓存获取
     */
    public static function getQuotationData($stockCode,$market,$alive=false)
    {
        //加入活跃列表 先放在缓存里 速度更快*/
        QuotationRedis::addAliveStocks($stockCode);
        $key = 'stock_hq_' . $market . $stockCode;
        $data = self::redis()->hGetAll($key);
        //$data = [];
        // 检测最后更新时间是否过期
        if(!empty($data) && is_array($data)){
            $nowHIS = intval(time())-intval($data[80]);
            $item   = $nowHIS <= 5 && $nowHIS >= 0 ? $data : self::checkAndGetStock($key,$market,$stockCode,$data,$alive);
        }else{
            $item = self::checkAndGetStock($key,$market,$stockCode,$data,$alive);
        }
        $json = self::JsonRegroup($item) ?? [];
        return $json ?? [];
    }
    /*
     * 检测交易时间并获取数据
     * $alive == true 时为持仓数据，直接从缓存获取
     */
    public static function checkAndGetStock($key,$market,$stockCode,$data,$alive)
    {
        try {
            //检测交易日和交易时间
            //if (!checkTradeTime()) return $data;
            //远程获取最新行情数据
            if($alive == true) return $data;
            $item = getApiStock(strtolower($market).$stockCode);
            //将获取的数据缓存本地
            if($item) self::redis()->hMSet($key, $item);
        } catch (\Exception $e) {
            $item = $data;
        }
        return $item ?? [] ;
    }
    /*
     * 重组数据
     */
    public static function JsonRegroup($item)
    {
        $json['market']   = isset($item[0]) ?strtoupper($item[0]):'';
        $json['code']     = isset($item[2]) ?$item[2] :'';
        $json['name']     = isset($item[1]) ?$item[1] :'';
        $json['Price']    = isset($item[3]) ?$item[3] :'';
        $json['Close']    = isset($item[4]) ?$item[4] :'';
        $json['Open']     = isset($item[5]) ?$item[5] :'';
        $json['High']     = isset($item[33])?$item[33]:'';
        $json['Low']      = isset($item[34])?$item[34]:'';
        $json['Highest']  = isset($item[41])?$item[41]:''; 
		$json['Lowest']   = isset($item[42])?$item[42]:''; 
        $json['Volume']   = isset($item[36])?$item[36]:'';
        $json['Turnover'] = isset($item[37])?$item[37]:'';
        $json['Pe_ratio'] = isset($item[39])?$item[39]:'';
        $json['Pb_ratio'] = isset($item[46])?self::chaeckTMC($item):'';
        $json['Harden']   = isset($item[47])?$item[47]:'';
        $json['Drop']     = isset($item[48])?$item[48]:'';
        $json['Trate']    = isset($item[38])?$item[38]:'';
        $json['TMC']      = isset($item[45])?$item[45]:'';
        $json['Bp1']      = isset($item[9]) ?$item[9] :'';
        $json['Bv1']      = isset($item[10])?$item[10]:'';
        $json['Bp2']      = isset($item[11])?$item[11]:'';
        $json['Bv2']      = isset($item[12])?$item[12]:'';
        $json['Bp3']      = isset($item[13])?$item[13]:'';
        $json['Bv3']      = isset($item[14])?$item[14]:'';
        $json['Bp4']      = isset($item[15])?$item[15]:'';
        $json['Bv4']      = isset($item[16])?$item[16]:'';
        $json['Bp5']      = isset($item[17])?$item[17]:'';
        $json['Bv5']      = isset($item[18])?$item[18]:'';
        $json['Sp1']      = isset($item[19])?$item[19]:'';
        $json['Sv1']      = isset($item[20])?$item[20]:'';
        $json['Sp2']      = isset($item[21])?$item[21]:'';
        $json['Sv2']      = isset($item[22])?$item[22]:'';
        $json['Sp3']      = isset($item[23])?$item[23]:'';
        $json['Sv3']      = isset($item[24])?$item[24]:'';
        $json['Sp4']      = isset($item[25])?$item[25]:'';
        $json['Sv4']      = isset($item[26])?$item[26]:'';
        $json['Sp5']      = isset($item[27])?$item[27]:'';
        $json['Sv5']      = isset($item[28])?$item[28]:'';
        $json['Range']    = isset($item[3])&&isset($item[4]) ? round(($item[3]-$item[4]),2) : '';
		$json['Rate']     = isset($item[4])&&$item[4]>0 ? round((($item[3]-$item[4])/$item[4]*100),2) : '';
        //$json['last_time']= 930<intval(date('Hi')) && intval(date('Hi'))<1500 ? $item[80] : '';
        $json['last_date_time'] = isset($item[80]) ? self::market_time($item[80]) : date('Y-m-d H:i:s');
        $json['server_time']    = isset($item[80]) ? date('Y-m-d H:i:s',$item[80]) : '----';
        return $json;
    }
    /*
    缓存最新获取的所有股票
    */
    public static function cacheNewStockList($data)
    {
        // 数据存在，缓存数据
        $key = "stock_list";
        // 删除之前的列表
        self::redis()->del($key);
        return;
    	foreach ($data as $item) {
            $stock = $item ? $item['market'].",".$item['code'].",".$item['name'].",".$item['pinyin'] : " ";
            //print_r($stock);exit;
            self::redis()->rpush($key, $stock);
        }
        $ret =  self::redis()->expireAt($key, self::midnight());
        
        return $ret ? true : false;
    }
    /*
     * 获取缓存的最新获取的所有股票
    */
    public static function getCacheNewStockList()
    {
        $key = "stock_list";
        $list = self::redis()->lRange($key, 0, -1);
        return $list ?: [];
    }
    /*
     * 获取热门行业缓存
     */
    public static function getHotIndustrys($num = null)
    {
        $key = 'Hot_Industrys';
        //self::redis()->del($key);
        if (!self::redis()->exists($key)) {
            //exit('没有缓存');
            $res = getSinahy();
            if($res) self::redis()->Set($key, serialize($res));
        }
        $data = unserialize(self::redis()->GET($key));
        if($data && intval($num) > 0){
            $json = [];
            for ($i = 0; $i < $num; $i++) {
                $json[] = $data[$i];
            }
        } else {
            $json = $data;
        }
        //var_dump($json);exit;
        return $json ?? false;
    }
    /*
     * 获取热门行业分类缓存
     */
    public static function getNodeclassData($node,$page,$num)
    {
        $key = 'Hot_Nodeclass_' . $node;
        //self::redis()->del($key);
        if (!self::redis()->exists($key)) {
            //exit('没有缓存');
            $res = getSinaNodeclass($node,$page,$num);
            if($res) self::redis()->Set($key, serialize($res));
        }
        $data = unserialize(self::redis()->GET($key));
        return $data ?? false;
    }
    /*
     * 判断市净值的值是否有效
     */
    public static function chaeckTMC($data)
    {
        if (is_numeric($data[46])){
            return $data[46];
        } else {
            return $data[58];
        }
    }
    public static function market_time($time)
    {
        if(!$time) return date('Y-m-d H:i:s');
        $nowHI = intval(date('Hi'));
        if(930  > $nowHI || $nowHI > 1500){
            return date('Y-m-d 15:00:00',$time);
        }
        if(1130 < $nowHI && $nowHI < 1300){
            return date('Y-m-d 11:30:00',$time);
        }else{
            return date('Y-m-d H:i:s',$time);
        }
    }
    
    public static function cacheClientIp($data)
    {
        self::redis()->set('admin_ip',$data);
    }
    
    public static function getClientHost()
    {
        if(self::redis()->exists('admin_ip')){
            return self::redis()->get('admin_ip');
        }else{
            return '';
        }
    }
}
