<?php

namespace Business\User;

use DAO\MbUserTokenModel;
use DAO\MemberModel;
use DAO\SaleMemberModel;
use Error\CodeConfigModel;
use Error\ErrorModel;
use Our\ApiConst;
use Our\Common;
use Our\CommonExtension;


/**
 * 用户登录业务
 */
class MemberServiceModel extends \Business\AbstractModel
{

    private $memberDao;
    private $memberDb0Redis;
    private $sessionDb0Redis;
    public function init()
    {
        $this->memberDao = MemberModel::getInstance();
        $this->memberDb0Redis=\Redis\Db0\MemberRedisModel::getInstance();
        $this->sessionDb0Redis= \Redis\Db0\SessionRedisModel::getInstance();
    }

    /**
     * 登录业务
     *
     * @param array $params
     * @return
     */
    public function login()
    {
        $userM = MemberModel::getInstance();
        //系统封装好的方法
        $one = $userM->find(1);
        //系统自带走从库方法
        return $one;
        $user = $userM->query();
        //系统原生走主库
        $user = $userM->update("UPDATE Member SET member_name='abc' WHERE member_id=1");
        return $user;
    }
    public function saveMember($member){
        $this->addOrUpdateMbUserToken($member);
        foreach($member as $key =>$value){
            if(!$value){
                $member[$key]=ApiConst::zero;
            }
        }
        $member['sendTime']=TIMESTAMP;
        $this->memberDb0Redis->tableHMSet(trim($member['member_id']),$member,ApiConst::tenDaySecond);
    }


    public function clearKey($key){
        $this->sessionDb0Redis->delSessionKey($key);

        //  $this->memberDb0Redis->tableDel($key);
    }
    public function checkUserNamePassWord($mobile, $password)
    {
        if (empty($mobile)) {
            ErrorModel::throwException(CodeConfigModel::emptyMobileForLogin);
        }
        if (empty($password)) {
            ErrorModel::throwException(CodeConfigModel::emptyPassword);
        }
        if (!Common::checkMobilePhone($mobile)) {
            ErrorModel::throwException(CodeConfigModel::wrongTelnumber);
        }
        return true;

    }

    public function getOneByMobileAndPassword($mobile, $password)
    {
        $password = md5($password);
        $member= $this->memberDao->getOneByMobileAndPassword($mobile, $password);
        return $member ? $member : false;
    }

    /**
     * 登录业务
     *
     * @var \Business\User\LoginV2Model
     */
    private static $_instance = null;

    /**
     * 单例模式获取类实例
     *
     * @return \Business\User\LoginV2Model
     */
    public static function getInstance()
    {
        if (!(self::$_instance instanceof self)) {
            self::$_instance = new self();
        }

        return self::$_instance;
    }

    public function addOrUpdateMbUserToken($data)
    {
        $mbUserToken = MbUserTokenModel::getInstance();
        $inserData = [
            'member_id' => $data['member_id'],
            'member_name' => $data['member_name'],
            'token' => $data['key'],
            'login_time' => time(),
            'client_type' => Common::getDriverType(true),
        ];
        return $mbUserToken->insertOrUpdate($inserData);
    }

    public function findMbUserTokenByMemberId($memberId)
    {
        if ($memberId != (int)$memberId) {
            return false;
        }
        $mbUserTokenModel = MbUserTokenModel::getInstance();
        return $mbUserTokenModel->findByMemberId($memberId);
    }



    public function getMemberInfo($memberId)
    {
        $memberDao=\DAO\MemberModel::getInstance(\Our\DbNameConst::masterDBConnectName);
        $member=$memberDao->getInfo($memberId);
        $returnMember=array(
            'memberId'=>$member['memberId'],
            'memberName'=>$member['memberName'],
            'memberTrueName'=>$member['memberTrueName'],
            'memberAvatar'=>$member['memberAvatarUrl'],
            'memberSex'=>$member['memberSex'],
            'memberBirthday'=>$member['memberBirthday'],
            'memberMobile'=>$member['memberMobile'],
            'memberMobileBind'=>$member['memberMobileBind'],
            'sellerId'=>$member['sellerId'],
            'diliverymanId'=>$member['diliverymanId'],
        );

        $returnMember['isWeiboBind'] = \Our\ApiConst::zero;
        $returnMember['isQqBind'] = \Our\ApiConst::zero;
        $returnMember['isWeiboBind'] = \Our\ApiConst::zero;
        $memberMappingDao = \DAO\MemberMappingModel::getInstance(\Our\DbNameConst::masterDBConnectName);
        $memberMappingList = $memberMappingDao->getAvailableMemberMappingList($memberId);
        foreach($memberMappingList as $memberMapping){
            if($memberMapping['user_type']== \Our\ApiConst::userFromWeibo){
                $returnMember['isWeiboBind'] = \Our\ApiConst::one;
            }else if($memberMapping['user_type'] == \Our\ApiConst::userFromQQ){
                $returnMember['isQqBind'] = \Our\ApiConst::one;
            }else if($memberMapping['user_type'] == \Our\ApiConst::wechatUserType){
                $returnMember['isWxBind'] = \Our\ApiConst::one;
            }else if($memberMapping['user_type'] == \Our\ApiConst::userFromWx){
                $returnMember['isWxBind'] = \Our\ApiConst::one;
            }
        }
        return $returnMember;
    }

