<?php
//  ---------------------------------------------------------------------------------
//    _____   _             _                   _   _____
//   |  __ \ | |           | |    /\           (_) |  __ \
//   | |__) || |__    __ _ | |   /  \    _ __   _  | |__) |_ __  ___
//   |  ___/ | '_ \  / _` || |  / /\ \  | '_ \ | | |  ___/| '__|/ _ \
//   | |     | | | || (_| || | / ____ \ | |_) || | | |    | |  | (_) |
//   |_|     |_| |_| \__,_||_|/_/    \_\| .__/ |_| |_|    |_|   \___/
//                                      | |
//                                      |_|
//   PhalApi Pro 专业版
//   广州果创网络科技有限公司
//
//  ---------------------------------------------------------------------------------
//
//   一、协议的许可和权利
//    1. 您可以在完全遵守本协议的基础上，将本软件应用于商业用途；
//    2. 您可以在协议规定的约束和限制范围内修改本产品源代码或界面风格以适应您的要求；
//    3. 您拥有使用本产品中的全部内容资料、商品信息及其他信息的所有权，并独立承担与其内容相关的
//       法律义务；
//    4. 获得商业授权之后，您可以将本软件应用于商业用途，自授权时刻起，在技术支持期限内拥有通过
//       指定的方式获得指定范围内的技术支持服务；
//
//   二、协议的约束和限制
//    1. 未获商业授权之前，禁止将本软件用于商业用途（包括但不限于企业法人经营的产品、经营性产品
//       以及以盈利为目的或实现盈利产品）；
//    2. 未获商业授权之前，禁止在本产品的整体或在任何部分基础上发展任何派生版本、修改版本或第三
//       方版本用于重新开发；
//    3. 如果您未能遵守本协议的条款，您的授权将被终止，所被许可的权利将被收回并承担相应法律责任；
//
//   三、有限担保和免责声明
//    1. 本软件及所附带的文件是作为不提供任何明确的或隐含的赔偿或担保的形式提供的；
//    2. 用户出于自愿而使用本软件，您必须了解使用本软件的风险，在尚未获得商业授权之前，我们不承
//       诺提供任何形式的技术支持、使用担保，也不承担任何因使用本软件而产生问题的相关责任；
//    3. 广州果创网络科技有限公司不对使用本产品构建的商城中的内容信息承担责任，但在不侵犯用户隐
//       私信息的前提下，保留以任何方式获取用户信息及商品信息的权利；
//
//   有关本产品最终用户授权协议、商业授权与技术服务的详细内容，均由广州果创网络科技有限公司独家
//   提供。广州果创网络科技有限公司拥有在不事先通知的情况下，修改授权协议的权力，修改后的协议对
//   改变之日起的新授权用户生效。电子文本形式的授权协议如同双方书面签署的协议一样，具有完全的和
//   等同的法律效力。您一旦开始修改、安装或使用本产品，即被视为完全理解并接受本协议的各项条款，
//   在享有上述条款授予的权力的同时，受到相关的约束和限制。协议许可范围以外的行为，将直接违反本
//   授权协议并构成侵权，我们有权随时终止授权，责令停止损害，并保留追究相关责任的权力。
//
//  ---------------------------------------------------------------------------------

namespace Base\Domain;

use Base\Common\TimeUtil;
use Base\Model\Member;
use Base\Model\Member as UserModel;
use PDOException;
use PhalApi\Exception\BadRequestException;
use PhalApi\Tool;
use Base\Model\Authorization as AuthorizationModel;

/**
 * 用户领域类
 */
class User extends Base {

    public function getOwnUsername(){
        return $this->getUsername($this->uid);
    }

    // 获取其他用户的信息，公开的信息有限
    public function profile($username) {
        $model = new UserModel();
        return $model->getBy('username', $username, array(), 'id,username,register_time,avatar,nickname,email,sex,mobile');
    }

