<?php
defined('IN_WEB') or die('Include Error!');
if(!defined('INVITE_SECRET')){
    define( 'INVITE_SECRET', 'super*&()[ant!@+?>#2017~.,-sap' );
}
define( 'SVR_UPDATE_SPINS',0x5001);
define( 'SVR_UPDATE_COINS',0x5002);
/**
 * 邀请相关
 */
class ModelInvite{
    private $inviteReward = 1000;			/* 邀请一个好友赠送的奖励 */
    private $dailyInviteLimit = 100;		/* 限制每天发送邀请后可领奖的次数为100次 */

    /**
     * 生成邀请ID
     * @param int $uid
     * @return string
     * Created by: Owen
     * Created on: 2020/8/26 11:31
     */
    public function getInviteID($uid = 0) {
        $suffix = $uid % 100;
        return sprintf('%d%04d%02d', time(), mt_rand(1, 9999), $suffix);
    }

    /**
     * 生成消息验证skey
     * @param $uid
     * @param $inviteId
     * @return string
     * Created by: Owen
     * Created on: 2020/8/26 11:30
     */
    public function getInviteSkey($uid, $inviteId) {
        return md5(INVITE_SECRET.$uid.$inviteId);
    }

    /**
     * 校验请求的邀请是否合法
     * @param $data
     * @return array|null
     * Created by: Owen
     * Created on: 2020/8/26 11:30
     */
    public function check($data) {
        $array = array();
        preg_match('/u:([^;]+);id:([^;]+);sk:([^;]+);type:(.+)/', $data, $array);
        if (empty($array)) {
            preg_match('/u:([^;]+);id:([^;]+);sk:(.+)/', $data, $array);
            if (empty($array)) {
                return NULL;
            }
        }
        $sk = $this->getInviteSkey($array[1], $array[2]);
        if ($sk != $array[3]) {
            return NULL;
        }
        return $array;
    }

    /**
     * 邀请上报接口
     * @param $param
     * @return false|string
     * Created by: Owen
     * Created on: 2020/8/26 11:30
     */
    public function report($param){
        $arr = array('code' => 0, 'money' => 0);
        $uid = oo::functions()->uint($param['uid']);
        $data = isset($param['data']) ? oo::functions()->escape($param['data']) : '';
        $list = isset($param['list']) ? oo::functions()->escape($param['list']) : '';
        $source = isset($param['source']) ? oo::functions()->escape($param['source']) : '';
        $requestid = isset($param['requestid']) ? oo::functions()->escape($param['requestid']) : '';
        if( empty($uid) || empty($data) || empty($list) || empty($source) || empty($requestid) ){
            $arr['code'] = -1;
            oo::logs()->debug3(array('uid' => $uid, 'data' => $data, 'list' => $list, 'source' => $source, 'requestid' => $requestid, 'time' => time()),'InviteReportErr.log');
            return json_encode($arr);
        }
        $check  = $this->check($data);
        $inviteId = $check[2]; //邀请ID
        if (empty($check)) {
            $arr['code'] = -2;
            oo::logs()->debug3(array('uid' => $uid, 'reason' => 'checkIsEmpty', 'time' => time(), 'line' => __LINE__),'InviteReportErr.log');
            return json_encode($arr);
        }
        $setInviteInfo = array(
            'uid'          => $uid,
            'siteuidList'  => $list,
            'joinList'     => '',
            'time'         => time(),
            'requestid'    => $requestid,
            'type'         => $source,
        );
        $result = $this->setInvite( $check[2], $setInviteInfo );
        if ($result != 0) {
            $arr['code'] = -3;
            oo::logs()->debug3(array('uid' => $uid, 'reason' => 'setInviteFail', 'time' => time(), 'line' => __LINE__),'InviteReportErr.log');
            return json_encode($arr);
        }
        //判断玩家可以获得多少奖励
        $money = 0;
        $inviteCount = 0;
        $ret = $this->getRwdMoney($uid, $list, $money, $inviteCount);
        if ($ret != 0) {
            $arr['code'] = -4;
            $arr['ret'] = $ret;
            $money = 0;
        }
        $arr['spin'] = 25;
        $arr['count'] = $inviteCount;
        //统计每日发送的具体人数
        oo::commonOprRedis('statistics')->incrBy(okeys::dailyInviteNum(), $inviteCount);
        oo::commonOprRedis('statistics')->expireAt(okeys::dailyInviteNum(), oo::redisRandomExpire(strtotime('23:59:59')));
        //上报统计
        oo::commonOprModel('statistics')->event(array($uid, 1014));
        $arr = ['code'=>1,'data'=>[
            'spin'=>25
        ]];
        return json_encode($arr);
    }