    public function saveMemberInfo($where,$memberId){
        $memberDao=\DAO\MemberModel::getInstance(\Our\DbNameConst::masterDBConnectName);
        $data = $memberDao->getValidMember($where);

        $result = $memberDao->saveInfo($data,$memberId);
        return $result;
    }

    public function getWxUserToken($memberId){
        $memberDao = \DAO\MemberModel::getInstance();
        $userToken = $memberDao->getWxUserToken($memberId);
        return $userToken;
    }

    public function saveWxUserToken($key,$memberId){
        $memberDao = \DAO\MemberModel::getInstance();
        $memberDao->saveWxUserToken($key,$memberId);
    }

    /**
     * 保存会员头像
     * @param $where 参数
     * @param $memberId 对应会员
     * @return mixed 返回头像地址
     * @throws \Exception
     * @throws \OSS\Core\OssException
     */
    public function saveMemberAvatar($where,$memberId){
        $memberAvatar = $where['memberAvatar'];
        if(!($memberAvatar)){
            \Error\ErrorModel::throwException(\Error\CodeConfigModel::emtpyMemberAvatar);
        }
        $requestDriver = \Our\Common::getDriverType();
        if ($requestDriver == \Our\ApiConst::wxType) {
            $where['type'] = \Our\ApiConst::memberAvatarType;
            $returnAvatar = \Our\ImageUtil::saveWxImage($where);
            if(!$returnAvatar){
                \Error\ErrorModel::throwException(\Error\CodeConfigModel::uploadWxMemberAvatarFailed);
            }
            $memberAvatarName = $returnAvatar['fileName'];
        }else{
            $memberAvatarName = \Our\ImageConst::memberAvatarPrefix.$memberId;
            $result = \Our\ImageUtil::uploadBase64Image($memberAvatar,\Our\ImageConst::memberAvatar,$memberAvatarName);
            if(!$result){
                \Error\ErrorModel::throwException(\Error\CodeConfigModel::uploadMemberAvatarFailed);
            }
        }
        $data['member_avatar'] = $memberAvatarName;
        $memberDao=\DAO\MemberModel::getInstance(\Our\DbNameConst::masterDBConnectName);
        $result = $memberDao->saveInfo($data,$memberId);
        return $result;
    }


    /**
     * 退出登录
     */
    public function logOut($key){
        $sess=\Yaf\Session::getInstance();
        $sess->del('member_id');
        $this->clearKey($key);
        return true;
    }
    /**
     * 退出登录
     */
    public function logOutTest($key){

        $this->sessionDb0Redis->delSessionKeyTest($key);
        return true;
    }

    /**
     * 注册时验证手机号码
     * @param $where
     * @return bool
     * @throws \Exception
     */
    private function validRegisterSmsCode($where){
        //验证手机号码
        if($where['code']=='666666'&&(APP_ENV=='test'||APP_ENV=='develop')){
            return true;
        }
        $validData['key'] = $where['key'];
        $validData['messageType'] = ApiConst::messageTypeRegister;
        $validData['mobile'] = $where['mobile'];
        $validData['code'] = $where['code'];
        $shortMessageDao  = \DAO\ShortMessageModel::getInstance();
        if(!$shortMessageDao->validCode($validData)){
            \Error\ErrorModel::throwException(\Error\CodeConfigModel::wrongSmsCode);
        }
        return true;
    }

    /**
     * 注册保存用户信息
     * @param $where
     * @return mixed 保存成功,返回memberId
     * @throws \Exception
     */
    private function saveRegisterMemberInfo($where){
        $memberDao = \DAO\MemberModel::getInstance(\Our\DbNameConst::masterDBConnectName);

        //构造需要保存的会员信息
        $member['member_name'] = \Our\CommonExtension::createNewMemberName();
        $member['member_mobile'] = $where['mobile'];
        $member['member_mobile_bind'] = \Our\ApiConst::one;
        $member['member_passwd'] = md5($where['password']);
        $member['member_time'] = TIMESTAMP;
        $result = $memberDao->addInfo($member);
        return $result;
    }

