<?php
/**
 *  ╔═══════════════════════════════════════════════════╗
 *  ║                                                   ║
 *  ║     ██╗  ██╗   █████╗    ██████╗                  ║
 *  ║     ██║  ██║  ██╔══██╗  ██╔═══██╗                 ║
 *  ║     ███████║  ███████║  ██║   ██║                 ║
 *  ║     ██╔══██║  ██╔══██║  ██║   ██║                 ║
 *  ║     ██║  ██║  ██║  ██║  ╚██████╔╝   SNS           ║
 *  ║                                                   ║    
 *  ║                                                   ║    
 *  ║     © 2023 HaoSNS™ All Rights Reserved            ║
 *  ║     官方网站: https://www.haosns.com                *
 *  ║     本代码由赣州乐易网络科技有限公司®提供             *
 *  ║                                                    *
 *  ║   未经授权禁止复制、传播或用于其他商业目的            *
 *  ║                                                   ║
 *  ╚═══════════════════════════════════════════════════╝
 */


namespace app\api\controller;
use app\common\enum\NoticeEnum;
use app\common\enum\UserTerminalEnum;
use app\api\{
    validate\LoginValidate,
    validate\WechatLoginValidate,
    logic\LoginLogic
};

use app\common\service\ConfigService;
use EasyWeChat\MiniApp\Application;

class Login extends BaseShopController
{
    public array $notNeedLogin = ['account','wechatQrLoginCallback','captchaEmail','registerEmail','logout', 'config', 'captcha', 'third','appWechat','getWechatAuthUrl','wechatCallback'];

    /**
     * @notes 账号密码/手机号密码/手机号验证码登录
     * @return \think\response\Json
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function account()
    {
        $params = (new LoginValidate())->post()->goCheck('account');
        $result = (new LoginLogic())->login($params);
        if ($result === false) {
            return $this->fail(LoginLogic::getError());
        }
        // 记录登录日志
        \app\common\model\UserLog::create([
            'user_id'=>$result['user_id'],
            'ip'=>$this->request->ip(),
            'remark'=>'账号登录',
            'code'=>'login',
            'text'=>json_encode($_SERVER,true),
        ]);
        
        return $this->data($result);
    }

    /**
     * 获取微信公众号登录URL
     */
    public function getWechatAuthUrl() 
    {
        // 开放平台相关信息
        // ConfigService::set('official','open_app_id', $params['open_app_id'] ?? '');
        // ConfigService::set('official','open_app_secret',$params['open_app_secret'] ?? '');

        // 拍优品服务号
        // wx11b567c8a10fb82e
        // bea4aa8ec884b2ebf4d341f30b628a73

        // $app_id = \app\common\service\ConfigService::get('official', 'app_id', '');
        // if(empty($$app_id)){
        //     return show(config('status.error'),'未配置公众号appid');
        // }

        // 如果启用了开放平台则走开放平台的ConfigService::set('official','use_open', $params['use_open'] ?? '')==1;
        // 开放平台相关信息
        // ConfigService::set('official','open_app_id', $params['open_app_id'] ?? '');
        // ConfigService::set('official','open_app_secret',$params['open_app_secret'] ?? '');

        $app_id = 'wxb8dbdb61e7d7a857';
        $canllback = $this->request->domain().'/api/login/wechatCallback';

        // 'scope' => 'snsapi_login', // 网站应用固定为snsapi_login
        // 'scope' => 'snsapi_userinfo', // 获取用户信息（含UnionID）有开放平台

        $state = uniqid();
        $url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid={$app_id}&redirect_uri={$canllback}&response_type=code&scope=snsapi_userinfo&state={$state}&connect_redirect=1#wechat_redirect";

        return show(config('status.success'),'',['url'=>$url]);

    }