    /**
     * 被邀请玩家回来发奖
     * @param $param
     * @return false|string
     * Created by: Owen
     * Created on: 2020/8/26 11:30
     */
    public function update($param){
        $arr = array('code' => 1, 'spins' => 50, 'ret' => 0);
        $uid = oo::functions()->uint($param['uid']);
        $data = isset($param['data']) ? oo::functions()->escape($param['data']) : '';
        if( empty($uid) || empty($data) ){
            $arr['ret'] = -1;
            $arr['code'] = -1;
            oo::logs()->debug3(array('uid' => $uid, 'data' => $data, 'time' => time()),'InviteReportErr.log');
            return json_encode($arr);
        }
        $check  = $this->check($data);
        if (empty($check)) {
            $arr['ret'] = -2;
            $arr['code'] = -2;
            oo::logs()->debug3(array('uid' => $uid, 'data' => $data, 'time' => time(), 'line' => 157),'InviteReportErr.log');
            return json_encode($arr);
        }
        $srcuid = $check[1];
        $inviteid = $check[2];
        $cacheKey = okeys::InviteUrlRecord($uid);
        if(!oo::commonOprRedis('User')->setnx($cacheKey,$srcuid)){
            return oo::response(-2,[],'邀请记录已上报');
        }
        oo::commonOprRedis('User')->expire($cacheKey,oo::redisRandomExpire(3*24*60*60));
        /* 查询该用户是否已经被邀请过 */
        $userinfo = oo::commonOprModel('member')->getUserInfo($uid);
        if( !is_array($userinfo) || $userinfo <= 0 ){
            $arr['ret'] = -3;
            $arr['code'] = -3;
            oo::logs()->debug3(array('uid' => $uid, 'data' => $data, 'time' => time(), 'line' => 170),'InviteReportErr.log');
            return json_encode($arr);
        }
        if ($userinfo['inviteuid'] > 0) {
            $arr['ret'] = $userinfo['inviteuid'];
            oo::logs()->debug3(array('uid' => $uid, 'data' => $data, 'time' => time(), 'line' => 176),'InviteReportErr.log');
            return json_encode($arr);
        }
        $siteuid = trim($userinfo['siteuid']);
        $inviteArr = array();
        $result = $this->getInvite($inviteid, $srcuid, $inviteArr);
        if ($result < 0) {
            oo::logs()->debug3(array('uid' => $uid, 'data' => $data, 'time' => time(), 'line' => 187),'InviteReportErr.log');
            $arr['ret'] = -4;
            $arr['code'] = -4;
            return json_encode($arr);
        }else if ($result == 0) {
            oo::logs()->debug3(array('uid' => $uid, 'data' => $data, 'time' => time(), 'line' => 191),'InviteReportErr.log');
            $arr['ret'] = -5;
            $arr['code'] = -5;
            return json_encode($arr);
        }
        /* 判断是否已经在安装了应用的好友里面 */
        $joinList = $inviteArr[0]['joinList'];
        $tmpJoinList = array();
        if (!empty($joinList)) {
            $tmpJoinList = explode(',', $joinList);
            if (in_array($siteuid, $tmpJoinList)) {
                $arr['ret'] = 0;
                oo::logs()->debug3(array('uid' => $uid, 'data' => $data, 'time' => time(), 'line' => 203),'InviteReportErr.log');
                return json_encode($arr);
            }
        }
        /* 判断是否在邀请的好友列表里面 */
        $siteuidList = $inviteArr[0]['siteuidList'];
        if (empty($siteuidList)) {
            oo::logs()->debug3(array('uid' => $uid, 'data' => $data, 'time' => time(), 'line' => 211),'InviteReportErr.log');
            $arr['ret'] = -6;
            $arr['code'] = -6;
            return json_encode($arr);
        }
        $tmpSiteUidList = explode(',', $siteuidList);
        if (!in_array($siteuid, $tmpSiteUidList)) {
            oo::logs()->debug3(array('uid' => $uid, 'data' => $data, 'time' => time(), 'line' => 217),'InviteReportErr.log');
            $arr['ret'] = -7;
            $arr['code'] = -7;
            return json_encode($arr);
        }
        /* 设置用户信息表的被邀请字段 */
        $result = oo::commonOprModel('member')->updateUserInfo($uid, array('inviteuid' => $srcuid));
        if ( $result < 1 ) {
            oo::logs()->debug3(array('uid' => $uid, 'data' => $data, 'time' => time(), 'line' => 225),'InviteReportErr.log');
            $arr['ret'] = -8;
            $arr['code'] = -8;
            return json_encode($arr);
        }
        /* 设置安装了应用的好友列表 */
        array_push($tmpJoinList, $siteuid);
        $result = $this->updateInvite($inviteid, $srcuid, array('joinList' => implode(',', $tmpJoinList)));
        if ($result != 0) {
            $arr['ret'] = -9;
            $arr['code'] = -9;
            oo::logs()->debug3(array('uid' => $uid, 'data' => $data, 'time' => time(), 'line' => 236),'InviteReportErr.log');
            return json_encode($arr);
        }
        $source = intval($inviteArr[0]['type']);
        $logArr = array(
            'uid'     => $uid,
            'sendUid' => $srcuid,
            'source'  => $source,
            'reason'  => 'invite_success'
        );
        oo::logs()->debug3($logArr, 'invite_update.log');

        $arr['ret'] = 0;
        //记录新玩家登陆游戏的渠道
        $deviceId = oo::getDefinedDeviceId($uid);
        oo::commonOprRedis('common')->incr(okeys::newplayerFrom(1, $deviceId));
        oo::commonOprRedis('common')->expire(okeys::newplayerFrom(1, $deviceId), oo::redisRandomExpire(86400*31*2));
        $this->inviteSuccess($srcuid,$uid,1);
        return json_encode($arr);
    }

    /**
     * 成功邀请好友游戏进度及奖励配置
     * @return array
     */
    public function getInviteProgressConf() {
        return [
            ['step' => 0, 'reward' => ['spins' => 10], 'task' => 'level', 'target' => 1],
            ['step' => 1, 'reward' => ['spins' => 15], 'task' => 'level', 'target' => 2],
            ['step' => 2, 'reward' => ['spins' => 20], 'task' => 'level', 'target' => 3],
            ['step' => 3, 'reward' => ['spins' => 25], 'task' => 'bindFb'],
            ['step' => 4, 'reward' => ['spins' => 0], 'task' => 'charge'],
        ];
    }

    /**
     * 好友邀请进度充值进度钻石奖励乘系数
     */
    public function getInviteProgressDiamondRate() {
        $rate = intval(oo::commonOprModel('readconfig')->getCon('Game','inviteRewardDiamondRate'));
        return $rate > 0 ? $rate : 5;
    }

