<?php
/**
 * Created by PhpStorm.
 * User: liang
 * Date: 2020/2/18
 * Time: 6:36 PM
 */
namespace console\controllers;


use common\models\UserInfo;
use common\models\UserNetwork;
use common\models\UserRelation;

class FixNetController extends BaseController {

    const LIMIT = 1000;
    //顶点ID列表
    const TOP_ID_LIST = [
        '670B84FD7C216D4EE055736AECE8644D',
        '80552117701578757',
    ];
    //PARENT_UIDS缓存键
    const FIX_NET_CACHE_NETWORK_PARENT_UIDS_KEY = 'fixNet:cache:network:parentUids:key';
    const FIX_NET_CACHE_RELATION_PARENT_UIDS_KEY = 'fixNet:cache:relation:parentUids:key';

    const FIX_RELATION_DEEP_DEEP_USER_ID_KEY = 'fixRelationDeepDeepUserIdKey_%d';

    /**
     * 清空缓存
     */
    public function actionClearCache() {
        $this->_clearNetworkParentUidsCache();
        $this->_clearRelationParentUidsCache();
        echo '缓存清理成功' . PHP_EOL;
    }

    /**
     * 安置数据
     * @param int $startPage
     * @throws \yii\db\Exception
     */
    public function actionNetwork($startPage=1) {
        $allCount = UserNetwork::find()->where('1=1')->orderBy('TOP_DEEP ASC,ID ASC')->count('ID');
        $limit = self::LIMIT;
        $pageCount = ceil($allCount/$limit);
        unset($allCount);
        for($page=$startPage;$page<=$pageCount;$page++) {
            $userList = UserNetwork::find()->where('1=1')->orderBy('TOP_DEEP ASC,ID ASC')->limit($limit)->offset(($page-1)*$limit)->asArray()->all();
            foreach ($userList as $everyUser) {
                //顶点不处理
                if( $everyUser['PARENT_UID'] == 0 ) continue;

                $parentUidsCacheStr = $this->_getNetworkParentUidsCache($everyUser['PARENT_UID']);
                if( $parentUidsCacheStr ) {
                    $parentUidsStr = $parentUidsCacheStr . ',' . $everyUser['PARENT_UID'];
                }else {
                    if( $everyUser['TOP_DEEP'] == 1 ) {
                        $parentUidsStr = $everyUser['PARENT_UID'];
                    }else {
                        echo sprintf('parentUids错误 userId:%s,parentUid:%s'.PHP_EOL, $everyUser['USER_ID'], $everyUser['PARENT_UID']);
                        continue;
                    }
                }

                $this->_addNetworkParentUidsCache($everyUser['USER_ID'], $parentUidsStr);

                if( $parentUidsStr != $everyUser['PARENT_UIDS'] ) {
                    UserNetwork::updateAll(['PARENT_UIDS'=>$parentUidsStr], 'ID=:ID', ['ID'=>$everyUser['ID']]);
                    echo sprintf('parentUids成功 userId:%s,parentUid:%s'.PHP_EOL, $everyUser['USER_ID'], $everyUser['PARENT_UID']);
                }
                unset($everyUser, $parentUidsCacheStr, $parentUidsStr);
            }
            unset($userList);
            echo sprintf("更新网体表数据，总页数【%s】，当前页数：【%s】更新成功".PHP_EOL, $pageCount, $page);
        }

        echo '更新网体表数据全部完成' . PHP_EOL;

    }

    /**
     * 跑关系表中所有的深度
     * @param int $deep
     */
    public function actionRelationTopDeep($deep=1) {
        if( $deep === 1 ) $this->_cacheOneDeepInit();
        //取deep的列表
        $status = $this->_calcOneDeepList($deep);

        if( $status ) $this->actionRelationTopDeep($deep+1);
    }

    /**
     * 初始化0层的缓存
     */
    private function _cacheOneDeepInit() {
        foreach (self::TOP_ID_LIST as $userId) {
            self::_addRelationDeepUserIdCache(0, $userId);
        }
    }

    /**
     * 计算某一层深度的列表
     * @param $deep
     * @param int $offset
     * @return bool
     */
    private function _calcOneDeepList($deep, $offset=0) {
        echo sprintf("时间:[%s]推荐深度，当前deep为:【%d】，当前offset为:【%d】" . PHP_EOL, date('Y-m-d H:i:s', time()) , $deep, $offset);
        $allData = self::_getRelationDeepList($deep-1, $offset, self::LIMIT);
        if( $allData ) {
            foreach ($allData as $userId) {
                $childrenList = UserRelation::find()->where('PARENT_UID=:PARENT_UID', ['PARENT_UID'=>$userId])->asArray()->all();
                foreach ($childrenList as $childData) {
                    if( $childData['TOP_DEEP'] != $deep ) {
                        UserRelation::updateAll([
                            'TOP_DEEP' => $deep,
                        ], 'USER_ID=:USER_ID', ['USER_ID'=>$childData['USER_ID']]);

                        UserInfo::updateAll(['RELATION_DEEP'=>$deep], 'USER_ID=:USER_ID', ['USER_ID'=>$childData['USER_ID']]);
                    }
                    if( !in_array($childData['TOP_UID'], self::TOP_ID_LIST) ) {
                        if( in_array($userId, self::TOP_ID_LIST) ) {
                            UserRelation::updateAll([
                                'TOP_UID' => $userId,
                            ], 'USER_ID=:USER_ID', ['USER_ID'=>$childData['USER_ID']]);
                        }else {
                            $parentData = UserRelation::find()->where('USER_ID=:USER_ID', ['USER_ID'=>$userId])->asArray()->one();
                            UserRelation::updateAll([
                                'TOP_UID' => $parentData['TOP_UID'],
                            ], 'USER_ID=:USER_ID', ['USER_ID'=>$childData['USER_ID']]);
                            unset($parentData);
                        }
                    }

                    self::_addRelationDeepUserIdCache($deep, $childData['USER_ID']);
                }
            }

            return $this->_calcOneDeepList($deep, $offset + self::LIMIT);
        }

        unset($allData);
        $this->_clearRelationDeepUserIdCache($deep-1);
        if( $offset > 0 ) {
            return true;
        }else {
            return false;
        }
    }