    /**
     * 微信公众号登录回调
     * 通过code换取access_token和用户信息
     */
    public function wechatCallback() 
    {
        $params = $this->request->get();

        $code = $params['code'];

        // dd($params['code']);

        // 1. 获取access_token
        // $tokenUrl = 'https://api.weixin.qq.com/sns/oauth2/access_token';
        // $tokenParams = [
        //     'appid' => $this->appId,
        //     'secret' => $this->appSecret,
        //     'code' => $code,
        //     'grant_type' => 'authorization_code'
        // ];
        
        // $tokenResult = $this->httpGet($tokenUrl . '?' . http_build_query($tokenParams));


        // $app_id = \app\common\service\ConfigService::get('official', 'app_id', '');
        // $secret = \app\common\service\ConfigService::get('official', 'app_secret', '');
        $app_id = 'wxb8dbdb61e7d7a857';
        $secret = 'cb0d1e781bf0911d304d2a5148c106aa';
        
        try {
            // 构造请求URL
            $url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=$app_id&secret=$secret&code=$code&grant_type=authorization_code";
            $response = file_get_contents($url);
            $result = json_decode($response, true);
            $auth = [
                'openid' => $result['openid'] ?? '',
                'unionid' => $result['unionid'] ?? '',
                'access_token'=>$result['access_token']??'',
            ];
        } catch (\Exception $e) {
            dd($e->getMessage());
        }

        if (isset($auth['errcode'])) {
            dd($auth['errmsg']);
        }
        
        $third = $this->createAuth(['platform' => 'weixin_open', 'unionid' => $auth['unionid'], 'openid' => $auth['openid'], 'terminal' => 2]);
        if ($third) {
            try{
                // 新用户修改头像
                if($third['is_new_user']==1){
                    $info_url = "https://api.weixin.qq.com/sns/userinfo?access_token={$auth['access_token']}&openid={$auth['openid']}";
                    $info_response = file_get_contents($info_url);
                    $user_info = json_decode($info_response, true);
                    \app\common\model\User::where('id',$third['user_id'])->update([
                        "avatar"=>$user_info['headimgurl'],
                        "nickname"=>$user_info['nickname'],
                    ]);
                }
            }catch(\Exception $e){
                // dd($e->getMessage());
            }

            // 记录登录日志
            \app\common\model\UserLog::create([
                'user_id'=>$third['user_id'],
                'ip'=>$this->request->ip(),
                'remark'=>'微信登录',
                'code'=>'login',
                'text'=>json_encode($_SERVER,true),
            ]);

            // echo 33;die;
            // $url = '/mobile/pages/login/loginCheck?token='.$third['token'];
            $url = '/haosns-login-wxtoken.html?token='.$third['token'];
            header("Location:$url");die;
            // return show(1, 'user_login', $third);
        }
        dd($third);

    }


    /**
     * 包含微信开放平台
     * 通过公众号code获取用户信息（含UnionID）
     */
    // public function getUserInfoByCode($code) {
    //     // 1. 通过公众号code换取access_token和openid
    //     $tokenUrl = 'https://api.weixin.qq.com/sns/oauth2/access_token';
    //     $tokenParams = [
    //         'appid' => $this->mpAppId,
    //         'secret' => $this->mpAppSecret,
    //         'code' => $code,
    //         'grant_type' => 'authorization_code'
    //     ];
        
    //     $tokenResult = $this->httpGet($tokenUrl . '?' . http_build_query($tokenParams));
    //     $tokenData = json_decode($tokenResult, true);
        
    //     if (isset($tokenData['errcode'])) {
    //         return ['error' => '获取access_token失败: ' . $tokenData['errmsg']];
    //     }
        
    //     // 2. 获取用户信息（若公众号已绑定开放平台，将包含UnionID）
    //     $userInfoUrl = 'https://api.weixin.qq.com/sns/userinfo';
    //     $userParams = [
    //         'access_token' => $tokenData['access_token'],
    //         'openid' => $tokenData['openid'],
    //         'lang' => 'zh_CN'
    //     ];
        
    //     $userResult = $this->httpGet($userInfoUrl . '?' . http_build_query($userParams));
    //     $userData = json_decode($userResult, true);
        
    //     if (isset($userData['errcode'])) {
    //         return ['error' => '获取用户信息失败: ' . $userData['errmsg']];
    //     }
        
    //     return $userData;
    // }

    /**
     * 发送邮箱验证码
     */
    public function captchaEmail()
    {
        $code = mt_rand(1000, 9999);

        $email = input('email');
        $type = input('type');
        
        \think\facade\Cache::set('email_'.$type.'_'.$email,$code,1000);

        $result = \app\common\service\EmailService::send($email, '验证码', '验证码：'.$code);
        if($result===true){
            return show(1,'发送成功');
        }
        return show(1,'发送失败');
    }