    /**
     * 我的邀请进度及奖励领取信息
     * @return array
     */
    public function getInviteProgressInfo($uid, $fid = 0,$client = false) {
        if(empty($fid)){
            $tmp = oo::commonOprRedis('User')->hGetAll(okeys::userinvitesuc($uid));
        }else{
            $tmp = oo::commonOprRedis('User')->hMGet(okeys::userinvitesuc($uid), [$fid]);
        }

        $config = $this->getInviteProgressConf();
        $data = [];
        foreach($tmp as $tid => $val){
            if($tid == $uid){
                oo::commonOprRedis('User')->hDel(okeys::userinvitesuc($uid),$tid);
                continue;
            }
            $val = json_decode($val, true);
            if(!isset($val['step']) || !isset($config[$val['step']])){
                continue;
            }
            if($config[$val['step']]['task'] == 'level'){
                $val['reward'] = $config[$val['step']]['reward'];
                $levelId = oo::commonOprModel('member')->getUserLevelId($tid);
                $val['can_get'] = $levelId > $config[$val['step']]['target'] ? 1 : 0;
            }
            $userInfo = oo::commonOprModel('member')->getUserInfo($tid);
            if($config[$val['step']]['task'] == 'bindFb'){
                $val['reward'] = $config[$val['step']]['reward'];
                $val['can_get'] = !empty($userInfo['isFb']) ? 1 : 0;
            }
            if($config[$val['step']]['task'] == 'charge'){
                $val['last'] = empty($val['last']) ? 0 : $val['last'];
                $payNum = $this->getSumPayNum($tid);
                $val['can_get'] = 0;
                if($payNum > $val['last']){
                    $val['reward'] = $config[$val['step']]['reward'];
                    $val['reward']['spins'] = $payNum - $val['last'];
                    $val['can_get'] = 1;
                }else{
                    $val['reward'] = $config[$val['step']]['reward'];
                    $val['reward']['spins'] = $this->getInviteProgressDiamondRate();
                }
            }
            $val['uid']       = $tid;
            $val['u_flag']    = $userInfo['u_flag'];
            $val['avatar']    = $userInfo['avatar'];
            $val['s_picture'] = $userInfo['s_picture'];
            $val['nick']      = $userInfo['nick'];
            $val['isFb']      = $userInfo['isFb'];
            $data[$tid] = $val;
        }

        if($client){
            $invites = oo::commonOprModel('invite')->getInviteRewardList($uid, 0, 1);
            $newArr = $invites ? array_column($invites, 'uid') : [];
            $dataTemp = [];
            foreach($data as $v){
                $reward = [];
                if(isset($v['reward']['spins'])){
                    $reward = ['propsId' => 15, 'num' => $v['reward']['spins']];
                }elseif(isset($v['reward']['diamond'])){
                    $reward = ['propsId' => 22, 'num' => $v['reward']['diamond']];
                }elseif(isset($v['reward']['money'])){
                    $reward = ['propsId' => 14, 'num' => $v['reward']['money']];
                }
                $v['isNew']  = in_array($v['uid'],$newArr) ? 1 : 0;
                $v['reward'] = $reward;
                $v['status'] = $v['can_get'];
                unset($v['can_get']);
                if($v['uid'] == $fid){
                    return $v;
                }
                $dataTemp[] = $v;
            }
            $data = $dataTemp;
        }

        if(!empty($fid)){
            return empty($data[$fid]) ? [] : $data[$fid];
        }

        return $data;
    }

    /**
     * 累计充值金额
     * @param 充值玩家id
     * @param 充值金额
     * @return bool
     */
    public function addSumPayNum($uid, $num) {
        $key = okeys::inviteSumPayNum($uid);
        $num = ceil($num);
        if($num < 1){
            return false;
        }
        $rate = $this->getInviteProgressDiamondRate();
        return oo::commonOprRedis('User')->incrBy($key,intval($rate * $num)) ? true : false;
    }

    /**
     * 领取邀请进度奖励
     * @param int $uid
     * @param int $step
     */
    public function gainInviteReward($uid, $fid, $num = 0) {
        $arr = $this->getInviteProgressInfo($uid, $fid);
        if(empty($arr['can_get'])){
            return false;
        }
        $config = $this->getInviteProgressConf();
        $data = [];
        if(isset($config[$arr['step']+1])){
            $data['step'] = $arr['step']+1;
        }else{
            $data['step'] = $arr['step'];
            $data['last'] = $this->getSumPayNum($fid);
        }
        if(!empty($data['last']) && !empty($arr['reward']['spins'])){
            if($num > $arr['reward']['spins']){
                return false;
            }
            if($num > 0){
                $data['last'] = intval($arr['last']) + $num;
                $arr['reward']['spins'] = $num;
            }
        }
        oo::commonOprRedis('common')->hset(okeys::userinvitesuc($uid), $fid, json_encode($data));
        //添加奖励
        oo::commonOprModel('member')->optProperty($uid,$arr['reward'],'+',115,'新邀请进度奖励:'.$uid.':'.$fid);
        return true;
    }

    /**
     * 获取玩家invite进度奖励累计充值钻石可领个数
     * @param int $uid
     * @return int
     */
    public function getSumPayNum($uid) {
        return (int)oo::commonOprRedis('User')->get(okeys::inviteSumPayNum($uid));
    }

    /**
     * 获取用户邀请信息
     * @param  inviteid  邀请ID
     * @param  uid       发起邀请的用户id
     * @param  invite    需要插入的邀请数组
     * @return <0,失败; =0,成功
     */
    public function getInvite($inviteid, $uid, &$invite) {
        $num = 0;
        $invite = array();
        $table = otable::userinvite($uid);
        $sql = " SELECT `siteuidList`, `joinList`, `time`, `requestid`, `type` FROM $table WHERE id = $inviteid AND uid = $uid LIMIT 1 ";
        $rs = oo::commonOprDb('common')->getOne($sql, MYSQLI_ASSOC);
        if( is_array($rs) && !empty($rs) ){
            $num = oo::commonOprDb('common')->affectedRows();
            $invite[0] = $rs;
        }
        return $num;
    }