    private function saveWxInfoMemberInfo($where){
        $memberDao = \DAO\MemberModel::getInstance(\Our\DbNameConst::masterDBConnectName);

        //构造需要保存的会员信息
        $member['member_name'] = \Our\CommonExtension::createNewMemberName();
        $result = $memberDao->addInfo($member);
        return $result;
    }

    /**
     * 保存店铺会员
     * @param $memberId
     * @return bool
     */
    private function saveStoreMembers($memberId){
        $sess=\Yaf\Session::getInstance();
        $scan_store_ids = $sess->get('scan_store_ids');//扫码带入的店铺ID
        if($scan_store_ids){
            $storeMembers = array();
            foreach($scan_store_ids as $storeId){
                $storeMember = array();
                $storeMember['store_id'] = $storeId;
                $storeMember['member_id'] = $memberId;
                $storeMember['fav_from'] = \Our\ApiConst::scanFavor;
                $storeMembers[] = $storeMember;
            }
            /*$storeMemberDao = \DAO\StoreMemberModel::getInstance(\Our\DbNameConst::masterDBConnectName);
            $result = $storeMemberDao->addBatch($storeMember);*/
            $favoritesStoreDao = \DAO\FavoritesStoreModel::getInstance();
            $result = $favoritesStoreDao->insertAll($storeMembers);
            if(!$result){
                \Our\Log::getInstance()->write(json_encode($storeMembers).'扫码数据写入失败');
                return false;
            }
        }
        $scan_sale_ids = $sess->get('scan_sale_ids');
        if($scan_sale_ids){
            $saleIds = array_keys($scan_sale_ids);
            $saleList = \DAO\SaleModel::getInstance()->getList(array('sale_id'=>array('in',$saleIds)),'sale_id,sale_act_id,member_id');
            $saleMembers = array();
            foreach($saleList as $sale){
                $saleMember = array();
                $saleMember['member_id'] = $memberId;
                $saleMember['store_id'] = $scan_sale_ids[$sale['sale_id']];
                $saleMember['sale_id'] = $sale['member_id'];
                $saleMember['sale_act_id'] = $sale['sale_act_id'];
                $saleMembers[]=$saleMember;
            }
            $resultSaleMember = \DAO\SaleMemberModel::getInstance()->insertAllOrUpdate($saleMembers);
            return $resultSaleMember;
        }
        return true;
    }

    /**
     * 保存注册会员设置信息
     * @param $where
     * @param $memberId
     * @return bool
     */
    private function saveRegisterDeviceInfo($where,$memberId){
        if($where['deviceType']){
            $memberDeviceInfo = array(
                'member_id' => $memberId,
                'device_type' => $where['deviceType']
            );
            if(isset($where['deviceUniqueCode'])){
                $memberDeviceInfo['device_unique_code']= $where['deviceUniqueCode'];
            }
            $memberDeviceInfoDao = \DAO\MemberDeviceInfoModel::getInstance(\Our\DbNameConst::masterDBConnectName);
            $memberDeviceResult = $memberDeviceInfoDao->add($memberDeviceInfo);
            return $memberDeviceResult;
        }
        return false;
    }

    /**
     * @param $where
     * @param $memberId
     * @return bool
     * @throws \Exception
     * @throws \OSS\Core\OssException
     */
    public function saveRegisterMapping($where,$memberId,$key=null){
        $memberDao = \DAO\MemberModel::getInstance(\Our\DbNameConst::masterDBConnectName);
        $memberDao->validMemberNameAndAvatar($where);
        $result = $this->saveMappingInfo($where,$memberId);
        if($result){
            $redisKey = isset($where['key'])?$where['key']:$key;
            if($redisKey){
                $this->memberDb0Redis->tableDel(\Our\NameConst::authInfoPrefix.$redisKey);
            }
            /*$memberAvatarFileName= \Our\ImageConst::memberAvatarPrefix.$memberId.\Our\NameConst::dot.\Our\NameConst::jpg;
            \Our\ImageUtil::uploadImageWithUrl($where['userInfo']['avatar'],\Our\ImageConst::memeberAvatar,$memberAvatarFileName);
            $member['member_avatar'] = $memberAvatarFileName;*/

            $member['member_avatar'] = $where['avatar'];
            $member['member_name'] = $where['nickname'];

            if($where['gender']){
                if($where['gender'] == \Our\ApiConst::man){
                    $member['member_sex'] = \Our\ApiConst::one;
                }else if($where['gender'] == \Our\ApiConst::woman){
                    $member['member_sex'] = \Our\ApiConst::zero;
                }
            }
            $result = $memberDao->saveInfo($member,$memberId);
            return $result ;

        }
        return false;


    }