    /**
     * 邮箱注册账号
     */
    public function registerEmail()
    {
        $params = $this->request->post();

        $code = \think\facade\Cache::get('email_'.$params['type'].'_'.$params['email']);

        if($code!=$params['code']){
            return show(0,'验证码不对');
        }

        $user = \app\common\model\User::where('email',$params['email'])->find();
        if ($user) {
            return \show(0,'邮箱已被注册');
        }

        $passwordSalt = generateRandomString();
        $password = create_password($params['password'], $passwordSalt);

        $data=[
            'password'=>$password,
            'salt'=>$passwordSalt,
            'email'=>$params['email'],
        ];
        
        $res = \app\common\model\User::create($data);

        if(!$res){
            return show(0,'注册失败');
        }

        // 记录登录日志
        \app\common\model\UserLog::create([
            'user_id'=>$res->id,
            'ip'=>$this->request->ip(),
            'remark'=>'邮箱注册',
            'code'=>'register',
            'text'=>json_encode($_SERVER,true),
        ]);
        
        return show(1,'注册成功');

    }

    /**
     * @notes 发送验证码-登录
     */
    public function captcha()
    {
        $params = (new LoginValidate())->post()->goCheck('captcha');
        $code = mt_rand(1000, 9999);
        $result = event('Notice', [
            'scene_id' => NoticeEnum::LOGIN_CAPTCHA,
            'params' => [
                'mobile' => $params['mobile'],
                'code' => $code,
            ]
        ]);
        if ($result[0] === true) {
            return $this->success('发送成功');
        }
        return $this->fail($result[0], [], 0, 1);
    }

    /**
     * @notes 退出登录
     * @return \think\response\Json
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function logout()
    {
        //退出登录情况特殊，只有成功的情况，也不需要token验证
        (new LoginLogic())->logout($this->userInfo);

        // 记录登录日志
        \app\common\model\UserLog::create([
            'user_id'=>$this->userId,
            'ip'=>$this->request->ip(),
            'remark'=>'退出登录',
            'code'=>'logout',
            'text'=>json_encode($_SERVER,true),
        ]);

        return $this->success();

    }



    /**
     * @notes 更新用户头像昵称
     * @return \think\response\Json
     * @throws \think\db\exception\DbException
     * @author lgp
     * @date 2023/2/2 6:36 下午
     */
    public function updateUser()
    {
        $params = (new WechatLoginValidate())->post()->goCheck("updateUser");
        LoginLogic::updateUser($params, $this->userId);

        return $this->success('操作成功', [], 1, 1);
    }



    /**
     * @notes 小程序绑定微信
     * @return \think\response\Json
     * @author lgp
     * @date 2022/7/17 10:56
     */
    public function mnpAuthLogin()
    {
        $params = (new WechatLoginValidate())->post()->goCheck("wechatAuth");
        $params['user_id'] = $this->userId;
        $result = (new LoginLogic())->mnpAuthLogin($params);
        if ($result === false) {
            return $this->fail(LoginLogic::getError());
        }
        return $this->success('绑定成功', [], 1, 1);
    }

    /**
     * 第三方登录
     * @ApiMethod   (POST)
     * @param string $platform 平台名称
     * @param string $code     Code码
     */
    public function third()
    {
        //设置过滤方法
        $this->request->filter(['strip_tags']);
        if ($this->request->isPost()) {

            // 获取登录配置
            // $config = get_addon_config('wanlshop');
            // 获取前端参数
            $post = $this->request->post();
            $platform = $post['platform'];

            // 开始登录
            // dd($post);
            switch ($platform) {
                // 微信小程序登录
                case 'mp_weixin':
                    $wx_config = \app\adminapi\logic\wechat\MiniProgramSettingLogic::getConfig();
                    // dd($wx_config);
                    $config = [
                        'app_id' => $wx_config['app_id'],
                        'secret' => $wx_config['app_secret'],
                    ];

                    try {

                        // 通过code获取openid
                        $app = new Application($config);
                        $response = $app->getUtils()->codeToSession($post['login_code']);
                        $auth = [
                            'openid' => $response['openid'] ?? '',
                            'session_key' => $response['session_key'] ?? '',
                            'unionid' => $response['unionid'] ?? '',
                        ];

                    } catch (\Exception $e) {
                        dd($e->getMessage());
                    }
                    if (isset($auth['errcode'])) {
                        dd($auth['errmsg']);
                    }
                    // dd($post['terminal']);
                    $third = $this->createAuth(['platform' => 'weixin_open', 'unionid' => $auth['unionid'], 'openid' => $auth['openid'], 'terminal' => $post['terminal']]);
                    if ($third) {
                        return show(1, 'user', $third);
                    }
                    return show(0, 'error');
            }
        }
    }