    /**
     * 更新用户的邀请，一般用途是更新加入应用的用户siteuid
     * @param  inviteid  邀请ID
     * @param  uid       邀请的用户uid
     * @param  array     需要设置的数组
     * @return <0,失败; =0,成功
     */
    public function updateInvite($inviteid, $uid, $array) {
        if( !is_array($array) || empty($array) ){
            return -1;
        }
        $table = otable::userinvite($uid);
        $where = " id = $inviteid AND uid = $uid ";
        $set = ' SET ';
        foreach( $array as $k => $val ){
            $set .= " $k = '$val' ";
        }
        $sql = " UPDATE $table $set WHERE $where LIMIT 1 ";
        $rs = oo::commonOprDb('common')->query($sql);
        $num = oo::commonOprDb('common')->affectedRows();
        return $num >= 1 ? 0 : -1;
    }


    /**
     * 判断玩家当天可以获得多少奖励
     * @param  int    uid   邀请的用户uid
     * @param  string list  新发送邀请的siteuid列表,','隔开
     * @param  int    money 邀请者本次邀请可以获得的奖励数量
     * @param  int    inviteCount 邀请者本次邀请成功领奖的人次
     * @return int    <0,失败; =0,成功
     */
    public function getRwdMoney($uid, $list, &$money=0, &$inviteCount=0) {
        $newInviteArr = explode(',', trim($list, ' ,'));
        $memData      = $this->getTodayInvite($uid);
        $memData      = (empty($memData)) ? array() : $memData;
        $rwdCount     = count($memData);
        $dailyInviteLimit = $this->dailyInviteLimit;
        if ($rwdCount >= $dailyInviteLimit) {
            return 0;
        }
        $diffArr      = array_diff($newInviteArr, $memData);
        $inviteCount  = count($diffArr);
        $newMemData   = array_merge($memData, $diffArr);
        $ret          = $this->setTodayInvite($uid, $newMemData);
        if (empty($ret)) {
            return -1;
        }
        $inviteCount  = (($rwdCount + $inviteCount) >= $dailyInviteLimit) ? ($dailyInviteLimit - $rwdCount) : $inviteCount;
        $sendChips = $this->getSendChipsByRange($uid);
        $money = $inviteCount * $sendChips;
        return 0;
    }

    /**
     *
     * @param unknown $uid
     * @return number
     */
    public function getSendChipsByRange($uid)
    {
        return $this->inviteReward;//用回原来的奖励
    }

    /**
     * 获取用户邀请mcache的key
     * @param  uid       邀请的用户uid
     * @return mcache的key
     */
    private function _createMemKey($uid) {
        return $uid."_invite_".date('Ymd');
    }

    /**
     * 获取用户今日已邀请列表
     * @param  int   uid       邀请者的用户uid
     * @return array 已发送的目标siteuid列表
     */
    public function getTodayInvite($uid) {
        $memKey = $this->_createMemKey($uid);
        $data = oo::commonOprRedis('usercache')->hGetAll($memKey);
        return $data;
    }

    /**
     * 设置用户今日已邀请列表
     * @param  int   uid       邀请者的用户uid
     * @param  array data      已发送的目标siteuid数组
     * @return bool  设置mcache是否成功
     */
    public function setTodayInvite($uid, $data) {
        $memKey = $this->_createMemKey($uid);
        $expire = oo::redisRandomExpire(strtotime('23:59:59') - time());
        $ret = oo::commonOprRedis('usercache')->hMset($memKey, $data);
        oo::commonOprRedis('usercache')->expire($memKey, $expire);
        return $ret;
    }


    /**
     * 插入用户邀请信息
     * @param  inviteid  邀请ID
     * @param  invite    需要插入的邀请数组
     * @return <0,失败; =0,成功
     */
    public function setInvite($inviteid, $array) {
        if(!is_array($array) || empty($array) || empty($inviteid) ){
            return -1;
        }
        $uid = $array['uid'];
        $table = otable::userinvite($uid);
        $siteuidList = $array['siteuidList'];
        $joinList = $array['joinList'];
        $time = $array['time'];
        $requestid = $array['requestid'];
        $type = $array['type'];

        $sql = " INSERT IGNORE INTO $table VALUES ($inviteid, $uid, '$siteuidList', '$joinList', $time, '$requestid', '$type') ";
        $rs = oo::commonOprDb('common')->query($sql);
        if( $rs == true ){
            return 0;
        }
        return -1;
    }

    /**
     * 邀请列表
     * @param $uid
     * @param $touid
     * @param $isReard
     * @return array
     * Created by: Owen
     * Created on: 2020/1/8 17:04
     */
    public function getInviteRewardList($uid,$touid = 0,$isReard = 0){
        $tb = otable::userinvitesuc();
        if($touid != 0){
            $sql = "SELECT * FROM {$tb} WHERE is_senduid={$uid} AND is_backuid={$touid} LIMIT 1";
            $ret = oo::commonOprDb('common')->getOne($sql,MYSQLI_ASSOC);
            return $ret;
        }
        if($isReard){
            $sql = "SELECT DISTINCT(is_backuid),is_reward FROM {$tb} WHERE is_senduid={$uid} AND is_reward=0 ORDER BY is_reward,is_time DESC";
        }else{
            $sql = "SELECT DISTINCT(is_backuid),is_reward FROM {$tb} WHERE is_senduid={$uid} ORDER BY is_reward,is_time DESC";
        }
        $ret = oo::commonOprDb('common')->getAll($sql,MYSQLI_ASSOC);
        $uids= array_column($ret,'is_backuid');
        $out = [];
        if(!empty($uids)){
            $userinfos = [];
            oo::commonOprModel('member')->getUserInfoMulti(array('keylist' => $uids), $userinfos);
            foreach ($ret as $key=>$row){
                if(empty($userinfos[$key]['nick'])){
                    continue;
                }
                $out[] = [
                    'uid'      =>$row['is_backuid'],
                    'isreward' =>$row['is_reward'],
                    'nick'     =>$userinfos[$key]['nick'],
                    's_picture'=>$userinfos[$key]['s_picture'],
                ];
            }
        }
        return $out;
    }

