<?php
class wxAction extends baseAction
{
	/**
	  * @method 更新微信账号的通信录 
	    整体周期：30天
		仅更新新的部分：7天  
		单账号每天更新200个好友信息
	  * @param  count 默认40 每个微信更新通信录用户信息数量
	  */
	function wxUserTask()
	{
		$Params = mvc::$URL_PARAMS;
		//if(!LibFc::hasFunLock(mvc::$URL_METHOD, 1200)) return true;
		$upCount = $Params['count']? $Params['count']: 200;
		$h = date('H');
		if($h < 9 || $h > 18) exit('不允许在此时间段内操作微信API');
		$reg = [
			'all'=>strtotime('-30 days'),	
			'onlynew'=>strtotime('-7 days'),	
			'maxday'=>800,	
		];
		$B2cBase = new B2cBase();
		$OthWechatBot = new OthWechatBot();

		//主账号信息
		$tokenWhere = sprintf(" and wrt_status=1 and wrt_loginstatus=1 and wrt_token_type='eyapi' and wrt_comname='宜配CRM' and wrt_login_last < %d and (wrt_sleeptime is null or UNIX_TIMESTAMP(wrt_sleeptime) < %d)", time() -3600*24*2, time());
		$where = $tokenWhere.sprintf("AND wrt_wxid NOT IN (SELECT wu_wxid FROM wx_user JOIN wx_user_address ON wua_mwu_id = wu_id AND wu_id = wua_wu_id AND wu_isaccout=1 WHERE wua_utime > %d)", $reg['onlynew']);
		$res = $B2cBase->get('wx_robot_token', ['wrt_id', 'wrt_eywid'], $where);
		foreach($res['data'] as $v){
			$OthWechatBot->initMainUser($v['wrt_id']);
		}
		
		//整体周期：30天
		$where = $tokenWhere.sprintf(" and wu_address_status in (-1, 0,2) and wu_address_utime < %d group by wu_id", $reg['all']);
		$res = $B2cBase->get('wx_user join wx_robot_token on wrt_wxid = wu_wxid and wu_isaccout=1', ['wu_id', 'wrt_id', 'wrt_eywid'], $where);
		foreach($res['data'] as $v){
			$OthWechatBot->updateWxUserAddrList($v['wrt_id'], $v['wu_id'], 'all');
		}

		//仅更新新的部分：7天  
		$where = $tokenWhere.sprintf(" and wu_address_status2 in (-1,2) and wu_address_utime2 < %d group by wu_id", $reg['onlynew']);
		$res = $B2cBase->get('wx_user join wx_robot_token on wrt_wxid = wu_wxid and wu_isaccout=1', ['wu_id', 'wrt_id', 'wrt_eywid'], $where);
		foreach($res['data'] as $v){
			$OthWechatBot->updateWxUserAddrList($v['wrt_id'], $v['wu_id'], 'onlynew');
		}
		
		//更新通信录明细 随机分散
		$per = 20;
		$today = strtotime(date('Y-m-d'));
		$where = $tokenWhere." and (wu_address_status=1 or wu_address_status2=1) group by wu_id order by rand()";
		$res = $B2cBase->get('wx_user a join wx_robot_token on wrt_wxid = wu_wxid and wu_isaccout=1', ['wrt_id', 'wrt_eywid', 'a.*'], $where);
		foreach($res['data'] as $v){
			$max = ceil($upCount / $per);
			for($i = 0; $i < $max; $i++){
				//已经处理个数
				$res = $B2cBase->get('wx_user_address', ['count(*) ok_count'], sprintf(" and wua_mwu_id=%d and wua_ustatus = 2 and wua_utime>=%d", $v['wu_id'], $today), true);
				$okcount = $res['data']['ok_count'];
				if($okcount >= $reg['maxday']) break;
				$need = $reg['maxday'] - $okcount;
				if($need > $per) $need = $per;
				$res = $B2cBase->get('wx_user_address join wx_user on wua_wu_id=wu_id', ['wu_wxid'], sprintf(" and wua_mwu_id=%d and wua_ustatus!=2 limit %d", $v['wu_id'], $need));
				$wxids = array_column($res['data'], 'wu_wxid');
				$OthWechatBot->updateWxUserAddrByWxids($v['wrt_eywid'], $v['wu_id'], $wxids);
				sleep(1,10);
				if(count($wxids) < $need) break;
			}
			$res = $B2cBase->get('wx_user_address', ['count(*) wait_count'], sprintf(" and wua_mwu_id=%d and wua_ustatus!=2", $v['wu_id']), true);
			if($res['data']['wait_count'] == 0){
				if($v['wu_address_status'] == 1){
					$B2cBase->set('wx_user', ['wu_address_status'=>2, 'wu_address_utime'=>time(), 'wu_address_status2'=>2, 'wu_address_utime2'=>time()], sprintf(" and wu_id=%d", $v['wu_id']));
				}else{
					$B2cBase->set('wx_user', ['wu_address_status2'=>2, 'wu_address_utime2'=>time()], sprintf(" and wu_id=%d", $v['wu_id']));
				}
			}
		}
		$this->linkWxUserToYpUser();
		
		$B2cBase->query("UPDATE `wx_user` JOIN `wx_robot_token` ON wu_wxid = wrt_wxid AND wu_isaccout = 1 JOIN `an_user` ON wrt_uid = au_uid SET wu_realname = au_name, wu_auid = au_uid, wu_uid = au_uid WHERE wu_realname = ''");

		//省市补充
		$B2cBase->query("UPDATE `ypb2c`.`wx_user`
		JOIN `ypdb_write`.`yp_province_city` ON pc_pid = 0 AND INSTR(pc_en_name, wu_province) > 0 AND wu_province != '' AND wu_province_id = 0 AND wu_province !=''
		SET wu_province = pc_name, wu_province_id = pc_id");
		$B2cBase->query("UPDATE `ypb2c`.`wx_user`
		JOIN `ypdb_write`.`yp_province_city` ON pc_pid IN (SELECT pc_id FROM `ypdb_write`.`yp_province_city` WHERE pc_pid = 0) AND INSTR(pc_en_name, wu_city) > 0 AND wu_city_id = 0 AND wu_city !=''
		SET wu_city = pc_name, wu_city_id = pc_id");
		
		//更新回复信息
		$B2cBase->query("UPDATE `yp_crm`.`ts_msg_history` a JOIN (
		SELECT tmh_id, MIN(wum_id) wum_id
		FROM `yp_crm`.`ts_msg_history`
		JOIN `ypb2c`.`wx_user` u1 ON tmh_from_wu_id = u1.wu_id
		JOIN `ypb2c`.`wx_user` u2 ON tmh_to_wu_id = u2.wu_id
		JOIN `ypb2c`.`wx_user_msg` ON wum_from_wxid = u2.wu_wxid AND wum_to_wxid = u1.wu_wxid
		WHERE tmh_status = 1 AND tmh_reply_wum_id = 0 AND wum_send_time > tmh_send_time GROUP BY tmh_id
		) t ON t.tmh_id = a.tmh_id SET a.tmh_reply_wum_id = t.wum_id");

		LibFc::delFunLock(mvc::$URL_METHOD);
		echo 'ok';
	}

	//绑定微信用户和宜配会员
	function linkWxUserToYpUser()
	{
		$B2cBase = new B2cBase();
		$OthWechatBot = new OthWechatBot();
		$lastid = 0;
		$per = 100;	
		while(true){
			$res = $B2cBase->get('wx_user', ['wu_id'], sprintf(" and wu_uid = 0 and wu_nickname !='' and wu_id > %d order by wu_id limit %d", $lastid, $per));
			$wuids = array_column($res['data'], 'wu_id');
			$lastid = end($wuids);
			if(empty($wuids)) break;
			$OthWechatBot->linkWxUserToYpUser($wuids);
			if(count($wuids) < $per) break;
		}
		echo 'ok';
	}

	//初始化微信头像
	function initWxHeadimg()
	{
		if(!LibFc::hasFunLock(mvc::$URL_METHOD, 600)) return true;
		$YpwWx = new YpwWx();
		$YpwWx->initWxHeadimg();
		LibFc::delFunLock(mvc::$URL_METHOD);
		echo 'ok';
	}

	//生产推送广告位记录
	function tsAdsPlaceToUser()
	{
		if(!LibFc::hasFunLock(mvc::$URL_METHOD, 3600)) return true;
		$CrmAds = new CrmAds();
		$CrmAds->del('ts_msg_history', sprintf(" and tmh_status=0 and tmh_atime < %d", strtotime('-2days', strtotime(date('Ymd')))));
		$CrmAds->tsAdsPlaceToUser();
		LibFc::delFunLock(mvc::$URL_METHOD);
		echo 'ok';
	}

	//发送消息任务  尽量利用随机间隔和分散发送人
	function sendWxMsgTask()
	{
		set_time_limit(0);
		$CrmBase = new CrmBase();
		$B2cBase = new B2cBase();
		$YpwBase = new YpwBase();
		$actArr = [
			//发送消息
			'sendmsg'=>[
				//每天最大数
				'max_count'=>50,
				//登录多少天后可以操作
				'loginday'=>2,
			], 
			//加好友
			'addfriend'=>[
				//每天最大数
				'max_count'=>20,
				//登录多少天后可以操作
				'loginday'=>7,
			], 
		];
		while(1){
			$h = date('H');
			$now = time();
			$today = date('Ymd');
			$res = $YpwBase->getKeyVal('holidays');
			$holidays = explode(',', $res['data']);
			if(in_array((int) date('Y-m-d'), $holidays) || in_array((int) date('N'), [6, 7])){
				LibFc::waitRand(300, 800, "非工作时间...");
				continue;
			}

			$ranges = [
				[strtotime($today . ' 09:00'), strtotime($today . ' 12:00')],
				[strtotime($today . ' 13:30'), strtotime($today . ' 18:00')],
			];
			//计算今天剩余的工作时间，单位秒
    		$hasTime = 0;
			$isWork = false;
			foreach ($ranges as [$start, $end]) {
				if ($now <= $start) {
					$hasTime += $end - $start;
				}else if ($now > $start && $now < $end) {
					$hasTime += $end - $now;
					$isWork = true;
				}
			}
			if(!$isWork || $hasTime < 600){
				LibFc::waitRand(300, 800, "非工作时间...");
				continue;
			}
			
			//当天开始时间戳
			$tbtime = strtotime(date('Y-m-d'));

			foreach($actArr as $act=>$reg){
				//发消息
				if($act == 'sendmsg'){
					//可用的发送人
					$reg['loginday'] = $reg['loginday'] < 1? 1: $reg['loginday'];
					$where = sprintf(" and wrt_status=1 and wrt_loginstatus=1 and wrt_token_type='eyapi' and wrt_comname='宜配CRM' and wrt_login_last < %d and (wrt_sleeptime is null or UNIX_TIMESTAMP(wrt_sleeptime) < %d)", strtotime('-'.$reg['loginday'].' days'), time());
					$res = $B2cBase->get('wx_robot_token join wx_user on wrt_wxid = wu_wxid and wu_isaccout=1 join an_user on wu_uid=au_uid', ['wu_id', 'wu_uid', 'wrt_id', 'au_name', 'wrt_eywid', '3 max_count', '0 has_count', '0 last_time'], $where);
					if(empty($res['data'])) {
						LibFc::waitRand(300, 800, "没有可用的微信机器人");
						continue;
					}
					$tokenArr = array_column($res['data'], null, 'wu_id');
					$mwuIds = array_keys($tokenArr);
					//最近一周的发送统计，平均每天发送数，供后续推送控制使用
					$table = sprintf("( SELECT  tmh_from_wu_id AS wu_id, DATE(FROM_UNIXTIME(tmh_send_time)) AS tj_date, COUNT(*) AS has_count FROM ts_msg_history WHERE tmh_status = 1 and tmh_from_wu_id in (%s) AND tmh_send_time BETWEEN %d AND %d GROUP BY tmh_from_wu_id, tj_date) t", implode(',', $mwuIds),  $tbtime - 3600*24*7, $tbtime);
					$res = $CrmBase->get($table, ['wu_id, AVG(has_count) avg_count'], " group by wu_id");
					foreach($res['data'] as $v){
						$max = ceil($v['avg_count']*1.1);
						if($max > $reg['max_count']) $max = $reg['max_count'];
						$tokenArr[$v['wu_id']]['max_count'] = $max;
					}
					
					//今日已发送统计
					$res = $CrmBase->get('ts_msg_history', ['tmh_from_wu_id wu_id, COUNT(*) has_count, MAX(tmh_send_time) last_time'], sprintf(" and tmh_status = 1 and tmh_from_wu_id in (%s) and tmh_send_time >=%d GROUP BY tmh_from_wu_id", implode(',', $mwuIds), $tbtime));
					foreach($res['data'] as $v){
						if($v['has_count'] >= $tokenArr[$v['wu_id']]['max_count']){
							unset($tokenArr[$v['wu_id']]);
							continue;
						}
						$tokenArr[$v['wu_id']]['has_count'] = $v['has_count'];
						$tokenArr[$v['wu_id']]['last_time'] = $v['last_time'];
					}
					if(empty($tokenArr)){
						LibFc::waitRand(300, 800, "没有可用的微信机器人");
						continue;
					}
					$mwuIds = array_keys($tokenArr);
					$auLinks = array_column($tokenArr, null, 'wu_uid');

					$where = sprintf("  and tmh_status = 0 AND wua_mwu_id IN (%s) GROUP BY tmh_id ORDER BY RAND()", implode(',', $mwuIds));
					$table = '`yp_crm`.`ts_msg_history` a
					JOIN `ypb2c`.`wx_user` ON wu_uid = tmh_u_id
					JOIN `ypb2c`.`wx_user_address` ON wua_wu_id = wu_id AND wua_mwu_id != wua_wu_id AND wua_status = 1';
					$mres = $CrmBase->get($table, ['a.*', 'GROUP_CONCAT(wua_mwu_id) mwu_ids'], $where);
					foreach($mres['data'] as $v){
						//这个用户有哪些业务员
						$where = sprintf(" and wu_uid = %d", $v['tmh_u_id']);
						$where .= $v['tmh_au_id'] ? sprintf(" AND wua_mwu_id = %d", $auLinks[$v['tmh_au_id']]['wu_id']): sprintf(" AND wua_mwu_id IN (%s)", implode(',', $mwuIds));
						$res = $B2cBase->get('wx_user JOIN wx_user_address ON wu_id = wua_wu_id AND wu_isaccout=0 and wua_autosend =1', ['wu_id, wu_wxid, wu_type,wu_uid,wu_nickname,wua_mwu_id'], $where);
						$toUser = [];
						foreach($res['data'] as $tv){
							//剩余可发的平均每条消息需要等待的时间
							$waitTime =  ceil($hasTime / ($tokenArr[$tv['wua_mwu_id']]['max_count'] - $tokenArr[$tv['wua_mwu_id']]['has_count'])) - rand(60, 120);
							if($waitTime < 600) $waitTime = 600;
							if($tokenArr[$tv['wua_mwu_id']]['has_count'] >= $tokenArr[$tv['wua_mwu_id']]['max_count'] || (time() - $tokenArr[$tv['wua_mwu_id']]['last_time']) < $waitTime){
								continue;
							}else{
								$toUser = $tv;
								break;
							}
						}
						if(empty($toUser)) continue;
						$CrmBase->set('ts_msg_history', ['tmh_status'=>2, 'tmh_etime'=>time()], sprintf(" and tmh_id=%d", $v['tmh_id']));
						$tokenInfo = $tokenArr[$toUser['wua_mwu_id']];
						$v['tmh_msg'] = json_decode($v['tmh_msg'], true);
						$OthWechat = new OthWechatEy();
						$OthWechat->eywid = $tokenInfo['wrt_eywid'];
						switch($v['tmh_msg_type']){
							case 'wxtext': 
								$tpost = [
									"wcId"=> $toUser['wu_wxid'],
									"content"=> $v['tmh_msg']['des']
								];
								$OthWechat->getWxApi('sendText', $tpost);
							break;
							case 'wxcard': 
								$tpost = [
									"wcId"=> $toUser['wu_wxid'],
									"title"=> $v['tmh_msg']['title'],
									"description"=> $v['tmh_msg']['des'],
									"url"=> $v['tmh_msg']['url'],
									"thumbUrl"=> $v['tmh_msg']['img']	
								];
								$OthWechat->getWxApi('sendUrl', $tpost);
							break;
							default:
								return LibFc::ReturnData(false, $v['tmh_msg_type'].'消息类型尚未配置');
							break;
						}
						$tokenArr[$toUser['wua_mwu_id']]['has_count']++;
						$tokenArr[$toUser['wua_mwu_id']]['last_time'] = time();
						$set = [
							'tmh_status'=>1,
							'tmh_send_time'=>time(),
							'tmh_from_au_id'=>$tokenInfo['wu_uid'],
							'tmh_from_wu_id'=>$toUser['wua_mwu_id'],
							'tmh_to_wu_id'=>$toUser['wu_id'],
							'tmh_etime'=>time()
						];
						$CrmBase->set('ts_msg_history', $set, sprintf(" and tmh_id=%d", $v['tmh_id']));
						echo "{$tokenInfo['au_name']}=>{$toUser['wu_nickname']}: {$v['tmh_msg']['des']}\n";
					}
				}else if($act == 'addfriend') {//加好友
					$reg['loginday'] = $reg['loginday'] < 7? 7: $reg['loginday'];
					$where = sprintf(" and wrt_status=1 and wrt_loginstatus=1 and wrt_token_type='eyapi' and wrt_comname='宜配CRM' and wrt_login_last < %d and (wrt_sleeptime is null or UNIX_TIMESTAMP(wrt_sleeptime) < %d)", strtotime('-'.$reg['loginday'].' days'), time());
					$res = $B2cBase->get('wx_robot_token join wx_user on wrt_wxid = wu_wxid and wu_isaccout=1 join an_user on wu_uid=au_uid', ['wu_id', 'wu_uid', 'wrt_id', 'au_name', 'wrt_eywid', '1 max_count', '0 has_count', '0 last_time'], $where);
					if(empty($res['data'])) {
						LibFc::waitRand(300, 800, "没有可用的微信机器人");
						continue;
					}
					$tokenArr = array_column($res['data'], null, 'wu_id');
					
					$mwuIds = array_keys($tokenArr);
					//最近一周加好友统计
					$table = sprintf("( SELECT wun_from_wu_id AS wu_id, DATE(FROM_UNIXTIME(wun_atime)) AS tj_date, COUNT(*) AS tj_count FROM wx_user_newfriend WHERE wun_from_wu_id in (%s) AND wun_atime BETWEEN %d AND %d GROUP BY wun_from_wu_id, tj_date) t", implode(',', $mwuIds),  $tbtime - 3600*24*7, $tbtime);
					$res = $B2cBase->get($table, ['wu_id, AVG(tj_count) avg_count'], " group by wu_id");
					foreach($res['data'] as $v){
						$max = ceil($v['avg_count']*1.1);
						if($max > $reg['max_count']) $max = $reg['max_count'];
						$tokenArr[$v['wu_id']]['max_count'] = $max;
					}
					
					//今日加好友
					$res = $B2cBase->get('wx_user_newfriend', ['wun_from_wu_id wu_id, COUNT(*) has_count, MAX(wun_atime) last_time'], sprintf(" and wun_from_wu_id in (%s) and wun_atime >=%d GROUP BY wun_from_wu_id", implode(',', $mwuIds), $tbtime));
					foreach($res['data'] as $v){
						if($v['has_count'] >= $tokenArr[$v['wu_id']]['max_count']){
							unset($tokenArr[$v['wu_id']]);
							continue;
						}
						$tokenArr[$v['wu_id']]['has_count'] = $v['has_count'];
						$tokenArr[$v['wu_id']]['last_time'] = $v['last_time'];
					}
					if(empty($tokenArr)){
						LibFc::waitRand(300, 800, "没有可用的微信机器人");
						continue;
					}
					$mwuIds = array_keys($tokenArr);
					$auLinks = array_column($tokenArr, null, 'wu_uid');

					$where = sprintf(" AND tmh_status = 0 
					and tmh_u_id NOT IN (SELECT DISTINCT wu_uid FROM `ypb2c`.`wx_user`)
					and tmh_u_id NOT IN (SELECT DISTINCT wun_to_uid FROM `ypb2c`.`wx_user_newfriend`) 
					and tmh_u_id NOT IN (SELECT DISTINCT ctr_uid FROM `crm_customer_admin` JOIN `crm_customer` ON ctr_id = cca_ctr_id WHERE cca_level_id IN (1,2,5) AND cca_end_time > %d)
					and tmh_au_id in (0, %s) GROUP BY tmh_u_id ORDER BY RAND() LIMIT 100", time(), implode(',', array_keys($auLinks)));
					$mres = $CrmBase->get('ts_msg_history JOIN ts_msg_tpl ON tm_id = tmh_tm_id', ['tmh_id, tm_type, tmh_u_id, tmh_au_id', "JSON_UNQUOTE(tmh_para->'$.reason') reason"], $where);
					foreach($mres['data'] as $v){
						//这个客户添加到哪个微信账号
						$tokenInfo = [];
						if($v['tmh_au_id']){
							$tokenInfo = $auLinks[$v['tmh_au_id']];
						}else{
							//还可以加的账号
							$tVals = $tokenArr;
							shuffle($tVals);
							foreach($tVals as $tv){
								$waitTime =  ceil($hasTime / ($tv['max_count'] - $tv['has_count'])) - rand(60, 120);
								if($waitTime < 600) $waitTime = 600;
								if($tv['has_count'] >= $tv['max_count'] || (time() - $tv['last_time']) < $waitTime){
									continue;
								}else{
									$tokenInfo = $tv;
									break;
								}
							}
						}
						if(empty($tokenInfo)) continue;
						$res = $YpwBase->get('yp_user', ['u_mobile'], sprintf(" and u_id=%d and u_mobile_check='Y'", $v['tmh_u_id']), true);
						if(empty($res['data']['u_mobile'])) continue;
						$v['u_mobile'] = $res['data']['u_mobile'];

						$verify = '您好，我是跑街令工作人员'.$tokenInfo['au_name'].'，注意到您是跑街令的资深用户，如果您在使用上有任何问题或者有计划在跑街令上做推广的需求随时可以联系我。';
						
						$CrmBase->set('ts_msg_history', ['tmh_status'=>3, 'tmh_etime'=>time()], sprintf(" and tmh_id=%d", $v['tmh_id']));
						$OthWechat = new OthWechatEy();
						$OthWechat->eywid = $tokenInfo['wrt_eywid'];
						$res = $OthWechat->getWxApi('searchUser', ["wcId"=>$v['u_mobile']]);
						$newUser = $res['data'];
						if(empty($newUser['nickName']) || empty($newUser['v1']) || empty($newUser['v2'])) continue;

						$tpost = [
							"v1"=> $newUser['v1'],
							"v2"=> $newUser['v2'],
							"type"=> 15,
							"verify"=> $verify
						];
						$OthWechat->getWxApi('addUser', $tpost);
						$tokenArr[$tokenInfo['wu_id']]['has_count']++;
						$tokenArr[$tokenInfo['wu_id']]['last_time'] = time();
						$add = [
							'wun_from_uid'=>$tokenInfo['wu_uid'],
							'wun_from_wu_id'=>$tokenInfo['wu_id'],
							'wun_mobile'=>$v['u_mobile'],
							'wun_to_uid'=>$v['tmh_u_id'],
							'wun_info'=>LibFc::jsonEncode($newUser),
							'wun_verify'=>$verify,
							'wun_reason'=>$v['reason'],
							'wun_atime'=>time(),
							'wun_from'=>'tsmsg',
							'wun_from_id'=>$v['tmh_id'],
						];
						$B2cBase->add('wx_user_newfriend', $add);
						echo "{$tokenInfo['au_name']}=>添加好友 {$v['u_mobile']}\n";

					}
				}
				
				$sleep = rand(120, 180);
				echo "sleep {$sleep}s\n";
				sleep($sleep);
			}
			$sleep = rand(120, 300);
			echo "sleep {$sleep}s\n";
			sleep($sleep);
		}
		echo 'ok';
	}
}