<?php
/**
 * Created by PhpStorm.
 * User: ywl
 * Date: 2017/4/14
 * Time: 11:38
 */

namespace App\User\Services;


use App\Exceptions\ApiException;
use App\Services\CommonBaseService;
use App\User\Facades\SysLogFacade;
use App\User\Facades\SysMenuFuncAuthFacade;
use App\User\Models\SysAdminUserModel;
use Illuminate\Support\Facades\Cache;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Mail;

class SysAdminUserService extends CommonBaseService
{
    protected $cache = true;

    protected $cacheBucket = 'SysAdminUser:';

    protected $tokenBucket = 'AdminToken:';

    protected $activeBucket = "Active:";

    /**
     * 设置token缓存时间
     * @param $token
     * @param $user
     */
    public function setToken($token, $user)
    {
        Cache::put($this->getTokenKey($token), $user, config('cache.token'));
    }

    /**
     * 移除token缓存
     * */
    public function forgotToken($token)
    {
        return Cache::pull($this->getTokenKey($token));
    }

    /**
     * 获取token缓存key
     * @param $token
     * @return string
     */
    private function getTokenKey($token)
    {
        return $this->tokenBucket . $token;
    }

    /**
     * 获取后台用户列表
     * */
    public function getAdminUserList($params)
    {
        $pageSize = empty($params['page_size']) ? 10 : $params['page_size'];
        $page = empty($params['page']) ? 1 : $params['page'];
        $skip = ($page - 1) * $pageSize; //页面记录的开始位置，即偏移量
        $where = [];
        $where[] = ['a.status', '<', '2'];
        $query = $this->model->alias('a')
            ->leftJoin('sys_role as b','a.role_id','=','b.id')
            ->where($where);
        if (!empty($params['keyword'])) {
            $keyword = $params['keyword'];
            $query->where(function ($queryStr) use ($keyword) {
                $queryStr->where('a.user_name', 'like', "%" . $keyword . "%")
                    ->orWhere('a.real_name', 'like', "%" . $keyword . "%");
            });
        }
        $totalCount = $query->count();
        $list = $query->skip($skip)
            ->limit($pageSize)
            ->selectRaw('a.id,a.user_name,a.real_name,a.phone,a.last_login_time,a.status,a.create_time,a.role_id,b.role_name')
            ->get()->toArray();
        $results = buildPage($list, $skip, $page, $pageSize, $totalCount);
        return $results;
    }

    /**
     * 新增后台修改用户信息
     * @return array
     * */
    public function saveAdminUser($params)
    {
        $userData = $this->buildAddAdminUser($params);
        if (!empty($userData['id'])) {
            $id = $userData['id'];
            $this->updateBy(['id' => $userData['id']], $userData);
            //求改当前用户的信息需要更新redis缓存
            if ($id == $this->getAuthUserId()) {
                $this->updateUserInfoCache();
            }
        } else {
            $id = $this->model->insertGetId($userData);
        }
        return $id;
    }

    /**
     * 构造编辑用户详情数据
     * @return array
     * */
    private function buildAddAdminUser($params)
    {
        $userData = [];
        if (isset($params['password'])) {
            $userData['salt'] = getRandomStr('PW');
            $password = $userData['salt'] . $params['password'];
            $userData['password'] = md5($password);
        }
        $time = nowTime();
        $userData['update_time'] = $time;
        if (!empty($params['id'])) {
            if (isset($params['password'])) {
                //修改密码要校验
                $this->checkLoginPassword($params['login_password']);
            }
            $userData['id'] = $params['id'];
            if (isset($params['real_name'])) {
                $userData['real_name'] = $params['real_name'];
            }
            if (isset($params['phone'])) {
                $userData['phone'] = $params['phone'];
                $info=$this->model
                    ->where('status','<',2)
                    ->where('id','<>',$params['id'])
                    ->where('phone', $userData['phone'])->first();
                if(!empty($info)){
                    throw new ApiException(10011,['phone'=>$userData['phone']]);
                }
            }
            if (isset($params['status'])) {
                $userData['status'] = $params['status'];
            }
            if (isset($params['role_id'])) {
                $userData['role_id'] = $params['role_id'];
            }
        } else {
            $userData['user_name'] = $params['user_name'] ?? '';
            $userData['real_name'] = $params['real_name'] ?? '';
            $userData['phone'] = $params['phone'] ?? '';
            $info=$this->model->where('status','<',2)
                ->where(function ($queryStr) use ($userData) {
                    $queryStr->where('user_name', '=',$userData['user_name'])
                        ->orWhere('phone', '=', $userData['phone']);
                })->first();
            if(!empty($info)){
                $info=$info->toArray();
                if($info['phone']==$userData['phone']){
                    throw new ApiException(10011,['phone'=>$userData['phone']]);
                }else{
                    throw new ApiException(10010,['user_name'=>$userData['user_name']]);
                }
            }
            $userData['create_time'] = $time;
            if (isset($params['status'])) {
                $userData['status'] = $params['status'];
            } else {
                $userData['status'] = SysAdminUserModel::STATUS_DISABLED;
            }
            if (isset($params['role_id'])) {
                $userData['role_id'] = $params['role_id'];
            }
        }
        return $userData;
    }

    /**
     * 根据id获取用户详情
     * */
    public function getUserInfoById($id)
    {
        $info = $this->model->where(['id' => $id])->first();
        $dataInfo = [];
        if (!empty($info)) {
            $dataInfo = $info->toArray();
        }
        return $dataInfo;
    }