    public function saveMappingInfo($where,$memberId){
        $memberMappingDao = \DAO\MemberMappingModel::getInstance(\Our\DbNameConst::masterDBConnectName);
        $memberMappingDao->validMemberMapping($where,$memberId);

        $mapping['user_type'] = $where['userType'];
        $mapping['openid'] = $where['openid'];
        $mapping['member_id'] = $memberId;
        $result = $memberMappingDao->insert($mapping);
        if(!$result){
            \Error\ErrorModel::throwException(\Error\CodeConfigModel::saveMemberMapppingFailed);
        }
        return $result;
    }

    /**
     * 登录时保存第三方信息
     * @param $where
     * @param $member
     */
    public function saveLoginMapping($member,$data,$authInfo=null){
        $memberDao = \DAO\MemberModel::getInstance();
        $memberMappingDao = \DAO\MemberMappingModel::getInstance(\Our\DbNameConst::masterDBConnectName);

        $redisKey =\Our\NameConst::authInfoPrefix.$data['key'];
        $where = $this->memberDb0Redis->find($redisKey);

        //没有第三方信息需要保存
        if(!$where){
            if($authInfo){
                $where = $authInfo;
            }else{
                return array('status'=>true) ;
            }
        }

        $memberId = $member['member_id'];

        $memberMappingDao->validMemberMapping($where,$memberId);


        $mapping['user_type'] = $where['userType'];
        $mapping['openid'] = $where['openid'];
        $mapping['member_id'] = $memberId;
        $result = $memberMappingDao->insert($mapping);
        if($result){

            $this->memberDb0Redis->tableDel($redisKey);
            $updateMember = array();
            if(!$member['member_avatar']){
                /*$memberAvatarFileName= \Our\ImageConst::memberAvatarPrefix.$memberId.\Our\NameConst::dot.\Our\NameConst::jpg;
                $memberAvatarUrl = \Our\ImageUtil::uploadImageWithUrl($where['userInfo']['avatar'],\Our\ImageConst::memeberAvatar,$memberAvatarFileName);
                $updateMember['member_avatar'] = $memberAvatarFileName;*/
                $updateMember['member_avatar'] = $where['avatar'];

            }
            if(empty($member['member_name'])||strpos($member['member_name'],\Our\DescribeConst::memberNamePrefix)===0){
                $updateMember['member_name'] = $where['nickname'];
            }
            if($updateMember){
                $result = $memberDao->updateInfo($updateMember,array('member_id'=>$memberId));
                if($result){
                    /*if($memberAvatarUrl){
                        $updateMember['memberAvatarUrl'] = $memberAvatarUrl;
                    }*/

                    if($updateMember['member_avatar']){
                        $updateMember['memberAvatarUrl'] = $updateMember['member_avatar'];
                    }
                    return array('status'=>true,'member'=>$updateMember);
                }
            }
            return array('status'=>$result) ;
        }
        return array('status'=>false);

    }

    public function saveOtherMemberInfo($where,$memberId,$saveDeviceFlag=false){
        //第二步保存扫码会员信息
        $result = $this->saveStoreMembers($memberId);
        if(!$result){
            \Error\ErrorModel::throwException(\Error\CodeConfigModel::saveStoreMemberFailed);
        }

        //第三步保存用户设备识别信息
        if(!$saveDeviceFlag){
            $memberDeviceResult = $this->saveRegisterDeviceInfo($where,$memberId);
            if(!$memberDeviceResult){
                \Error\ErrorModel::throwException(\Error\CodeConfigModel::saveMemberDeviceInfoFailed);
            }
        }


        $authInfo = $this->memberDb0Redis->find(\Our\NameConst::authInfoPrefix.$where['key']);
        if(!$authInfo&&$where['userType'] == \Our\ApiConst::wechatUserType){
            $authInfo['nickname'] = $where['nickname'];
            $authInfo['openid'] = $this->getUnionId($where['encryptedData'],$where['iv'],$where['session_key']);
            $authInfo['avatar'] = $where['avatar'];
            $authInfo['userType'] = $where['userType'];
            $authInfo['gender'] = $where['gender'];
        }
        //第四步保存第三方绑定关系(保存会员信息)
        if($authInfo['userType']){
            $mappingResult = $this->saveRegisterMapping($authInfo,$memberId,$where['key']);
            if(!$mappingResult){
                \Error\ErrorModel::throwException(\Error\CodeConfigModel::addMemberMappingError);
            }
        }
    }



