<?php


namespace App\Services\user;

use App\Models\user\mysql\UserWechatBind;
use Api\PhpUtils\Http\Request;
use App\Services\user\Weixin\WxBizDataCrypt;;
use App\Exception\BaseException;
use App\Exception\custom\UserException;

use Api\PhpUtils\Validate\Validate;
use Api\PhpServices\Idgen\Idgen;
use Api\PhpUtils\Redis\RedisUtil;
use Api\PhpServices\JwUser\JwUser;
use App\Services\common\CommonService;
use Api\PhpUtils\Log\FileLog;
use Api\PhpUtils\Lock\FrequencyLockUtil;

class UserService
{
    private $code;
    private $grant_type = 'authorization_code';
    private $loginUrl = 'https://api.weixin.qq.com/sns/jscode2session';

    public static function wechatLogin($params)
    {
        $code = !empty($params['code']) ? $params['code'] : '';//小程序授权code
        $openid = !empty($params['openid']) ? $params['openid'] : '';//小程序授权code
        $inviteUserId = !empty($params['invite_user_id']) ? intval($params['invite_user_id']) : 0;//邀请用户id
        $activityType = !empty($params['activity_type']) ? intval($params['activity_type']) : 0;//活动类型
        if (empty($code) && empty($openid)) {
            FileLog::error("wechatLogin:获取参数为空", json_encode($params, JSON_UNESCAPED_UNICODE),'','jianghaiming@yidian-inc.com');
            throw new UserException(['cus' => 0]);
        }

        $redis = RedisUtil::getInstance('cache');
        $key = "wx_wechat_login_".$code;
        $keyCode = "wx_wechat_login_code_".$code;
        $lock = FrequencyLockUtil::isLocked($key,1,120);
        if ($lock) {
            sleep(1);
            $user = $redis->get($keyCode);
            if (!empty($user)) {
                $user = json_decode($user,true);
            }
            FileLog::error("wechatLogin: lock", json_encode($user, JSON_UNESCAPED_UNICODE),'','jianghaiming@yidian-inc.com');
            FileLog::error("wechatLogin: lock--params", json_encode($params, JSON_UNESCAPED_UNICODE),'','jianghaiming@yidian-inc.com');
            return $user;
        }

        //需要授权微信
        //if (empty($openid)) {
            $appid = \Yaf\Registry::get('config')->wechat->appid;
            $secret = \Yaf\Registry::get('config')->wechat->secret;
            $grant_type = 'authorization_code';
            $loginUrl = 'https://api.weixin.qq.com/sns/jscode2session'; 
            //请求接口，获取用户openid
            $params = [
                'appid' => $appid,
                'secret' => $secret,
                'js_code' => $code,
                'grant_type' => $grant_type,
            ];
            $response = (new Request())->post($loginUrl, $params);


        $end = microtime(true);
        $totalTime = round(($end - $begin), 4) * 1000;
        if ($response['code'] == 0) {
            $response = $response['response'];
        }

        //mon打点
        $env = \Yaf\Application::app()->environ() ?? "dev";
        MonUtil::proxyMon($loginUrl, $response['code'], 'weixin_'.$env, $totalTime);

        if (empty($response) || array_key_exists('errcode', $response)) {
            //throw new \Exception('获取openid失败:' . $response['errcode']);
            FileLog::error("wechatLogin：获取openid失败", json_encode($params, JSON_UNESCAPED_UNICODE), '', 'jianghaiming@yidian-inc.com');
            throw new UserException(['cus' => 1]);
        }
        //检查系统是已注册
        $openid = !empty($response['openid']) ? $response['openid'] : '';


        $user = UserWechatBind::getRecordMaster(['openid' => $openid]);
        //如果系统不存在，用户信息，则注册新用户
        if (empty($user) && !empty($response)) {
            $insert = [
                'openid' => !empty($response['openid']) ? $response['openid'] : '',
                'union_id' => !empty($response['unionid']) ? $response['unionid'] : '',
                'session_key' => !empty($response['session_key']) ? $response['session_key'] : '', //默认7200有效期
                'invite_user_id' => $inviteUserId,
                'activity_type' => $activityType,
                'create_time' => date("Y-m-d H:i:s")
            ];

            $sessionKey = !empty($response['session_key']) ? $response['session_key'] : '';

            //$newWechatId = UserWechatBind::save($insert);
            $newWechatId =UserWechatBind::insertDuplicate($insert, ['session_key' => $sessionKey,'create_time' => date("Y-m-d H:i:s")]);
            if (!$newWechatId) {
                FileLog::error("wechatLogin：登陆创建用户失败", json_encode($params, JSON_UNESCAPED_UNICODE),'','jianghaiming@yidian-inc.com');
                FileLog::error("wechatLogin：登陆创建用户失败--insert", json_encode($insert, JSON_UNESCAPED_UNICODE),'','jianghaiming@yidian-inc.com');
                throw new UserException(['cus' => 2]);
            }

            $user['wechat_id'] = $newWechatId;
            $user['openid'] = $response['openid'];
            $user['session_key'] = $response['session_key'];
        }else{
            if (empty($user)) {
                FileLog::error("wechatLogin：登陆创建用户失败-- 微信response", json_encode($response, JSON_UNESCAPED_UNICODE),'','jianghaiming@yidian-inc.com');
                throw new UserException(['cus' => 2]);
            }

            if (empty($response)){
                FileLog::error("wechatLogin：登陆创建用户失败-- 微信response 获取失败", json_encode($params, JSON_UNESCAPED_UNICODE),'','jianghaiming@yidian-inc.com');
                throw new UserException(['cus' => 2]);
            }
            $insert = [
                'session_key' => !empty($response['session_key']) ? $response['session_key'] : '',
            ];
            $newWechatId = UserWechatBind::save($insert,['openid' => $openid]);
        }
        $user['third_session'] = self::generate3rdSession($openid);
        $redis->set($keyCode, json_encode($user),120);
        return $user;       
    }