    public function getUsername($id) {
        $model = new UserModel();
        $user = $model->get($id, 'username');
        return $user ? $user['username'] : null;
    }
    
    // 获取用户自己的信息，信息稍微多一些
    public function profileByUid($uid) {
        $model = new UserModel();
        $user = $model->get($uid, 'id,username,register_time,avatar,nickname,email,sex,mobile,member_level,member_status');
        return $this->addMoreUserInfo($user);
    }
    
    // 提供给管理后台使用的，获取的用户信息最全面
    public function profileByUidForAdmin($uid) {
        $model = new UserModel();
        $user = $model->get($uid, 'id,username,register_time,avatar,nickname,email,sex,mobile,member_level,member_status,ip');
        $info = $this->addMoreUserInfo($user);

        // 获取开放平台微信绑定信息，仅当用户存在时才查询
        if ($info) {
            $aModel = new AuthorizationModel();
            $aData = $aModel->getUserInfo(array('a.member_id' => $uid, 'authorization_type' => 1));
            $info['p_wx_nickname'] = !empty($aData['nickname']) ? $aData['nickname'] : null;
            $info['p_wx_headimgurl'] = !empty($aData['headimgurl']) ? $aData['headimgurl'] : null;
            $info['p_wx_openid'] = !empty($aData['openid']) ? $aData['openid'] : null;
        }

        return $info;
    }

    protected function addMoreUserInfo($user) {
        if ($user) {
            $user['member_level_name'] = UserType::getMemberLevelName($user['member_level']);
        }
        return $user;
    }

    public function register($username, $password, $avatar = '', $nickname = '', $email = '', $sex = 0, $mobile = '', $memberLevel = 0, $moreUserInfo = array()) {
        $salt = Tool::createRandStr(32);
        $enPassword = $this->encryptPassword($password, $salt);

        $uuid = Tool::createRandStr(32);
        
        $newUser = array(
            'username' => $username,
            'salt' => $salt,
            'password' => $enPassword,
            'avatar' => $avatar,
            'nickname' => $nickname,
            'email' => $email,
            'sex' => $sex,
            'mobile' => $mobile,
            'member_level' => $memberLevel,
            'ip' => Tool::getClientIp(),
            'register_time' => date('Y-m-d H:i:s'),
            'uuid' => $uuid,
        );
        
        // 合并更多信息，方便扩展
        if (!empty($moreUserInfo) && is_array($moreUserInfo)) {
            $newUser = array_merge($moreUserInfo, $newUser);
        }

        $model = new UserModel();
        $id = $model->insert($newUser);

        return intval($id);
    }

    public function encryptPassword($password, $salt) {
        return md5(md5($password . $salt) . \PhalApi\DI()->config->get('app.member.salt'));
    }

    // 修改密码（内含账号检测以及旧密码核对）
    public function alterPass($username, $password, $newPassword) {
        $model = new UserModel();
        $member = $model->getBy('username', $username);
        if (empty($member)) {
            return false;
        }

        return $this->alterPassByUsername($username, $member['salt'], $password, $newPassword);
    }

    // 根据uid修改密码
    public function alterPassByUid($uid, $password, $newPassword) {
        $model = new UserModel();
        $member = $model->get($uid, 'username,salt');
        if (empty($member)) {
            return false;
        }

        return $this->alterPassByUsername($member['username'], $member['salt'], $password, $newPassword);
    }

    // 根据账号名修改密码
    protected function alterPassByUsername($username, $salt, $password, $newPassword) {
        $model = new UserModel();
        $enPassword = $this->encryptPassword($password, $salt);
        $newEnPasswrod = $this->encryptPassword($newPassword, $salt);

        return $model->alterPass($username, $enPassword, $newEnPasswrod);
    }