    /**
     * 领取邀请奖励-(邀请人A领去所有邀请奖励,或者被邀请人B领奖)
     * @param $uid
     * @param $toUidArr
     * @return string
     * Created by: Owen
     * Created on: 2021/3/12 11:32
     */
    public function getInviteRewardArr($uid,$toUidArr){
        $toUidArr  = implode(',',$toUidArr);
        $tb  = otable::userinvitesuc();
        $ret = oo::commonOprDb('common')->getAll("SELECT is_backuid FROM {$tb} WHERE is_reward=0 AND is_senduid={$uid} AND is_backuid IN ({$toUidArr})",MYSQLI_ASSOC);
        $backUidArr= array_column($ret,"is_backuid");
        oo::commonOprDb('common')->query("UPDATE {$tb} SET is_reward=1 WHERE is_senduid='{$uid}' AND is_backuid IN ({$toUidArr})",false);
        $actionNum = count($backUidArr);
        $fbUid = [];
        if($actionNum){
            $version = oo::commonOprModel('user')->getUserVersion($uid);
            if(oo::compareVersion($version,'1.8.4')){
                $spinsConfig = self::inviteConfig($uid);
                $fbNum = 0;
                $base  = $spinsConfig['base'];
                $bind  = $spinsConfig['bind'];
                foreach ($backUidArr as $row){
                    $userInfo = oo::commonOprModel('member')->getUserInfo($row);
                    if($userInfo['isFb']==1){
                        $fbUid[] = $row;
                        $fbNum ++;
                    }
                }
                $spinsNum = $base * $actionNum + $bind * $fbNum;
            }else{
                $spinsNum  = self::inviteConfig($uid)['base'] * $actionNum;
            }
            $reward = ['spins'=>$spinsNum];
            oo::commonOprModel('member')->optProperty($uid,$reward,'+',51,'邀请奖励：基础奖励=>'.implode(',',$backUidArr).",绑定奖励:".implode(",",$fbUid));
            $userInfo = oo::commonOprModel('member')->getUserInfo($uid);
            $data[] = [
                'uid'   =>$uid,
                'u_flag'=>$userInfo['u_flag'],
                'avatar'=>$userInfo['avatar'],
                'nick'  =>$userInfo['nick'],
                's_picture'=>$userInfo['s_picture'],
                'isFb'  =>$userInfo['isFb'],
            ];
            foreach ($backUidArr as $toUid){
                oo::commonOprRedis('User')->setex(okeys::InviteeFbReward($toUid),$uid,15*24*60*60);
                oo::commonOprModel('Workerman')->push($toUid,ocmd::$send['Invitee'],$data);
            }
            return oo::response(1,$reward,'',true);
        }
        return oo::response(-2,[],'无领取对象');
    }

    /**
     * 获取邀请人Uid
     * @param $uid
     * @return int
     * Created by: Owen
     * Created on: 2021/3/12 11:39
     */
    public function getInviteInfo($uid){
        $tb  = otable::userinvitesuc();
        $ret = oo::commonOprDb('common')->getOne("SELECT * FROM {$tb} WHERE is_backuid={$uid} LIMIT 1",MYSQLI_ASSOC);
        return $ret;
    }

    /**
     * 记录邀请者绑定FB
     * @param $uid
     * Created by: Owen
     * Created on: 2021/3/12 12:31
     */
    public function recordInviteBindFb($uid){
        $ret = $this->getInviteInfo($uid);
        if(!empty($ret)){
            if($ret['is_reward'] == 1){
                $inviteUid = $ret['is_senduid'];
                $version = oo::commonOprModel('user')->getUserVersion($inviteUid);
                if(oo::compareVersion($version,"1.8.4")){
                    oo::commonOprRedis('User')->sAdd(okeys::inviteBindFb($inviteUid),$uid);
                    oo::commonOprRedis('User')->expire(okeys::inviteBindFb($inviteUid),15*24*60*60);
                    oo::commonOprRedis('User')->delete(okeys::t_userinfoNew($uid)); //user_info新缓存
                    $userInfo = oo::commonOprModel('member')->getUserInfo($uid);
                    $data[] = [
                        'uid'   =>$uid,
                        'u_flag'=>$userInfo['u_flag'],
                        'avatar'=>$userInfo['avatar'],
                        'nick'  =>$userInfo['nick'],
                        's_picture'=>$userInfo['s_picture'],
                        'isFb'  =>$userInfo['isFb'],
                    ];
                    oo::commonOprModel('Workerman')->push($inviteUid,ocmd::$send['InviteeBindFb'],$data);
                }
                return $inviteUid;
            }
        }
    }

    /**
     * 受邀请者绑定FB列表
     * @param $uid
     * @return array
     * Created by: Owen
     * Created on: 2021/3/12 15:04
     */
    public function getInviteeBindFbList($uid){
        $uidArr = oo::commonOprRedis('User')->sMembers(okeys::inviteBindFb($uid));
        $data = [];
        foreach ($uidArr as $toUid){
            $userInfo = oo::commonOprModel('member')->getUserInfo($toUid);
            $data[] = [
               'uid'   =>$toUid,
               'u_flag'=>$userInfo['u_flag'],
               'avatar'=>$userInfo['avatar'],
               'nick'  =>$userInfo['nick'],
               's_picture'=>$userInfo['s_picture'],
               'isFb'  =>$userInfo['isFb']
            ];
        }
        return $data;
    }