    /**
     * 绑定手机号
     * @param $params
     * @return \Api\PhpUtils\Mysql\MysqlBase
     * @throws UserException
     * @throws \App\Exception\custom\CodeSpecialException
     * @throws \App\Exception\custom\InterfaceException
     */
    public static function bindPhone($params)
    {
        $openid = !empty($params['openid']) ? $params['openid'] : '';
        $encryptedData = !empty($params['encryptedData']) ? $params['encryptedData'] : '';
        $iv = !empty($params['iv']) ? $params['iv'] : '';        
        $appid = \Yaf\Registry::get('config')->wechat->appid;
 
        if (!$encryptedData) {
            FileLog::error("bindPhone：encryptedData 为空", json_encode($params, JSON_UNESCAPED_UNICODE),'','jianghaiming@yidian-inc.com');
            throw new UserException(['cus' => 3]);
        }

        if (!$iv) {
            FileLog::error("bindPhone：iv 为空", json_encode($params, JSON_UNESCAPED_UNICODE),'','jianghaiming@yidian-inc.com');
            throw new UserException(['cus' => 4]);
        }

        $userInfo = UserWechatBind::getRecordMaster(['openid' => $openid]);
        $sessionKey = !empty($userInfo['session_key']) ? $userInfo['session_key'] : '';
        $openid = isset($userInfo['openid']) && $userInfo['openid'] ? $userInfo['openid'] : '';
        if (empty($userInfo) || !$sessionKey || !$openid) {
            FileLog::error("bindPhone：userInfo获取失败", json_encode($userInfo, JSON_UNESCAPED_UNICODE),'','jianghaiming@yidian-inc.com');
            throw new UserException(['cus' => 5]);
        }

        //解密
        $decryptData = [];
        $wXBizDataCrypt = new WxBizDataCrypt($appid, $sessionKey);
        $errCode = $wXBizDataCrypt->decryptData($encryptedData, $iv, $decryptData);

        if ($errCode) {
            FileLog::error("bindPhone：解密失败", json_encode($params, JSON_UNESCAPED_UNICODE),'','jianghaiming@yidian-inc.com');
            throw new UserException(['cus' => 6]);
        }

        // 手机号解密失败
        if (empty($decryptData['phoneNumber'])) {
            FileLog::error("bindPhone：手机号解密失败", json_encode($params, JSON_UNESCAPED_UNICODE),'','jianghaiming@yidian-inc.com');
            FileLog::error("bindPhone：手机号解密失败--decryptData", json_encode($decryptData, JSON_UNESCAPED_UNICODE),'','jianghaiming@yidian-inc.com');
            throw new UserException(['cus' => 7]);
        }

        $phoneNumber = strval($decryptData['phoneNumber']);
        //判断是否已
        $user = UserWechatBind::getRecordMaster(['phone' => $phoneNumber]);
        if (!empty($user) &&  $openid != $user['openid']) {
            FileLog::error("bindPhone：该手机号已绑定其他用户不能重复绑定", json_encode($params, JSON_UNESCAPED_UNICODE),'','jianghaiming@yidian-inc.com');
            FileLog::error("bindPhone：该手机号已绑定其他用户不能重复绑定--user", json_encode($user, JSON_UNESCAPED_UNICODE),'','jianghaiming@yidian-inc.com');
            throw new UserException(['cus' => 9]);
        }

        $jwUser = (new JwUser ())->getUserInfo(['mobile' => $phoneNumber]);
        $userId = '';
        if (!empty($jwUser['data'])) {
            $data = $jwUser['data'];
            $userId = !empty($data['userId']) ? $data['userId'] : '';
        }
        //进行绑定
        $update = [
            'phone' => $phoneNumber,
            "update_time" => date("Y-m-d H:i:s"),
            'user_id' => $userId,
        ];
        $bindStatus = UserWechatBind::save($update,['wechat_id' => $userInfo['wechat_id']]);

        if (empty($bindStatus)){
            FileLog::error("bindPhone：绑定手机号保存失败", json_encode($update, JSON_UNESCAPED_UNICODE),'','jianghaiming@yidian-inc.com');
            throw new UserException(['cus' => 12]);
        }

        if (!$phoneNumber) {
            FileLog::error("bindPhone：该手机号已绑定其他用户不能重复绑定--user", json_encode($user, JSON_UNESCAPED_UNICODE),'','jianghaiming@yidian-inc.com');
            throw new UserException(['cus' => 8]);
        }

        $isNewUser =  CommonService::isNewUser(['openid' => $openid]);
        if (!empty($isNewUser) && $isNewUser['is_new_user'] == 1) {
             $userInfo['is_pop_up'] = 1;
        }else{
            $userInfo['is_pop_up'] = 2;
        }

        $userInfo['user_id'] = $userId;
        $userInfo['phone'] = $phoneNumber;
        $userInfo['pop_up_text'] = "";
        return $userInfo;
    }