    // 提供给管理后台使用的，直接根据用户id修改密码
    public function alterPassByUidDirectly($uid, $newPassword) {
        $model = new UserModel();
        $member = $model->get($uid, 'salt');
        if (empty($member)) {
            return false;
        }
        $password = $this->encryptPassword($newPassword, $member['salt']);
        return $model->update($uid, array('password' => $password));
    }
    
    // 根据uid更新个人资料
    public function updateProfileByUid($uid, $avatar, $nickname, $email, $sex, $mobile, $memberType) {
        $updateData = $this->createUpdateProfileData($avatar, $nickname, $email, $sex, $mobile, $memberType);
        if (empty($updateData)) {
            return false;
        }

        // 刷新缓存
        $model = new UserModel();
        $model->deleteMemberLevelCache($uid);

        $model = new UserModel();
        return $model->update($uid, $updateData);
    }

    // 根据账号更新个人资料
    public function updateProfile($username, $avatar, $nickname, $email, $sex, $mobile, $memberType) {
        $updateData = $this->createUpdateProfileData($avatar, $nickname, $email, $sex, $mobile, $memberType);
        if (empty($updateData)) {
            return false;
        }

        $model = new UserModel();
        return $model->updateBy('username', $username, $updateData);
    }

    protected function createUpdateProfileData($avatar, $nickname, $email, $sex, $mobile, $memberType) {
        $updateData = array();
        if ($avatar !== null) {
            $updateData['avatar'] = $avatar;
        }
        if ($nickname !== null) {
            $updateData['nickname'] = $nickname;
        }
        if ($email !== null) {
            $updateData['email'] = $email;
        }
        if ($sex !== null) {
            $updateData['sex'] = $sex;
        }
        if ($mobile !== null) {
            $updateData['mobile'] = $mobile;
        }
        if ($memberType !== null) {
            $updateData['member_level'] = $memberType;
        }
        return $updateData;
    }

    public function userLogin($username, $password) {
        $model = new UserModel();
        $member = $model->getBy('username', $username);
        if (empty($member)) {
            Login::addLoginLog($username, Login::LOGIN_STATUS_NOT_EXISTS);
            return false;
        }

        if ($member['member_status'] != 1) {
            Login::addLoginLog($username, Login::LOGIN_STATUS_FORBID);
            return false;
        }

        $enPassword = $this->encryptPassword($password, $member['salt']);
        
        if ($enPassword != $member['password']) {
            Login::addLoginLog($username, Login::LOGIN_STATUS_ERROR_PASS);
            return false;
        }

        return true;
    }

    //模拟登录----后台用的返回token
    public function simulationLogin($uid){
        //查询企业
//        $appsInfo =  \Base\Model\Apps::model()->getData(['uid'=>$uid]);
        $menberInfo =  \Base\Model\Member::model()->get($uid);
        if (empty($menberInfo)){
            throw new BadRequestException(\PhalApi\T("The user uid does not exist, please check the parameter"));
        }
        $config = \PhalApi\DI()->config;
        $key = $config->get('app.jwt.key');
        $time = time();
        $token = array(
            "iss" => \Base\Common\ToolUtil::createISS($key),        // 该JWT的签发者
            "aud" => 'user',        // 接收该JWT的一方
            "sub" => 'platform',                    // 该JWT所面向的开发者
            "uid" => intval($uid),
            "iat" => $time,                         // 在什么时候签发的
            "exp" => $time + $config->get('app.jwt.exp', 86400),        // 什么时候过期，这里是一个Unix时间戳
        );

        $jwt = \lmxdawn\jwt\JWT::encode($token, $key, 'HS256');

        $rs['access_token'] = $jwt;
        $rs['expire_at'] = $token['exp'];

        return $rs;
    }
    
    /** ---------- 用户等级  ---------- **/
    
    // 是否为会员
    public function isMember($uid) {
        return UserType::isMemberLevel($this->getMemberLevel($uid));
    }
    
    // 是否为开发者
    public function isDeveloper($uid) {
        return UserType::isDeveloperLevel($this->getMemberLevel($uid));
    }