    /**
     * 获取受邀请者绑定FB奖励-(邀请者A领取所有B绑定FB奖励)
     * @param $uid
     * @return array
     * Created by: Owen
     * Created on: 2021/3/12 15:04
     */
    public function rewardInviteeBindFb($uid){
        $uidArr = oo::commonOprRedis('User')->sMembers(okeys::inviteBindFb($uid));
        foreach ($uidArr as $toUid){
            oo::commonOprRedis('User')->sRemove(okeys::inviteBindFb($uid),$toUid);
        }
        $spins = self::inviteConfig($uid)['bind'] * count($uidArr);
        $reward = ['spins'=>$spins];
        oo::commonOprModel('member')->optProperty($uid,$reward,'+',51,"邀请奖励：绑定奖励:".implode(",",$uidArr));

        $userInfo = oo::commonOprModel('member')->getUserInfo($uid);
        $data[] = [
            'uid'   =>$uid,
            'u_flag'=>$userInfo['u_flag'],
            'avatar'=>$userInfo['avatar'],
            'nick'  =>$userInfo['nick'],
            's_picture'=>$userInfo['s_picture'],
            'isFb'  =>$userInfo['isFb'],
        ];
        foreach ($uidArr as $toUid){//A领取奖励,给B 发奖励标识并推送
            oo::commonOprRedis('User')->setex(okeys::InviteeFbReward($toUid),$uid,15*24*60*60);
            oo::commonOprModel('Workerman')->push($toUid,ocmd::$send['Invitee'],$data);
        }

        return oo::response(1,$reward,'',true);
    }



    /**
     * 邀请奖励
     * @param $uid
     * @return int
     * Created by: Owen
     * Created on: 2020/7/24 17:32
     */
    public function inviteConfig($uid){
        $userInfo    = oo::commonOprModel('member')->getUserInfo($uid);
        $userLevelId = oo::commonOprModel('member')->getUserLevel($uid);
        $sid         = oo::getDefinedSid($uid);
        $isFb        = $userInfo['isFb'];
        $levelId     = $userLevelId['levelId'];
        $base        = 30;
        $bind        = 30;
        $ret = oo::commonOprModel('config')->getInviteRewardConfig(0,$sid);
        array_multisort(array_column($ret,'section_id'),SORT_DESC,$ret);
        foreach($ret as $row){
            if($row['level'] <= $levelId){
                $base = $isFb==1?intval($row['spins_fb']):intval($row['spins_guest']);
                $bind = $row['bind_fb'];
                break;
            }
        }
        return [
            'base' =>$base,
            'bind' =>$bind,
            'extra'=>oo::commonOprModel('readconfig')->getSysCon("Game","inviteBindFBExtraReward") ?? 50
        ];
    }

    /**
     * 获取用户邀请链接
     * @param $uid
     * @return string
     * Created by: Owen
     * Created on: 2020/8/26 11:58
     */
    public function getUserInviteUrl($uid){
        $version = oo::commonOprModel('user')->getUserVersion($uid);
        if(oo::compareVersion($version,'1.9')){
            if(IS_DEBUF){
                return [
                    okeys::InviteUrl()."api.php/".base64_encode(-$uid."|1"),
                    okeys::InviteUrl()."api.php/".base64_encode(-$uid."|2"),
                    okeys::InviteUrl()."api.php/".base64_encode(-$uid."|3"),
                ];
            }
            return [
                okeys::InviteUrl().base64_encode($uid."|1"),
                okeys::InviteUrl().base64_encode($uid."|2"),
                okeys::InviteUrl().base64_encode($uid."|3"),
            ];
        }else{
            if(IS_DEBUF){
                return okeys::InviteUrl().base64_encode(-$uid);
            }
            return okeys::InviteUrl().base64_encode($uid);
        }
    }

    /**
     * 領獎上報
     * @param $uid
     * @param $toUid
     * @param $exchange
     * @return string
     * Created by: Owen
     * Created on: 2020/8/26 12:05
     */
    public function inviteUrlRecord($uid,$toUid,$exchange = false){
        $cacheKey = okeys::InviteUrlRecord($uid);
        if(!oo::commonOprRedis('User')->setnx($cacheKey,$toUid)){
            return oo::response(-2,[],'邀请记录已上报');
        }
        oo::commonOprRedis('User')->expire($cacheKey,oo::redisRandomExpire(3*24*60*60));
        $userInfo = oo::commonOprModel('member')->getUserInfo($uid);
        if($userInfo['createtime'] + 3*24*60*60 < time()){
            return oo::response(-4,[],'受邀对象超过三天');
        }

        $version = oo::commonOprModel('user')->getUserVersion($uid);
        if(oo::compareVersion($version,"1.8.4")){
            return oo::response(-2,[],'邀请记录已上报');
        }

        if($userInfo['isFb'] != 0){
            $spins = 50;
        }else{
            $spins = 20;
        }
        $tb  = otable::userinvitesuc();
        $ret = oo::commonOprDb('userinfo')->getOne("SELECT * FROM {$tb} WHERE is_backuid={$uid} LIMIT 1",MYSQLI_ASSOC);
        if(!empty($ret)){
            if($ret['is_senduid'] == $toUid){
                return oo::response(-5,[],'邀請獎勵发放');
            }else{
                return oo::response(-6,[],'受邀請者已从其他用户邀请链接进入游戏');
            }
        }
        $money = 500000;
        oo::commonOprModel('member')->optProperty($uid,['spins'=>$spins,'money'=>$money],'+',113,"点击{$toUid}邀请码");
        oo::commonOprModel('friend')->addUserFriend($uid,$toUid);//加为好友
        $this->inviteSuccess($toUid,$uid,2);
        if($exchange){
            $info = oo::commonOprModel('member')->getUserAssetsInfo($uid);
            $info['coins'] = $info['money'];
            unset($info['money']);
            $data['reward'] = [
                'coins' => $money,
                'spins' => $spins,
            ];
            $data['info'] = $info;
            return oo::response(1,$data,"",true);
        }else{
            $toUidUserInfo = oo::commonOprModel('member')->getUserInfo($toUid);
            return oo::response(1,[
                'reward'=>[
                    'props' => [
                        ['propsId'=>14,'num'=>$money,'value'=>$money],
                        ['propsId'=>15,'num'=>$spins,'value'=>$spins],
                    ]
                ],
                'userData'=>[
                    'nick'     =>$toUidUserInfo['nick'],
                    's_picture'=>$toUidUserInfo['s_picture'],
                ]
            ]);
        }
    }