    /**
     * @notes 生成一条授权记录
     * @param $response
     * @return bool
     * @throws Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @author lgp
     * @date 2022/5/17 16:18
     */
    private function createAuth($response)
    {

        //先检查unionid是否有记录
        $isAuth = \app\common\model\UserAuth::where('unionid', '=', $response['unionid'])->findOrEmpty();
        $is_new_user = 0;
        if (!$isAuth->isEmpty()) {
            // throw new \Exception('该微信已经绑定，请切换微信授权登录');
            // 该微信已绑定返回用户信息
            // dd($isAuth);
            $user = \app\common\model\User::where('id', $isAuth->user_id)->find();
            // dd($user);
            try {
                $ip = $_SERVER['REMOTE_ADDR'];
                $ip_address = '';
                // 初始化，指定QQWry.dat文件路径
                $qqwry = new \app\common\service\QQWry('qqwry.dat');
                // 查询IP地理位置
                $location = $qqwry->getLocation($ip);
                $ip_address = $location['country'];
                $user->ip = $ip;
                $user->ip_address = $ip_address;

                $user->save();

            } catch (\Exception $e) {
                // echo "发生错误: " . $e->getMessage();
            }
            
        } else {

            // 新用户
            $is_new_user = 1;
            // 创建新账号
            $params = [
                'register_source' => '',
                'mobile' => '',
                'account' => time() . rand(0, 99),
                'invite_code' => '',
            ];
            $user = \app\api\logic\RegisterLogic::register($params);

            // //如果没有授权，直接生成一条微信授权记录
            \app\common\model\UserAuth::create([
                'user_id' => $user->id,
                'openid' => $response['openid'],
                'unionid' => $response['unionid'] ?? '',
                'terminal' => $response['terminal'],
            ]);

        }

        //设置token
        $userInfo = \app\api\service\UserTokenService::setToken($user->id, $response['terminal']);

        //返回登录信息
        $avatar = $user->avatar ? $user->avatar : \think\facade\Config::get('project.default_image.user_avatar');
        $avatar = \app\common\service\FileService::getFileUrl($avatar);
        $data = [
            'user_id' => $user->id,
            'nickname' => $userInfo['nickname'],
            'sn' => $userInfo['sn'],
            'mobile' => $userInfo['mobile'],
            'avatar' => $avatar,
            'token' => $userInfo['token'],
            'is_new_user'=>$is_new_user,//为空数组新用户
        ];
        return $data;
    }


    /**
     * app微信登录
     */
    public function appWechat($code)
    {
        try {
            $app_id = \app\common\service\ConfigService::get('open_platform', 'app_id', '');
            $secret = \app\common\service\ConfigService::get('open_platform', 'app_secret', '');
            // 构造请求URL
            $url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=$app_id&secret=$secret&code=$code&grant_type=authorization_code";
            $response = file_get_contents($url);
            $result = json_decode($response, true);
            $auth = [
                'openid' => $result['openid'] ?? '',
                'unionid' => $result['unionid'] ?? '',
                'access_token'=>$result['access_token']??'',
            ];
        } catch (\Exception $e) {
            dd($e->getMessage());
        }
        if (isset($auth['errcode'])) {
            dd($auth['errmsg']);
        }
        
        $third = $this->createAuth(['platform' => 'weixin_open', 'unionid' => $auth['unionid'], 'openid' => $auth['openid'], 'terminal' => $this->terminal]);
        if ($third) {
            try{
                // 新用户修改头像
                if($third['is_new_user']==1){
                    $info_url = "https://api.weixin.qq.com/sns/userinfo?access_token={$auth['access_token']}&openid={$auth['openid']}";
                    $info_response = file_get_contents($info_url);
                    $user_info = json_decode($info_response, true);
                    \app\common\model\User::where('id',$third['user_id'])->update([
                        "avatar"=>$user_info['headimgurl'],
                        "nickname"=>$user_info['nickname'],
                    ]);
                }
            }catch(\Exception $e){
                // dd($e->getMessage());
            }

            // 记录登录日志
            \app\common\model\UserLog::create([
                'user_id'=>$this->userId,
                'ip'=>$this->request->ip(),
                'remark'=>'APP微信登录',
                'code'=>'login',
                'text'=>json_encode($_SERVER,true),
            ]);

            return show(1, 'user_login', $third);
        }
        dd($third);
    }