    /**
     * 保存注册信息
     * @param $where
     * @param $memberId
     */
    public function saveRegisterInfo($where){

        $memberDao = \DAO\MemberModel::getInstance();
        $memberDao->setDb(\Our\DbNameConst::masterDBConnectName);
        $db = $memberDao->db;

        //验证表单传来数据
        $memberDao->validRegisterInfo($where);

        //判断手机号码是否已经被使用
        $memberDao->checkRegisterMobile($where);

        //验证短信验证码是否有效
        $this->validRegisterSmsCode($where);

        //开始事务
        $db->doTransaction();

        $saveDeviceFlag=true;
        $memberId = $this->checkMemberMappingExist($where);//检查登录的用户是否授权从其他第三方登录
         if(!$memberId){
             $saveDeviceFlag = false;
             $memberId = $this->saveRegisterMemberInfo($where);
        }
        //保存用户信息
        if(!$memberId){
            $db->doRollback();
            \Error\ErrorModel::throwException(\Error\CodeConfigModel::addMemberInfoFailed);
        }

        //保存用户其他相关信息
        $this->saveOtherMemberInfo($where,$memberId,$saveDeviceFlag);

        $db->doCommit();

        if($where['code']=='666666'&&(APP_ENV=='test'||APP_ENV=='develop')){

            $shortMessageDao = \DAO\ShortMessageModel::getInstance();
            $shortMessageDao->delCodeRedis($where['key'],$where['mobile'],\Our\ApiConst::messageTypeRegister);
        }
        $member = $memberDao->getMemberById($memberId);
        return $member;
        //return true;

    }

    /**
     * 注册时检查当前用户是否第三方授权,以及三方授权是否已经存在对应用户
     */
    public function checkMemberMappingExist($where){
        $authInfo = $this->memberDb0Redis->find(\Our\NameConst::authInfoPrefix.$where['key']);
        if(!$authInfo){
            return false;
        }
        $memberMappingDao = \DAO\MemberMappingModel::getInstance(\Our\DbNameConst::masterDBConnectName);
        $memberMapping = $memberMappingDao->find(array('openid'=>$authInfo['openid']));
        if(!$memberMapping){
            return false;
        }
        $memberDao = \DAO\MemberModel::getInstance(\Our\DbNameConst::masterDBConnectName);
        $existMember = $memberDao->getInfo($memberMapping['member_id']);
        if(!$existMember){
            $memberMappingDao->del(array('id'=>$memberMapping['id']));
            return false;
        }
        if($existMember['memberMobile']&&$existMember['memberMobileBind']){
            \Error\ErrorModel::throwException(\Error\CodeConfigModel::registerMemberInfoFailed);
        }
        $member['member_mobile'] = $where['mobile'];
        $member['member_mobile_bind'] = \Our\ApiConst::one;
        $member['member_passwd'] = md5($where['password']);
        $updateMemberResult = $memberDao->saveInfo($member,$memberMapping['member_id']);
        if(!$updateMemberResult){
            \Error\ErrorModel::throwException(\Error\CodeConfigModel::authMemberExistMobile);
        }
        return $memberMapping['member_id'];
    }

    public function cancelBinding($data,$memberId){
        $memberMappingDao = \DAO\MemberMappingModel::getInstance(\Our\DbNameConst::masterDBConnectName);
        $memberMappingDao->validCancelMapping($data,$memberId);
        $where['member_id'] = $memberId;
        $where['user_type'] = ($data['userType']==\Our\ApiConst::userFromWx||$data['userType']==\Our\ApiConst::wechatUserType)?array('in',array(\Our\ApiConst::userFromWx,\Our\ApiConst::wechatUserType)):$data['userType'];
        $result = $memberMappingDao->del($where);
        if(!$result){
            \Error\ErrorModel::throwException(\Error\CodeConfigModel::cancelBindingUserFailed);
        }
        return true;
    }

    /**
     * 登录后的第三方平台绑定
     * @param $where 前台参数
     * @param $memberId 对应用户
     * @return array
     */
    public function bindThirdPlatform($where,$memberId){
        $member = $this->getMemberInfo($memberId);
        $member = \Our\Common::convertHump($member);
        $authInfo['nickname'] = $where['nickname'];
        $authInfo['openid'] = $where['openid'];
        $authInfo['avatar'] = $where['avatar'];
        $authInfo['userType'] = $where['userType'];
        $authInfo['gender'] = $where['gender'];
        $result = $this->saveLoginMapping($member,$where,$authInfo);
        if($result['status']){
            if(isset($result['member'])&&$result['member']){
                $member = array_merge($member,$result['member']);
                $this->saveMember($member);
            }
            return true;
        }
        return false;
    }

    public function checkMobile($data){

        $memberDao = \DAO\MemberModel::getInstance();
        $result = $memberDao->checkLoginMobile($data);
        if($result){
            $data['messageType'] = \Our\ApiConst::messageTypeFindPassword;
            $shortMessageDao = \DAO\ShortMessageModel::getInstance();
            $smsReturn = $shortMessageDao->sendSms($data);
            if($smsReturn['status']){
                return true;
            }
        }
        return false;
    }