    /**
     * Notes:获取邀请人数及礼包领奖记录
     * User: wsc
     * Time: 2020/9/18 14:46
     * @param $uid
     * @param bool $db
     * @return array
     */
    public function getInviteLog($uid,$db=false){
        $key = okeys::InviteStageLog($uid);
        $data = oo::commonOprRedis('user')->hGetAll($key);
        if(empty($data)||$db){
            $tb = otable::userinvitegiftbag();
            $sql="SELECT * FROM {$tb} WHERE uid={$uid}";
            $data = oo::commonOprDb('common')->getOne($sql,1);
            if(empty($data)){
                $sql2 = "INSERT INTO {$tb} (uid,invitenum) VALUES({$uid},0)";
                $res =oo::commonOprDb('common')->query($sql2);
                if($res){
                    $data = $this->getInviteLog($uid,true);
                }
            }
            oo::commonOprRedis('user')->hMset($key,$data);
            oo::commonOprRedis('user')->expire($key,oo::redisRandomExpire(86400*5));
        }
        $data['extra_reward'] = empty($data['extra_reward']) ? [] : (array)json_decode($data['extra_reward'], true);
        return $data;
    }

    /**
     * 1.9版本后邀请人数及礼包奖励记录extra_reward解析后的数据
     * @param int $uid
     * @return array
     */
    public function getInviteLogNew($uid, $db=false) {
        $rewardLog = $this->getInviteLog($uid);
        if(empty($rewardLog['extra_reward'])){
            unset($rewardLog['extra_reward']);
            return $rewardLog;
        }
        //1.9版本添加无限级邀请进度,stage>5时奖励领取字段在extra_reward字段内
        foreach($rewardLog['extra_reward'] as $k => $v){
            $rewardLog[$k] = $v;
        }
        unset($rewardLog['extra_reward']);
        return $rewardLog;
    }

    /**
     * Notes:领取邀请进度奖励
     * User: wsc
     * Time: 2020/9/18 11:40
     * @param $uid
     * @param $stage
     * @return string
     */
    public function receiveInviteStageReward($uid,$stage){
        $data =[];
        $log = $this->getInviteLog($uid);
        $rkey = "reward{$stage}";
        //数据库大于5阶时,字段放在extra_reward字段内
        if(($stage > 5 && !empty($log['extra_reward'][$rkey]))||($stage <= 5 && $log[$rkey]!=0)){
            return oo::response(-2,[],'已领过该奖励');
        }
        $reward_conf =oo::commonOprModel('config')->inviteStageRewardConf();
        if(empty($reward_conf)||empty($log)){
            oo::logs()->debug3(["reward_conf"=>$reward_conf,"log"=>$log],'receiveISReward.log');
            return oo::response(-4,[],'配置异常');
        }
        $stages = $reward_conf ? array_column($reward_conf, 'stage') : [];
        if(!in_array($stage, $stages)){
            return oo::response(-3,[],'未达领奖条件');
        }
        $sumNum = $reward_conf[$stage-1]['num'];
        if(intval($log['invitenum'])<$sumNum){
            return oo::response(-3,[],'未达领奖条件');
        }
        $tb = otable::userinvitegiftbag();
        $ts=time();
        //数据库大于5阶时,字段放在extra_reward字段内
        if($stage > 5){
            $log['extra_reward'][$rkey] = $ts;
            $upJson = json_encode($log['extra_reward']);
            $sql = "UPDATE {$tb} SET extra_reward='{$upJson}' WHERE uid={$uid}";
        }else{
            $sql = "UPDATE {$tb} SET {$rkey}={$ts} WHERE uid={$uid}";
        }
        $res = oo::commonOprDb('common')->query($sql);
        if(!$res){
            oo::logs()->debug3(["update_err"=>$res],'receiveISReward.log');
            return oo::response(-5,[],'更新领奖记录失败');
        }
        $this->getInviteLog($uid,true);//更新缓存
        foreach ($reward_conf[$stage-1]['prize'] as $key=>$val){
            if($val['propsId']==14&&$val['rtype']){
                $val['num'] = oo::commonOprModel('goods')->getGoodCoins($uid,$val['rtype']) * intval($val['num']);
            }
            oo::commonOprModel('member')->sendReward($uid,$val['propsId'],$val['num'],114,"阶段：{$stage}");
            $data[] =["propsId"=>$val['propsId'],"num"=>$val['num'],"value"=>$val['num']];
        }
        //领奖进度统计打点
        $key = okeys::inviteStageSuccReward(date('Ymd'));
        $ret = oo::commonOprRedis("statistics")->hIncrBy($key,$stage,1);
        if($ret <= 1){
            oo::commonOprRedis("statistics")->expire($key,oo::redisRandomExpire(3*86400));
        }
        return oo::response(1,$data,'领取成功');
    }