    // 微信网页扫码登录回调
    public function wechatQrLoginCallback()
    {

        // 微信开放平台配置
        $appid =  \app\common\service\ConfigService::get('webapp', 'app_id', '');
        $appsecret =  \app\common\service\ConfigService::get('webapp', 'app_secret', '');

        // 1. 接收微信回调参数
        $code = $_GET['code'] ?? '';
        $state = $_GET['state'] ?? '';

        // 校验参数（防CSRF/非法请求）
        if (empty($code) || empty($state)) {
            die("登录失败：缺少必要参数");
        }

        // 2. 用code换取access_token和UnionID
        $tokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" . $appid . "&secret=" . $appsecret . "&code=" . $code . "&grant_type=authorization_code";
        $tokenRes = \file_get_contents($tokenUrl);
        $tokenData = json_decode($tokenRes, true);

        // 检查接口调用是否失败
        if (isset($tokenData['errcode']) && $tokenData['errcode'] != 0) {
            die("获取Token失败：" . $tokenData['errmsg']);
        }

        $accessToken = $tokenData['access_token']; // 接口调用凭证
        $openid = $tokenData['openid']; // 网页应用内唯一标识
        $unionid = $tokenData['unionid'] ?? ''; // 开放平台下唯一标识（多端通用）

        // 3. （可选）获取用户昵称、头像等基本信息
        $userInfoUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=" . $accessToken . "&openid=" . $openid . "&lang=zh_CN";
        $userInfoRes = file_get_contents($userInfoUrl);
        $userInfo = json_decode($userInfoRes, true);

        if (isset($userInfo['errcode']) && $userInfo['errcode'] != 0) {
            return show(0,"获取用户信息失败：" . $userInfo['errmsg']);
        }

        $auth = [
            'unionid' => $unionid,
            'openid' => $openid,
            'nickname' => $userInfo['nickname'],
            'avatar' => $userInfo['headimgurl'],
            'login_time' => date('Y-m-d H:i:s')
        ];

        // dd($user);

        $third = $this->createAuth(['platform' => 'weixin_open', 'unionid' => $auth['unionid'], 'openid' => $auth['openid'], 'terminal' => 4]);
        if ($third) {
            try{
                // 新用户修改头像
                if($third['is_new_user']==1){
                    $info_url = "https://api.weixin.qq.com/sns/userinfo?access_token={$auth['access_token']}&openid={$auth['openid']}";
                    $info_response = file_get_contents($info_url);
                    $user_info = json_decode($info_response, true);
                    \app\common\model\User::where('id',$third['user_id'])->update([
                        "avatar"=>$user_info['headimgurl'],
                        "nickname"=>$user_info['nickname'],
                    ]);
                }
            }catch(\Exception $e){
                echo '登录失败：'.$e->getMessage();
            }
            // return show(1, 'user_login', $third);
            // 5. 跳转回前端首页（或登录成功页）

            // 记录登录日志
            \app\common\model\UserLog::create([
                'user_id'=>$this->userId,
                'ip'=>$this->request->ip(),
                'remark'=>'网页微信登录',
                'code'=>'login',
                'text'=>json_encode($_SERVER,true),
            ]);

            header("Location: https://" . $_SERVER['HTTP_HOST'] . "/handler_login.html?token=".$third['token']);
        }

        echo "登录失败";
        exit;

     
    }
}