    public function checkVerifyCode($data){
        $memberDao = \DAO\MemberModel::getInstance();
        $result = $memberDao->checkLoginMobile($data);
        if($result){
            $data['messageType'] = \Our\ApiConst::messageTypeFindPassword;
            $shortMessageDao = \DAO\ShortMessageModel::getInstance();
            $smsReturn = $shortMessageDao->validCode($data);
            if($smsReturn){

                if(!(APP_ENV=='test'||APP_ENV=='develop')){
                    $shortMessageDao = \DAO\ShortMessageModel::getInstance();
                    $shortMessageDao->delCodeRedis($data['key'],$data['mobile'],\Our\ApiConst::messageTypeFindPassword);
                }

                $sess=\Yaf\Session::getInstance();
                $sess['findPasswordMobile'] = $data['mobile'];
                return true;
            }
        }
        return false;
    }

    public function setPassword($data){
        $sess=\Yaf\Session::getInstance();
        $passwordMobile = $sess->get('findPasswordMobile');
        if(!$passwordMobile){
            \Error\ErrorModel::throwException(\Error\CodeConfigModel::findPasswordLimit);
        }
        $memberDao = \DAO\MemberModel::getInstance();
        $memberDao->checkPassword($data);
        $result = $memberDao->updateInfo(array('member_passwd'=>md5($data['password'])),array('member_mobile'=>$passwordMobile));
        if($result===false){
            return false;
        }
        $sess->del('findPasswordMobile');
        return true;
    }


    public function changeMobile($data,$memberId){
        $memberDao = \DAO\MemberModel::getInstance();
        $memberDao->checkChangedInfo($data);
        //验证短信验证码
        $shortMessageDao = \DAO\ShortMessageModel::getInstance();

        $data['messageType'] = \Our\ApiConst::messageTypeValidNewMobile;
        $shortMessageDao->validCode($data);

        $result = $memberDao->updateInfo(array('member_passwd'=>md5($data['password']),'member_mobile'=>$data['mobile'],'member_mobile_bind'=>\Our\ApiConst::one),array('member_id'=>$memberId));
        if(!$result){
            \Error\ErrorModel::throwException(\Error\CodeConfigModel::changeMobileFailed);
        }
        $this->memberDb0Redis->tableHMSet($memberId,array('member_mobile'=>$data['mobile']),ApiConst::tenDaySecond);
        $shortMessageDao = \DAO\ShortMessageModel::getInstance();
        $shortMessageDao->delCodeRedis($data['key'],$data['mobile'],\Our\ApiConst::messageTypeValidNewMobile);
        return true;

    }

    /**
     * 修改密码
     * @param $where
     * @param $memberId
     * @return bool
     */
    public function changePassword($where,$memberId){
        $memberDao = \DAO\MemberModel::getInstance();
        $memberDao->checkOldPassword($where,$memberId);
        $result = $memberDao->updateInfo(array('member_passwd'=>md5($where['password'])),array('member_id'=>$memberId));
        if($result){
            $this->logOut($where['key']);
            return true;
        }
        return false;
    }

    public function checkSaveWechatInfo($where){
        $memberDao = \DAO\MemberModel::getInstance(\Our\DbNameConst::masterDBConnectName);
        $memberMappingDao = \DAO\MemberMappingModel::getInstance(\Our\DbNameConst::masterDBConnectName);
        if($where['userType'] == \Our\ApiConst::wechatUserType){
            $condition['openid'] = $this->getUnionId($where['encryptedData'],$where['iv'],$where['session_key']);
        }else{
            $condition['openid'] = $where['openid'];
        }
        if($where['userType'] == \Our\ApiConst::wechatUserType||$where['userType'] == \Our\ApiConst::userFromWx){
            $condition['user_type'] = array('in',array(\Our\ApiConst::wechatUserType,\Our\ApiConst::userFromWx));
        }else{
            $condition['user_type'] = $where['userType'];
        }
        $memberMappings = $memberMappingDao->getList($condition,'member_id');
        //$memberMapping = \Our\RedisHelper::cachedFunction(\Redis\Db0\MemberMappingRedisModel::getInstance(),array(&$memberMappingDao, 'find'),array($condition,'member_id'),\Our\ApiConst::tenDaySecond);
        if($memberMappings){
            $memberIds = array_column($memberMappings,'member_id');
            $member = $memberDao->getMemberForLogin($memberIds);
            if($where['userType'] == \Our\ApiConst::wechatUserType){
                $this->checkMemberMappingExistLogin($member['member_id'],$condition['openid'] ,$where['userType']);
            }
            if($where['userType'] == \Our\ApiConst::userFromWx){//如果当前openid存在对应的小程序码但是对应用户并没有绑定手机号码时 ,也需要绑定手机号码
                if($member['member_mobile']&&$member['member_mobile_bind']){
                    $this->checkMemberMappingExistLogin($member['member_id'],$condition['openid'] ,$where['userType']);
                }else{
                    return false;
                }
            }
            return $member;
        }
        return false;
    }