    /**
     * 邀请成功
     * @param $uid  int 被邀请人
     * @param $toUid int 邀请发起人
     * @param $from
     * Created by: Owen
     * Created on: 2021/3/11 17:13
     */
    public function inviteSuccess($uid,$toUid,$from){
        if($uid == $toUid){
            return false;
        }
        $gbTb = otable::userinvitegiftbag();
        oo::commonOprDb('common')->query("INSERT INTO {$gbTb} (uid, invitenum) VALUES({$uid}, 1) ON DUPLICATE KEY UPDATE invitenum = invitenum + 1") && $this->getInviteLog($uid,true);//入邀请礼包数据库
        $sucTime   = time();
        $tb = otable::userinvitesuc();
        oo::commonOprDb('common')->query("INSERT INTO {$tb} (is_senduid,is_backuid,is_time,is_reward,type) VALUES ({$uid}, {$toUid}, {$sucTime},0,{$from})") && oo::commonOprModel('config')->getLastFriendInfo($uid,true);//入库邀请成功玩家
        $toUidInfo = oo::commonOprModel('member')->getUserInfo($toUid);
        $nick      = $toUidInfo['nick'];
        $s_picture = $toUidInfo['s_picture'];
        $is_real   = 0;
        if(oo::compareVersion($toUidInfo['version'],"1.7.8")){
            if(oo::commonOprModel('Workerman')->isUidOnline($uid)){
                oo::commonOprModel('Workerman')->push($uid,ocmd::$send['InviteProgress'],oo::commonOprModel('invite')->getInviteProgressInfo($uid,$toUid,true));
                $is_real = 1;
            }
            oo::commonOprModel('message')->addMessage($uid,$toUid,$nick,$s_picture,0,10,$is_real);
        }else{
            $spinsNum = oo::commonOprModel('invite')->inviteConfig($toUid)['base'];
            oo::commonOprModel('Workerman')->push($uid,ocmd::$send['Reward_inviteUrl'],['uid'=>$toUid,'isreward'=>0,'nick'=>$nick,'s_picture'=>$s_picture,'reward'    => [
                ['propsId'=>15,'num'=>$spinsNum,'value'=>$spinsNum],
            ]]);
            oo::commonOprModel('message')->addMessage($uid,$toUid,$nick,$s_picture,0,7,$is_real);
        }
        //写邀请父id
        if(oo::commonOprModel('member')->updateUserInfo($toUid, array('inviteuid' =>$uid))<1){
            oo::logs()->debug3(array('uid' => $uid, 'fid' => $toUid, 'time' => time(),"mid"=>1),'InviteReportErr.log');
        }
        oo::commonOprRedis('common')->hset(okeys::userinvitesuc($uid), $toUid, json_encode(['step' => 0]));//新版邀请成功领奖和领奖进度-0
        oo::commonOprModel('activitynew')->addTrafficPermitNum($uid,1);//通行证任务1 邀请好友
        oo::commonOprRedis("statistics")->hIncrBy(okeys::friendRecallSta(3),$toUid,1);//好友召回统计
        oo::commonOprRedis("Statistics")->hIncrBy(okeys::inviteEventSta(oo::getDefinedSid($toUid),3),4,1);//邀请事件统计
        //召回活动-fb邀请任务
//        if(oo::compareVersion($toUidInfo['version'],"1.8.4")){
//            oo::commonOprModel('callback')->doTask($uid, 6, 1);
//        }
        //数数事件-邀请成功
        oo::commonOprModel('ta')->setEventData($toUid,"invite_success",["invite_user"=>$uid]);
        //数数事件用户数据-用户邀请人,用户召回人
        oo::commonOprModel('ta')->setEventData($uid,'user_set',['invited_user'=>$toUid,"recalled_user "=>$toUid]);
        //数数事件用户数据-用户邀请玩家数量
        oo::commonOprModel('ta')->setEventData($toUid,'user_set',["invite_num"=>count($this->getInviteRewardList($toUid))]);

    }

    /**
     * 被邀请方绑定FB额外奖励(用于邀请发起人数据展示)
     * @param $uid
     * @return array
     * Created by: Owen
     * Created on: 2021/3/23 14:25
     */
    public function InviteeBindFbExtra($uid){
        $inviteUid = oo::commonOprRedis('User')->get(okeys::InviteeFbReward($uid));
        if(empty($inviteUid)){
            return [];
        }
        $userInfo = oo::commonOprModel('member')->getUserInfo($inviteUid);
        $data[] = [
            'uid'   =>$inviteUid,
            'u_flag'=>$userInfo['u_flag'],
            'avatar'=>$userInfo['avatar'],
            'nick'  =>$userInfo['nick'],
            's_picture'=>$userInfo['s_picture'],
            'isFb'  =>$userInfo['isFb'],
        ];
        return $data;

    }

    /**
     * 被邀请方绑定FB额外奖励 -- 领取
     * @param $uid
     * @return array
     * Created by: Owen
     * Created on: 2021/3/23 14:25
     */
    public function RewardInviteeBindFbExtra($uid){
        $inviteUid = oo::commonOprRedis('User')->get(okeys::InviteeFbReward($uid));
        if(empty($inviteUid)){
            return oo::response(errorCode::NONE_REWARD);
        }
        $userInfo = oo::commonOprModel('member')->getUserInfo($uid);
        if(!$userInfo['isFb']){
            return oo::response(errorCode::CONDITION_NOT_RNOUGH);
        }
        $extra = oo::commonOprModel('readconfig')->getSysCon("Game","inviteBindFBExtraReward") ?? 50;
        $reward['spins'] = $extra;
        oo::commonOprModel('member')->optProperty($uid,$reward,'+',51,'被邀请者绑定FB额外奖励,来源'.$inviteUid);
        oo::commonOprRedis('User')->delete(okeys::InviteeFbReward($uid));
        return oo::response(errorCode::SUCCESS,['reward'=>['spins'=>$extra]]);
    }
}