    public static function userWechatBind($params)
    {
     
        $data['wechat_id[>]'] = 0;

        if (!empty($params['openid'])) {
            $data['openid'] = $params['openid'];
        }

        if (!empty($params['user_id'])) {
            $data['user_id'] = $params['user_id'];
        }

        if (!empty($params['phone'])) {
            $data['phone'] = $params['phone'];
        }
        
        $userList = UserWechatBind::getRecords($data);
        return $userList;
    }


    public static function bindAvatar($params)
    {
        //进行绑定
        $update = [
            "update_time" => date("Y-m-d H:i:s"),
            'user_nick' => !empty($params['user_nick']) ? $params['user_nick'] : '',
            'user_avatar' =>!empty($params['user_avatar']) ? $params['user_avatar'] : '',
            'gender' => !empty($params['gender']) ? $params['gender'] : '',
            'country' => !empty($params['province']) ? $params['province'] : '',
            'province' => !empty($params['province']) ? $params['province'] : '',
            "city" => !empty($params['city']) ? $params['city'] : '',
            "language" => !empty($params['language']) ? $params['language'] : '',
        ];
        $user = UserWechatBind::getRecordMaster(['openid' => $params['openid']]);
        if (empty($user)){
            $update['openid'] = $params['openid'];
            $bindStatus = UserWechatBind::save($update);
        }else{
            $bindStatus = UserWechatBind::save($update,['openid' => $params['openid']]);
        }
        if (!$bindStatus) {
            FileLog::error("bindAvatar：绑定头像失败", json_encode($params, JSON_UNESCAPED_UNICODE),'','jianghaiming@yidian-inc.com');
            FileLog::error("bindAvatar：绑定头像失败--update", json_encode($update, JSON_UNESCAPED_UNICODE),'','jianghaiming@yidian-inc.com');
            throw new UserException(['cus' => 11]);
        }
        return $update;
    }

    private static function generate3rdSession($openid) {
        return md5(mt_rand() . $openid);
    }

}