    /**
     * 小程序登录时检测当前openid(实际上存储的是unionid)是否存在对应的对应的手机账号,存在则直接登录,并且检查是否有对应记录,有直接写入,没有则不写入
     * @param $memberId
     * @param $openid
     * @param $userType
     * @return bool
     * @throws \Error\OurExceptionModel
     * @throws \Exception
     */
    public function checkMemberMappingExistLogin($memberId,$openid,$userType){
        $memberMappingDao = \DAO\MemberMappingModel::getInstance(\Our\DbNameConst::masterDBConnectName);
        $condition['member_id'] = $memberId;
        $condition['openid'] = $openid;
        $condition['user_type'] = $userType;
        $userMapping = $memberMappingDao->find($condition);
        if($userMapping){
            return true;
        }
        $condition['gmt_create'] = TIMESTAMP;
        $result = $memberMappingDao->insert($condition);
        if(!$result){
            \Error\ErrorModel::throwException(\Error\CodeConfigModel::saveUserMappingFailed);
        }
        return true;
    }

    public function getUnionId($encryptedData,$vi,$sessionKey){
        $wxInfo = \Our\ArrayConst::wechatInfo;
        $pc =\WxAes\WXBizDataCrypt::getInstance($wxInfo['appid'], $sessionKey);
        $errCode = $pc->decryptData($encryptedData, $vi, $data );
        if($errCode != \Our\ApiConst::zero){
            \Error\ErrorModel::throwException(\Error\CodeConfigModel::getUnionidFailed);
        }
        return $data['unionId'];
    }

    public function loginWithWechatInfo($where,$authInfo){
        $memberDao = \DAO\MemberModel::getInstance(\Our\DbNameConst::masterDBConnectName);
        $memberDao->setDb(\Our\DbNameConst::masterDBConnectName);
        $db = $memberDao->db;
        //$where['openid'] = $authInfo['openid'];
        $where['session_key'] = $authInfo['session_key'];
        $this->checkWechatInfo($where,$authInfo);

        $returnMember = $this->checkSaveWechatInfo($where);
        if($returnMember){
            return $returnMember;
        }
        $db->doTransaction();
        $memberId = $this->saveWxInfoMemberInfo($where);

        if(!$memberId){
            $db->doRollback();
            \Error\ErrorModel::throwException(\Error\CodeConfigModel::addMemberInfoFailed);
        }

        //保存用户其他相关信息
        $this->saveOtherMemberInfo($where,$memberId);

        $db->doCommit();
        $member = $memberDao->getMemberById($memberId);
        return $member;

    }

    public function loginWithThirdPlatformInfo($where){
        $this->checkAuthInfo($where);
        $member = $this->checkSaveWechatInfo($where);
        if(!$member){
            $sess=\Yaf\Session::getInstance();
            $authInfo['nickname'] = $where['nickname'];
            $authInfo['openid'] = $where['openid'];
            $authInfo['avatar'] = $where['avatar'];
            $authInfo['userType'] = $where['userType'];
            $authInfo['gender'] = $where['gender'];
            $this->memberDb0Redis->update(\Our\NameConst::authInfoPrefix.$where['key'],$authInfo,\Our\ApiConst::oneHour);
        }
        return $member;
    }



    public function checkWechatInfo($where,$authInfo){
        if(!$authInfo['session_key']){
            \Error\ErrorModel::throwException(\Error\CodeConfigModel::emptyWxUserInfoAuth);
        }
        /*if(!$where['openid']){
            \Error\ErrorModel::throwException(\Error\CodeConfigModel::emptyWxOpenid);
        }
        if($authInfo['openid']!=$where['openid']){
            \Error\ErrorModel::throwException(\Error\CodeConfigModel::wrongWxOpenid);
        }*/
        if(!($where['encryptedData']&&$where['iv'])){
            \Error\ErrorModel::throwException(\Error\CodeConfigModel::emptyEncryptedDataAndVi);
        }
        if(!($where['nickname']&&$where['avatar'])){
            \Error\ErrorModel::throwException(\Error\CodeConfigModel::emptyWxInfo);
        }

    }