    /**
     * 推荐数据
     * @param int $startPage
     * @throws \yii\db\Exception
     */
    public function actionRelation($startPage=1) {
        $allCount = UserRelation::find()->where('1=1')->orderBy('TOP_DEEP ASC,ID ASC')->count('ID');
        $limit = self::LIMIT;
        $pageCount = ceil($allCount/$limit);
        unset($allCount);
        for($page=$startPage;$page<=$pageCount;$page++) {
            $userList = UserRelation::find()->where('1=1')->orderBy('TOP_DEEP ASC,ID ASC')->limit($limit)->offset(($page-1)*$limit)->asArray()->all();
            foreach ($userList as $everyUser) {
                //顶点不处理
                if( $everyUser['PARENT_UID'] == 0 ) continue;

                $parentUidsCacheStr = $this->_getRelationParentUidsCache($everyUser['PARENT_UID']);
                if( $parentUidsCacheStr ) {
                    $parentUidsStr = $parentUidsCacheStr . ',' . $everyUser['PARENT_UID'];
                }else {
                    if( $everyUser['TOP_DEEP'] == 1 ) {
                        $parentUidsStr = $everyUser['PARENT_UID'];
                    }else {
                        echo sprintf('parentUids错误 userId:%s,parentUid:%s'.PHP_EOL, $everyUser['USER_ID'], $everyUser['PARENT_UID']);
                        continue;
                    }
                }

                $this->_addRelationParentUidsCache($everyUser['USER_ID'], $parentUidsStr);

                if( $parentUidsStr != $everyUser['PARENT_UIDS'] ) {
                    UserRelation::updateAll(['PARENT_UIDS'=>$parentUidsStr], 'ID=:ID', ['ID'=>$everyUser['ID']]);
                    echo sprintf('parentUids成功 userId:%s,parentUid:%s'.PHP_EOL, $everyUser['USER_ID'], $everyUser['PARENT_UID']);
                }
                unset($everyUser, $parentUidsCacheStr, $parentUidsStr);
            }
            unset($userList);
            echo sprintf("更新推荐表数据，总页数【%s】，当前页数：【%s】更新成功".PHP_EOL, $pageCount, $page);
        }

        echo '更新推荐表数据全部完成' . PHP_EOL;
    }

    /**
     * 添加parent_uids Cache数据
     * @param $userId
     * @param $parentUidsStr
     * @return mixed
     */
    private function _addNetworkParentUidsCache($userId, $parentUidsStr) {
        return \Yii::$app->redis->hSet(self::FIX_NET_CACHE_NETWORK_PARENT_UIDS_KEY, $userId, $parentUidsStr);
    }

    /**
     * 获取parent_uids Cache数据
     * @param $userId
     * @return mixed
     */
    private function _getNetworkParentUidsCache($userId) {
        return \Yii::$app->redis->hGet(self::FIX_NET_CACHE_NETWORK_PARENT_UIDS_KEY, $userId);
    }

    /**
     * 清空parent_uids Cache数据
     * @return mixed
     */
    private function _clearNetworkParentUidsCache() {
        return \Yii::$app->redis->del(self::FIX_NET_CACHE_NETWORK_PARENT_UIDS_KEY);
    }

    /**
     * 添加parent_uids Cache数据
     * @param $userId
     * @param $parentUidsStr
     * @return mixed
     */
    private function _addRelationParentUidsCache($userId, $parentUidsStr) {
        return \Yii::$app->redis->hSet(self::FIX_NET_CACHE_RELATION_PARENT_UIDS_KEY, $userId, $parentUidsStr);
    }

    /**
     * 获取parent_uids Cache数据
     * @param $userId
     * @return mixed
     */
    private function _getRelationParentUidsCache($userId) {
        return \Yii::$app->redis->hGet(self::FIX_NET_CACHE_RELATION_PARENT_UIDS_KEY, $userId);
    }

    /**
     * 清空parent_uids Cache数据
     * @return mixed
     */
    private function _clearRelationParentUidsCache() {
        return \Yii::$app->redis->del(self::FIX_NET_CACHE_RELATION_PARENT_UIDS_KEY);
    }

    private function _clearRelationDeepUserIdCache($deep) {
        $key = sprintf(self::FIX_RELATION_DEEP_DEEP_USER_ID_KEY, $deep);
        return \Yii::$app->redis->del($key);
    }

    private function _addRelationDeepUserIdCache($deep, $userId) {
        $key = sprintf(self::FIX_RELATION_DEEP_DEEP_USER_ID_KEY, $deep);
        return \Yii::$app->redis->rpush($key, $userId);
    }

    private function _getRelationDeepList($deep, $offset = 0, $limit = 1000) {
        $key = sprintf(self::FIX_RELATION_DEEP_DEEP_USER_ID_KEY, $deep);
        return \Yii::$app->redis->lrange($key, $offset, ($offset + $limit - 1));
    }

}