    // 是否为管理员或超级管理员
    public function isAdmin($uid) {
        return UserType::isAdminLevel($this->getMemberLevel($uid));
    }

    // 是否为超级管理员
    public function isSuperAdmin($uid) {
        return UserType::isSuperAdminLevel($this->getMemberLevel($uid));
    }

    // 获取用户等级
    public function getMemberLevel($uid) {
        if ($uid <= 0) {
            return 0;
        }

        $model = new UserModel();
        $row = $model->getMemberLevel($uid);

        return $row ? $row['member_level'] : UserType::MEMBER_LEVEL_USER;
    }

    public function getUserNum(){
        $model = new UserModel();
        return $model->getAllNum();
    }

    // 检测账号是否被禁用
    public function isUserActive($uid) {
        if ($uid <= 0) {
            return false;
        }

        $model = new UserModel();
        $row = $model->getMemberStatus($uid);

        return $row && $row['member_status'] == 1 ? true : false;
    }


    // 修改用户状态
    public function alterMemberStatus($uid, $newStatus) {
        if ($uid <= 0) {
            return false;
        }

        $model = new UserModel();
        $updateRs = $model->update($uid, array('member_status' => $newStatus));

        // 刷新缓存
        $model->deleteMemberStatusCache($uid);

        return $updateRs;
    }

    public function getAllUser($userId, $username, $memberType, $page = 1, $perpage = 100){
        $model = new UserModel();
        
        $where = array();

        if($username !== null){
            $where = array('username LIKE ?' => "%{$username}%");
        }
        if($memberType !== null){
            $where['member_level'] = $memberType;
        }
        if ($userId > 0) {
            $where['id'] = $userId;
        }
        $list = $model->getListEx(
            $where,
            array(),
            'id,username,nickname,mobile,email,member_level,register_time,member_status',
            'id DESC',
            $page,
            $perpage
        );
        
        return array('total' => $list['total'], 'list' => $list['items']);
    }

    public function deleteUser($id){
        $model = new UserModel();
        return $model->delete($id);
    }

    // 会员注册统计
    public function getNewMemberFlow($startTime, $endTime){
        if(empty($startTime)){
            $startTime = date("Y-m-d 00:00:00", strtotime("-30 days"));
        }
        if(empty($endTime)){
            $endTime = date("Y-m-d 23:59:59");
        }
        try {
            $model = new UserModel();
            $table = TimeUtil::createDefaultTimeLine($startTime, $endTime, 'day', array('total' => 0, 'monthAgo' => 0));
            $dataList = $model->getNewMemberFlow($startTime, $endTime);
            foreach ($dataList as $data){
                $time = $data['time'];
                $table[$time]['total'] = $data['total'];
            }
            // 同比上个月
            $monthStart = date("Y-m-d 00:00:00", strtotime("{$startTime} - 30 days"));
            $monthEnd = date("Y-m-d 23:59:59", strtotime("{$endTime} - 30 days"));
            $monthAgoList = $model->getNewMemberFlow($monthStart, $monthEnd);
            foreach ($monthAgoList as $monthAgoData){
                $time = date("Y-m-d", strtotime("{$monthAgoData['time']} + 30 days"));
                $table[$time]['monthAgo'] = $monthAgoData['total'];
            }
        }catch (PDOException $e){
            throw new BadRequestException(\PhalApi\T("there is a problem with the time format"), 8);
        }
        return $table;
    }

    /**
     * @param array $uidArr uid列表
     * @return array $uidMap id与username对应的Map
     */
    public function getUserNameByUid($uidArr){
        $uidMap = array();
        $model = new Member();
        $list = $model->getListEx(array('id' => $uidArr), array(), 'id, username');
        if(!empty($list['items'])){
            foreach ($list['items'] as $item){
                $id = $item['id'];
                $uidMap[$id] = $item['username'];
            }
        }
        return $uidMap;
    }

}
