<?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;
use Our\DbNameConst;
use Our\NameConst;


/**
 * 用户登录业务
 */
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,$client='member'){


        foreach($member as $key =>$value){
            if(!$value){
                $member[$key]=ApiConst::zero;
            }
        }
        if($client=='member'){
            $this->addOrUpdateMbUserToken($member);
            $member['sendTime']=TIMESTAMP;
            $this->memberDb0Redis->tableHMSet(trim($member['member_id']),$member,ApiConst::tenDaySecond);
            $this->memberDb0Redis->tableHDel(trim($member['member_id']),'unread_message_count');
        }
        if($client=='seller'){
            $storeRedisDb0=\Redis\Db0\StoreRedisModel::getInstance();
            $storeFd=$storeRedisDb0->tableHGet(trim($member['store_id']),'fd');
            if(!empty($storeFd)){
                $push=\Our\Push::getInstance();
                $push->addOneToClient(array('storeId'=>$member['store_id'],'type'=>\Our\ApiConst::messageOtherLogin,'params'=>array('c'=>'member','m'=>'logOut')));
                $push->sendTcpMessage();
            }
            $this->updataSellerToken($member);
            $member['sendTime']=TIMESTAMP;
            $storeRedisDb0->tableHMSet(trim($member['store_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;

    }
    private function getRealPassword($password,$timeSpan){
        $addKey=Common::getConfig('password.key');
        $md5Str = $timeSpan.$password.$addKey;
        return $md5Str;
    }

    public function getOneByMobileAndPassword($mobile, $password)
    {
//      $password=$this->getPassAddKey($password);
//      $password = Common::format('md5({0})');
        $member= $this->memberDao->getOneByMobileAndPassword($mobile, $password);
        return $member ? $member : false;
    }


    public function getOneByStoreId($storeId){
         $memberDao=\DAO\MemberModel::getInstance();
         $member=$memberDao->getOneByStoreId($storeId);
         return $member;
    }

    /**
     * 登录业务
     *
     * @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' => TIMESTAMP,
            'client_type' => Common::getDriverType(true),
        ];
        return $mbUserToken->insertOrUpdate($inserData);
    }
    public function updataSellerToken($data)
    {
        $sellerDao = \DAO\Store\SellerModel::getInstance(DbNameConst::masterDBConnectName);
        $inserData = [
            'token' => $data['key'],
            'last_login_time' => TIMESTAMP,
        ];
        return $sellerDao->updateBySellerId($inserData,$data['seller_id']);
    }

    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);
        $addKey=Common::getConfig('password.key');
        $memberTime = TIMESTAMP;
        if(!empty($addKey)){
            $md5Str=$memberTime.$where['password'].$addKey;
        }else{
            $md5Str=$where['password'];
        }

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

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

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

    /**
     * 保存店铺会员
     * @param $memberId
     * @return bool
     */
    public function saveStoreMembers($memberId){
        $sess=\Yaf\Session::getInstance();
        $scan_store_ids = $sess->get('scan_store_ids');//扫码带入的店铺ID
        if($scan_store_ids){
            if(!is_array($scan_store_ids)){
                $scan_store_ids = explode(',',$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;
                $storeMember['fav_type'] = \Our\ApiConst::one;
                $storeMembers[] = $storeMember;
            }
            /*$storeMemberDao = \DAO\StoreMemberModel::getInstance(\Our\DbNameConst::masterDBConnectName);
            $result = $storeMemberDao->addBatch($storeMember);*/
            $favoritesStoreDao = \DAO\FavoritesStoreModel::getInstance();
            $storeIds = array_column($scan_store_ids,'store_id');
            //$list = $favoritesStoreDao->selectList(array('store_id'=>array('in',$storeIds),'member_id'=>$memberId,'fav_type'=>0),'store_id');
            $list = $favoritesStoreDao->selectList(array('store_id'=>array('in',$storeIds),'member_id'=>$memberId,'fav_type'=>\Our\ApiConst::one),'store_id');
            $storeIds2 = $list ? array_column($list, 'store_id') : [];
            $storeIds = array_diff($storeIds,$storeIds2);
            $result = $favoritesStoreDao->insertAll($storeMembers);
            if(!$result){
                \Our\Log::getInstance()->write(json_encode($storeMembers).'扫码数据写入失败');
                return false;
            }
            if($storeIds && $result) {
                $favoritesStoreDao->updateStoreCollecitonsCache($storeIds,$memberId,2);
            }

        }
        $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();
            if($saleList&&$saleList['list']){
                foreach($saleList['list'] 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);
        }
        $memberTime= $memberDao->getInfo($memberMapping['member_id'],'member_time');
        if(!$memberTime){
            $memberTime = TIMESTAMP;
        }
        $passwordStr = $this->getRealPassword($where['password'],$memberTime);
        $member['member_mobile'] = $where['mobile'];
        $member['member_mobile_bind'] = \Our\ApiConst::one;
        $member['member_passwd'] = md5($passwordStr);
        $member['member_time'] = $memberTime;
        $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);
        $memberTimeArray = $memberDao->getOneByWhereWithField(array('member_mobile'=>$passwordMobile),'member_time');
        $memberTime = TIMESTAMP;
        if($memberTimeArray&&$memberTimeArray['member_time']){
            $memberTime = $memberTimeArray['member_time'];
        }
        $passwordStr = $this->getRealPassword($data['password'],$memberTime);
        $result = $memberDao->updateInfo(array('member_passwd'=>  md5($passwordStr),'member_time'=>$memberTime),array('member_mobile'=>$passwordMobile));
        if($result===false){
            return false;
        }
        $sess->del('findPasswordMobile');
        return true;
    }


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

        $data['messageType'] = \Our\ApiConst::messageTypeValidNewMobile;
        $shortMessageDao->validCode($data);
        $memberTime= $memberDao->getInfo($memberId,'member_time');
        if(!$memberTime){
            $memberTime = TIMESTAMP;
        }
        $oldMemberMobile= $memberDao->getInfo($memberId,'member_mobile');
        $passwordStr = $this->getRealPassword($data['password'],$memberTime);

        $storeModel = \DAO\StoreModel::getInstance(\Our\DbNameConst::masterDBConnectName);
        $store = $storeModel->getInfo(array('store_phone'=>$oldMemberMobile));
        $memberDao->db->doTransaction();
        $result = $memberDao->updateInfo(array('member_passwd'=>md5($passwordStr),'member_mobile'=>$data['mobile'],'member_time'=>$memberTime,'member_mobile_bind'=>\Our\ApiConst::one),array('member_id'=>$memberId));
        if(!$result){
            $memberDao->db->doRollback();
            \Error\ErrorModel::throwException(\Error\CodeConfigModel::changeMobileFailed);
        }
        if($store){
            $storeResult = $storeModel->save(array('store_phone'=>$data['mobile'],'seller_name'=>$data['mobile']),array('store_id'=>$store['store_id']));
            if($storeResult===false){
                $memberDao->db->doRollback();
                \Error\ErrorModel::throwException(\Error\CodeConfigModel::storePhoneUpdateFailed);
            }
            $resultStoreJoinin = \DAO\Store\StoreJoininModel::getInstance(\Our\DbNameConst::masterDBConnectName)->save(array('seller_name'=>$data['mobile']),array('member_id'=>$store['member_id']));
            if($resultStoreJoinin===false){
                $memberDao->db->doRollback();
                \Error\ErrorModel::throwException(\Error\CodeConfigModel::sellerJoinUpdateFailed);
            }
        }
        $sellerResult = \DAO\Store\SellerModel::getInstance(\Our\DbNameConst::masterDBConnectName)->update(array('seller_name'=>$data['mobile']),array('seller_name'=>$oldMemberMobile));
        if($sellerResult===false){
            $memberDao->db->doRollback();
            \Error\ErrorModel::throwException(\Error\CodeConfigModel::sellerNameUpdateFailed);
        }

        $memberDao->db->doCommit();
        if($store){
            \Our\RedisHelper::delCachedFunction(\Redis\Db6\StoreRedisModel::getInstance(),array(&$storeModel, 'getInfoById'),array(),array($store['store_id']));
        }
        $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);
        $memberTime = TIMESTAMP;
        $memberTimeStr = $memberDao->getInfo($memberId,'member_time');
        if(!$memberTimeStr){
            $memberTime = $memberTimeStr;
        }
        $passwordStr = $this->getRealPassword($where['password'],$memberTime);
        $result = $memberDao->updateInfo(array('member_passwd'=>md5($passwordStr),'member_time'=>$memberTime),array('member_id'=>$memberId));
        if($result){
            $this->logOut($where['key']);
            return true;
        }
        return false;
    }

    public function checkSaveWechatInfo($where, $wxappopenid = ''){
        $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, $wxappopenid);
            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, $authInfo['openid']);
        if($returnMember){
            return $returnMember;
        }
        $db->doTransaction();
        $openid = $this->getUnionId($where['encryptedData'],$where['iv'],$where['session_key']);
        $wxappOpenid = $authInfo['session_key'];
        $memberId = $this->saveWxInfoMemberInfo($where, $openid, $wxappOpenid);

        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);
        $memberTime = TIMESTAMP;
        $memberTimeStr = $memberDao->getInfo($memberId,'member_time');
        if(!$memberTimeStr){
            $memberTime = $memberTimeStr;
        }
        $passwordStr = $this->getRealPassword($data['password'],$memberTime);
        $updateMember = array('member_passwd'=>md5($passwordStr),'member_mobile'=>$data['mobile'],'member_mobile_bind'=>\Our\ApiConst::one,'member_time'=>$memberTime);
        $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();

        $memberTime = TIMESTAMP;
        $memberTimeStr = $memberDao->getInfo($memberId,'member_time');
        if(!$memberTimeStr){
            $memberTime = $memberTimeStr;
        }
        $passwordStr = $this->getRealPassword($data['password'],$memberTime);
        $data['messageType'] = \Our\ApiConst::messageTypeWxLietBindMobile;
        $shortMessageDao->validCode($data);
        if($mobileMember){
            $memberDao->db->doTransaction();
            $updateMobileMember['member_passwd'] = md5($passwordStr);
            $updateMobileMember['member_time'] = $memberTime;
            $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{

            $memberTime = TIMESTAMP;
            $memberTimeStr = $memberDao->getInfo($memberId,'member_time');
            if(!$memberTimeStr){
                $memberTime = $memberTimeStr;
            }
            $passwordStr = $this->getRealPassword($data['password'],$memberTime);
            $data['messageType'] = \Our\ApiConst::messageTypeWxLietBindMobile;
            $updateMember = array('member_passwd'=>md5($passwordStr),'member_mobile'=>$data['mobile'],'member_mobile_bind'=>\Our\ApiConst::one,'member_time'=>$memberTime);
            $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;
    }


    public function growMembers(){
        $memberDao=\DAO\MemberModel::getInstance();
        $res =$memberDao->getAll();
        $pre="1780";
        for($i=0;$i<1000000;$i++){
            $memberId=50000+$i;
            $re=array_rand($res);
            if(!empty($res[$re])){
                $data=$res[$re];
                $data['member_id']=$memberId;
                $data['store_id']=$memberId;
                $data['member_mobile']=$pre.(string)(1000000+$i);
                $data['store_id']=$memberId;
                $data['member_passwd']='a18ddf021c99cb0d9e3ff3b52815d1de';
                $data['member_time']='1461747049';
                $memberDao->add($data);
                echo '增加数据'.$i.'条member_id 是:'.$memberId."\n";
            }
        }
    }


    /**
     * 获取当前用户最新的扫码关注店铺
     * @param $memberId
     * @return int
     * @throws \Our\Exception
     */
    public function getMyFavoritesStore($memberId){
        if($memberId){
            $favoritesDao = \DAO\FavoritesStoreModel::getInstance();
            $favStore = \Our\RedisHelper::cachedFunction(\Redis\Db6\FavoritesStoreRedisModel::getInstance(),array(&$favoritesDao, 'getOne'),array('store_id',array('fav_from'=>\Our\ApiConst::scanFavor,'member_id'=>$memberId)),\Our\ApiConst::oneDaySecond,array($memberId));
            if($favStore&&$favStore['store_id']){
                return $favStore['store_id'];
            }
        }
        return \Our\ApiConst::zero;
    }


    public function updateMemberAreaInfo(){
        $currentTime = TIMESTAMP;
        $startTime = $currentTime-\Our\ApiConst::oneDaySecond;
        if($currentTime<1546272000){
            $startTime =0;
        }
        $whereSql = \Our\Common::format("member_provinceid = '0' and  member_cityid = '0' and  register_ip !=''  and  (member_time between '{0}' and '{1}') ",$startTime,$currentTime);
        $memberDao = \DAO\MemberModel::getInstance();
        $memberList = $memberDao->getList($whereSql,'member_id,register_ip');
        if($memberList){
            foreach($memberList as $member){
                $ip = $member['register_ip'];
                $updateData = \Area\AreaUtil::getInstance()->getIpCityInfo($ip);
                $memberDao->saveInfo($updateData,$member['member_id']);
            }
        }
    }

}