    public function checkAuthInfo($where){
        if(!$where['openid']){
            \Error\ErrorModel::throwException(\Error\CodeConfigModel::emptyWxUserInfoAuth);
        }
        if(!$where['userType']&&in_array($where['userType'],array_keys(\Our\ArrayConst::userType))){
            \Error\ErrorModel::throwException(\Error\CodeConfigModel::emptyOrWrongAuthUserType);
        }
        if(!($where['nickname']&&$where['avatar'])){
            \Error\ErrorModel::throwException(\Error\CodeConfigModel::emptyWxInfo);
        }
    }

    /**
     * 微信登录用户绑定手机号码
     * @param $where
     * @param $memberId
     */
    public function bindMobileForWx($data,$memberId){
        $memberDao = \DAO\MemberModel::getInstance();
        $memberDao->checkWxBindMobile($data);
        //验证短信验证码
        $shortMessageDao = \DAO\ShortMessageModel::getInstance();

        $data['messageType'] = \Our\ApiConst::messageTypeWxLietBindMobile;
        $shortMessageDao->validCode($data);
        $updateMember = array('member_passwd'=>md5($data['password']),'member_mobile'=>$data['mobile'],'member_mobile_bind'=>\Our\ApiConst::one);
        $result = $memberDao->updateInfo($updateMember,array('member_id'=>$memberId));
        if(!$result){
            \Error\ErrorModel::throwException(\Error\CodeConfigModel::wxMemberBindMobileFailed);
        }
        unset($updateMember['member_passwd']);
        $this->memberDb0Redis->tableHMSet($memberId,$updateMember,ApiConst::tenDaySecond);
        $shortMessageDao = \DAO\ShortMessageModel::getInstance();
        $shortMessageDao->delCodeRedis($data['key'],$data['mobile'],\Our\ApiConst::messageTypeWxLietBindMobile);
        return true;
    }


    /**
     * 绑定手机号码
     * @param $where
     * @param $memberId
     */
    public function bindMobile($data,$memberId){
        $sess=\Yaf\Session::getInstance();
        $loginUserType = $sess->get('user_type');
        $dbName = \Our\DbNameConst::masterDBConnectName;
        $memberDao = \DAO\MemberModel::getInstance($dbName);
        $memberDao->setDb($dbName);
        $memberMappingDao = \DAO\MemberMappingModel::getInstance($dbName);
        $memberDao->validPassword($data);
        $memberMemberMappingDao = \DAO\Member\MemberMemberMappingModel::getInstance();
        $mobileMember = $memberMemberMappingDao->checkBindMobileCommon($data,$memberId,$loginUserType);

        //验证短信验证码
        $shortMessageDao = \DAO\ShortMessageModel::getInstance();

        $data['messageType'] = \Our\ApiConst::messageTypeWxLietBindMobile;
        $shortMessageDao->validCode($data);
        if($mobileMember){
            $memberDao->db->doTransaction();
            $updateMobileMember['member_passwd'] = md5($data['password']);
            $resultMember = $memberDao->updateInfo($updateMobileMember,array('member_id'=>$mobileMember['member_id']));
            if($resultMember===false){
                $memberDao->db->doRollback();
                \Error\ErrorModel::throwException(\Error\CodeConfigModel::updateMobileMembmerFailed);
            }
            $currentMemberMapping = $memberMappingDao->find(array('member_id'=>$memberId,'user_type'=>$loginUserType));
            $newMapping['member_id'] = $mobileMember['member_id'];
            $newMapping['openid'] = $currentMemberMapping['openid'];
            $newMapping['user_type'] = $currentMemberMapping['user_type'];
            $resultMemberMapping = $memberMappingDao->insert($newMapping);
            if(!$resultMemberMapping){
                $memberDao->db->doRollback();
                \Error\ErrorModel::throwException(\Error\CodeConfigModel::updateMobileMembmerMappingFailed);
            }
            $memberDao->db->doCommit();
            $sess['member_id'] = $mobileMember['member_id'];
        }else{
            $updateMember = array('member_passwd'=>md5($data['password']),'member_mobile'=>$data['mobile'],'member_mobile_bind'=>\Our\ApiConst::one);
            $result = $memberDao->updateInfo($updateMember,array('member_id'=>$memberId));
            if(!$result){
                \Error\ErrorModel::throwException(\Error\CodeConfigModel::wxMemberBindMobileFailed);
            }
            unset($updateMember['member_passwd']);
            $this->memberDb0Redis->tableHMSet($memberId,$updateMember,ApiConst::tenDaySecond);
        }
        $shortMessageDao = \DAO\ShortMessageModel::getInstance();
        $shortMessageDao->delCodeRedis($data['key'],$data['mobile'],\Our\ApiConst::messageTypeWxLietBindMobile);
        return true;
    }



}