    /**
     * 校验登陆密码
     * */
    private function checkLoginPassword($loginPassword)
    {
        $userInfo = $this->getAuthUser();
        if (!empty($userInfo)) {
            $prefixed = $userInfo['salt'];
            $password = $prefixed . $loginPassword;
            $loginPasswordMd5 = md5($password);
            if ($loginPasswordMd5 === $userInfo['password']) {
                return true;
            }
        }
        throw new ApiException(10001);
    }

    /**
     * 更新用户缓存
     * */
    public function updateUserInfoCache($token = '', $user = [])
    {
        if (empty($user)) {
            $userId = $this->getAuthUserId();
            $newUser = $this->getUserInfoById($userId);
        } else {
            $newUser = $user;
        }
        if (empty($token)) {
            if (config('app.login_singleton')) {
                $key = $this->cacheBucket . $this->tokenBucket . $userId . 'admin_token';
                $token = Cache::get($key);
            } else {
                $token = $this->getAuthToken();
            }
        }
        $CacheTokenTimeMinute = config('cache.token');
        $nowTime = time();
        $expiration_time = $nowTime + 60 * $CacheTokenTimeMinute;
        $newUser['expiration_time'] = $expiration_time;//过期时间
        $newUser['token'] = $token;
        $newUser['permission'] = $this->getPermission($newUser['role_id']);
        $this->setToken($token, $newUser);
        return $newUser;
    }

    /**
     * 根据用户名密码登陆
     * */
    public function adminLoginByPassword($params)
    {
        $ret = ['code' => 0, 'data' => []];
        if (empty($params)) {
            return;
        }

        $where = [];
        $where['user_name'] = $params['user_name'];
        $where['status'] = 0;
        $userInfo = $this->model->alias('a')
            ->where($where)->selectRaw('a.*')->first();
        if (!empty($userInfo)) {
            $prefixed = $userInfo->salt;
            $password = $prefixed . $params['password'];
            $loginPasswordMd5 = md5($password);
            if ($loginPasswordMd5 == $userInfo->password) {
                $now = nowTime();
                $userInfo->last_login_time = $now;
                $randomStr = getRandomStr('ADMIN_TOKEN');
                $token = md5($userInfo['user_name'] . $randomStr);
                $userInfo->save();
                $userInfo = $userInfo->toArray();
                $CacheTokenTimeMinute = config('cache.token');
                $nowTime = time();
                $expiration_time = $nowTime + 60 * $CacheTokenTimeMinute;
                $userInfo['expiration_time'] = $expiration_time;//过期时间
                $userInfo['token']=$token;
                $userInfo['permission']=$this->getPermission($userInfo['role_id']);
                if (config('app.login_singleton')) {
                    $this->setCacheToken($userInfo['id'], $token);
                }
                $this->setToken($token, $userInfo);
                SysLogFacade::saveSysLoginLog($userInfo['id']);
                $ret['data']['token'] = $token;
            }else{
                $ret['code'] = 10001;
            }
        } else {
            $ret['code'] = 10006;
        }
        return $ret;
    }

    private function getPermission($roleId){
        $data=SysMenuFuncAuthFacade::adminRoleAuth($roleId);
        $permission=[];
        foreach ($data as $value){
            if(!empty($value['route_path'])){
                $permission[]=$value['route_path'];
            }
        }
        return  $permission;
    }

    /**
     * 用户登出
     * */
    public function logout($token)
    {
        if (empty($token)) {
            return;
        }
        $this->forgotToken($token);
        return true;
    }

    /**
     * 根据token获取用户
     * @param $token
     * @return SysAdminUserModel | mixed
     */
    public function findOneByToken($token)
    {
        return Cache::get($this->getTokenKey($token));
    }

    /**
     * 获取用户的详细信息
     * @param int $type 0 简略详细 1详细信息
     * */
    public function getUserDetail($type = 0)
    {
        $ret = ['code' => 0, 'data' => []];
        $baseFields=['id','user_name','real_name','is_super','permission'];
        $detailFields=['id','user_name','real_name','phone','is_super','permission','role_id','area_id'];
        $user = $this->getAuthUser();
        $resultUser = [];
        if ($type) {
            $resultFields = $detailFields;
        } else {
            $resultFields = $baseFields;
        }
        foreach ($resultFields as $value) {
            $resultUser[$value] = $user[$value];
        }
        $ret['data'] = $resultUser;
        return $ret;
    }


    /**
     * 设置当前用户token
     * @param $userId
     * @param $token
     */
    public function setCacheToken($userId, $token)
    {
        $key = $this->cacheBucket . $this->tokenBucket . $userId . 'admin_token';
        Cache::put($key, $token, config('cache.token'));
    }

    /**
     * 是否最近登录的一个账号
     * @param $userId
     * @param $token
     * @return bool
     */
    public function isLastToken($userId, $token)
    {
        $key = $this->cacheBucket . $this->tokenBucket . $userId . 'admin_token';
        $insideToken = Cache::get($key);
        //如果缓存中不存在token
        if (!$insideToken) {
            $this->setCacheToken($userId, $token);
            return true;
        }
        //如果缓存中的token跟用户传入的token一致
        if ($insideToken == $token) {
            return true;
        }
        return false;
    }

    public function heartbeat($token)
    {
        if ($token) {
            $data = $this->findOneByToken($token);
            if (!empty($data)) {
                return $this->updateUserInfoCache($token, $data);
            }
        }
    }

}
