<?php

namespace app\home\service;

use app\home\controller\User;
use app\home\validate\LoginValidate;
use app\model\AdminModel;
use app\model\CountryModel;
use app\model\UserModel;
use app\utility\Jwt;
use app\utility\SendSms;
use app\utility\UnqId;
use Psr\SimpleCache\InvalidArgumentException;
use think\exception\ValidateException;
use think\facade\Cache;
use think\facade\Queue;
use think\queue\Job;
use GeoIp2\Database\Reader;

class LoginService extends BaseHomeService
{

    /**
     * 发送邮件
     * @param $param
     * @return array
     * @throws InvalidArgumentException
     */
    public function sendEmail($param): array
    {
        try {
            // 防止重复操作 单个ip 3秒钟内只能请求一次
            $ip = $this->getClientRealIp();

            // 参数校验
            validate(LoginValidate::class)->scene('sendEmail')->check($param);

            $param['email'] = trim($param['email']);
            // 邮箱类型校验 去除国内邮箱
            if ($this->checkForbidEmail($param['email'])) {
                return $this->toData('100300', 'The email is not supported.', []);
            }

            // 每天获取code 次数限制
            $sendCodeKey = 'USER:SEND_CODE_NUM:' . $ip;
            if ($this->checkGetNoTradeCodeNum($sendCodeKey)) {
                return $this->toData('100300', 'The maximum number of attempts for today has been exceeded. Please try again tomorrow.', []);
            }

            // 获取发送的邮件内容
            $content = $this->getEmailContent();
            $content['email'] = $param['email'];

            // 将发送邮件任务添加到异步队列
            $queuename = 'app\home\job\SendEmail';
            Queue::push($queuename, $content, 'sendEmail');

            // 邮件code存到缓存(未登录操作共用)
            $key = 'DB:USER:UNLOGIN:EMAIL_CODE:' . $param['email'];
            $this->insertCodeToCache($key, $content['code'], 300);

            // 记录已经发送的code次数
            $this->updateHadGetCodeNumCache($sendCodeKey);

            // 返回结果
            return $this->toData('0', 'Email sent successfully. Please check your inbox.', []);

        } catch (ValidateException $validateException) {
            // 参数校验失败 异常类
            $message = $validateException->getError();
            return $this->toData('100400', $message);
        } catch (\Exception $exception) {
            // 异常情况
            return $this->toData('100500', 'The system is busy.', [$exception->getMessage()]);
        }

    }

    /**
     * @desc 邮箱注册用户
     * @param $param
     * @return array
     * @throws InvalidArgumentException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function registerEmail($param): array
    {
        try {
            // 获取客户端ip
            $ip = $this->getClientRealIp();

            $param['invite_code'] = $param['invite_code'] ?? '';
            $param['agent_code'] = $param['agent_code'] ?? '';

            // 邮件注册参数校验
            validate(LoginValidate::class)->scene('emailRegister')->check($param);

            // 判断注册数量 ip每天可注册数量
            $ipCanRegisterNumPerIpPerDay = 'USER:REGISTER:' . $ip;
            if ($this->checkRegisterLimit($ipCanRegisterNumPerIpPerDay)) {
                return $this->toData('100300', 'The maximum number of attempts for today has been exceeded. Please try again tomorrow.', []);
            }

            // 验证验证码
            $emailKey = 'DB:USER:UNLOGIN:EMAIL_CODE:' . $param['email'];
            if (!$this->checkCode($emailKey, $param['email_code'])) {
                //注册验证码
                $reg_key = "USER:REG:CODE";
                if (!$this->checkCode($reg_key, $param['email_code'])) {
                    return $this->toData('100300', 'The verification code is incorrect.', []);
                } else {
                    $code = random_int(1000, 9999);
                    $this->insertCodeToCache($reg_key, $code, 300);
                }
            }

            $email = $param['email'];
            $inviteCode = trim($param['invite_code']);
            $agentCode = trim($param['agent_code']);

            // 邮箱是否已经存在
            $emailExists = UserModel::checkEmailExists($email);
            if ($emailExists) {
                return $this->toData('100300', 'The email has already been registered.', []);
            }

            // 判断邀请人是否存在
            $agentId = 0;
            $parentUserId = 0;
            if (!empty($inviteCode)) {
                $agentId = AdminModel::getIdByInviteCode($inviteCode);
                if ($agentId <= 0) {
                    $parentUserId = $this->getParentIdByInviteCode($inviteCode);
                    if ($parentUserId <= 0) {
                        return $this->toData('100400', 'The invitation code is invalid.', []);
                    }
                }
            }

            // 判断代理人是否存在
            if (!empty($agentCode) || $agentId > 0) {
                if ($agentId == 0) {
                    $agentId = AdminModel::getIdByInviteCode($agentCode);
                    if ($agentId <= 0) {
                        return $this->toData('100400', 'The invitation code is invalid.', []);
                    }
                }
            } else {
                // 是否必须填写有效的邀请码
                $inviteCodeIsRequired = env("REG_USER.INVITE_CODE_REQUIRED");
                if ($parentUserId <= 0 && $inviteCodeIsRequired >= 1) {
                    return $this->toData('100400', 'The invitation code is invalid.', []);
                }
            }

            // 入库
            $userNo = $this->getUniqUserNo();
            $salt = env('ENCRYPT.SALT');
            $password = (new UnqId())->encryptPassword($param['password'], $salt);
            $userInviteCode = $this->getUniqInviteCode();
            // 需要开启事务
            \think\facade\Db::transaction(function () use ($email, $userNo, $userInviteCode, $parentUserId, $password, $ip, $salt, $agentId) {
                // 生成用户数据
                $userId = UserModel::emailRegister($email, $userNo, $userInviteCode, $parentUserId, $password, $ip, $salt, 1, $agentId);
                // 生成钱包地址
                (new UserService())->doRegInitUserInfo($userId, $parentUserId);
            });
            // 删除缓存
            $this->delCache($emailKey);
            // 累加已经注册的个数
            $this->updateHadRegisterNumCache($ipCanRegisterNumPerIpPerDay);
            return $this->toData('0', 'Registration Successful.', []);
        } catch (ValidateException $validateException) {
            // 参数校验失败 异常类
            $message = $validateException->getError();
            return $this->toData('100400', $message);
        } catch (\Exception $exception) {
            trace('【注册错误】提交数据:'.json_encode($param), 'error');
            trace('【注册错误】'.$exception->getMessage(), 'error');
            return $this->toData('100500', 'The system is busy.', [$exception->getMessage(), $exception->getTrace()]);
        }
    }

    /**
     * @desc 登陆业务处理接口
     * @param array $param
     * @return array
     */
    public function loginEmail(array $param): array
    {
        try {
            // 参数校验 邮箱 密码
            validate(LoginValidate::class)->scene('emailLogin')->check($param);

            $param['email'] = trim($param['email']);
            // 查找邮箱
            $userId = UserModel::getUserIdByEmail($param['email']);
            if ($userId <= 0) {
                return $this->toData('100300', 'The user does not exist.', []);
            }

            // 查找用户信息
            $user = UserModel::getFieldsByUserId('invite_code,user_id,user_no,nick_name,is_real,login_password,salt', $userId);
            if (empty($user)) {
                return $this->toData('100300', 'Incorrect account or password.', []);
            }

            // 校验密码
            $checkPasswordBool = (new UnqId())->checkPassword($param['password'], $user['login_password'], $user['salt']);
            if (!$checkPasswordBool) {
                return $this->toData('100300', 'Incorrect account or password.', []);
            }

            // 生成token
            $token = (new Jwt())->getToken($userId, env('ENCRYPT.SALT'));
            if (empty($token)) {
                return $this->toData('100300', 'The system is busy.', []);
            }

            // 用户登陆之后需要进行的操作 异步完成
            Queue::push('app\home\job\LoginDone', ['userId' => $userId,
                'fields' => [
                    'last_login_time' => date('Y-m-d H:i:s'),
                    'ip' => $this->getClientRealIp(),
                    'device' => $param['device'],

                ]
            ], 'loginDone');

            // 将token存致缓存 覆盖新的缓存 实现单设备登陆
            $this->setUserTokenCache($token, $userId);

            // 用户登记关系
            (new UserService())->getUserLevel($userId);

            // 返回结果以及用户信息
            return $this->toData('0', 'Request successful.', [
                'userId' => $userId,
                'userNo' => $user['user_no'],
                'nickName' => $user['nick_name'],
                'inviteCode' => $user['invite_code'],
                'isReal' => $user['is_real'],
                'logo' => env('USER.DEFAULT_HEAD_IMG_PATH'),
                'token' => $token,
            ]);
        } catch (ValidateException $validateException) {
            // 参数校验失败 异常类
            $message = $validateException->getError();
            return $this->toData('100400', $message);
        } catch (InvalidArgumentException $invalidArgumentException) {
            return $this->toData('100400', 'The system is busy. Please try again later.', []);
        } catch (\Exception $exception) {
            return $this->toData('100500', 'The system is busy.', []);
        }
    }

    /**
     * @desc未登陆获取短信验证码
     * @param array $param
     * @return array
     * @throws InvalidArgumentException
     */
    public function sendSms(array $param): array
    {
        try {
            // 防止重复操作 单个ip 3秒钟内只能请求一次
            $ip = $this->getClientRealIp();

            // 参数校验
            validate(LoginValidate::class)->scene('sendSms')->check($param);

            $param['nation'] = trim($param['nation']);
            $param['phone'] = trim($param['phone']);
            // 去除国内手机号
            if ($this->checkForbidNation($param['nation'])) {
                return $this->toData('100300', 'Unsupported country or region.', []);
            }

            // 判断国家码是否有效
            $nationExists = CountryModel::checkCodeExists($param['nation']);
            if (!$nationExists) {
                return $this->toData('100300', 'Unsupported country or region.', []);
            }

            // 发送次数校验 - 号码
            $phoneSendCodeKey = 'USER:PHONE_SEND_CODE_NUM:' . $param['nation'].':'.$param['phone'];
            if ($this->checkGetNoTradeCodeNumPhone($phoneSendCodeKey)) {
                return $this->toData('100300', 'No worries. Please feel free to reach out again tomorrow.', []);
            }

            // 发送次数校验 - ip
            $ipSendCodeKey = 'USER:IP_SEND_CODE_NUM:' . $ip;
            if ($this->checkGetNoTradeCodeNum($ipSendCodeKey)) {
                return $this->toData('100300', 'No worries. Please feel free to reach out again tomorrow.', []);
            }

            // 获取发送内容
            $content = $this->getSmsContent();
            $mobile = $param['nation'] . $param['phone'];
            $content['mobile'] = $mobile;

            // 异步发送
            $queuename = 'app\home\job\SendSms';
            Queue::push($queuename, $content, 'sendSms');

            // 短信code存到缓存(未登录操作共用)
            $key = 'DB:USER:UNLOGIN:SMS_CODE:' . $mobile;
            $this->insertCodeToCache($key, $content['code'], 300);

            // 累加已经获取的次数
            $this->updateHadGetCodeNumCache($phoneSendCodeKey);
            $this->updateHadGetCodeNumCache($ipSendCodeKey);

            // 返回结果
            return $this->toData('0', 'The message has been sent. Please check your inbox.', []);
        } catch (ValidateException $validateException) {
            // 参数校验失败 异常类
            $message = $validateException->getError();
            return $this->toData('100400', $message);
        } catch (\Exception $exception) {
            trace('【注册错误】提交数据:'.json_encode($param), 'error');
            trace('【注册错误】'.$exception->getMessage(), 'error');
            return $this->toData('100500', 'The system is busy.', [$exception->getMessage()]);
        }
    }

    /**
     * @desc 短信注册
     * @param array $param
     * @return array
     * @throws InvalidArgumentException
     */
    public function registerSms(array $param): array
    {
        try {
            // 防止重复操作
            $ip = $this->getClientRealIp();

            $param['invite_code'] = $param['invite_code'] ?? '';
            $param['agent_code'] = $param['agent_code'] ?? '';

            // 短信注册参数校验
            validate(LoginValidate::class)->scene('smsRegister')->check($param);

            // 判断注册数量 ip每天可注册数量
            $ipCanRegisterNumPerIpPerDay = 'USER:REGISTER:' . $ip;
            $this->checkRegisterLimit($ipCanRegisterNumPerIpPerDay);

            // 校验验证码
            $mobile = $param['nation'] . $param['phone'];
            $smsKey = 'DB:USER:UNLOGIN:SMS_CODE:' . $mobile;
            if (!$this->checkCode($smsKey, $param['sms_code'])) {
                $reg_key = "USER:REG:CODE";
                //注册验证码
                if (!$this->checkCode($reg_key, $param['sms_code'])) {
                    return $this->toData('100300', 'The verification code is incorrect.', []);
                } else {
                    $code = random_int(1000, 9999);
                    $this->insertCodeToCache($reg_key, $code, 300);
                }
            }

            // 手机号是否已经存在
            $phoneExists = UserModel::checkPhoneExists($param['phone']);
            if ($phoneExists) {
                return $this->toData('100300', 'The phone number has already been registered.', []);
            }

            // 邀请人
            $inviteCode = trim($param['invite_code']);
            $agentCode = trim($param['agent_code']);
            $parentUserId = 0;
            $agentId = 0;
            if (!empty($inviteCode)) {
                $agentId = AdminModel::getIdByInviteCode($inviteCode);
                if ($agentId <= 0) {
                    $parentUserId = $this->getParentIdByInviteCode($inviteCode);
                    if ($parentUserId <= 0) {
                        return $this->toData('100400', 'The invitation code is invalid.', []);
                    }
                }
            }

            // 判断代理人是否存在
            if (!empty($agentCode) || $agentId > 0) {
                if ($agentId == 0) {
                    $agentId = AdminModel::getIdByInviteCode($agentCode);
                    if ($agentId <= 0) {
                        return $this->toData('100400', 'The invitation code is invalid.', []);
                    }
                }
            } else {
                // 是否必须填写有效的邀请码
                $inviteCodeIsRequired = env("REG_USER.INVITE_CODE_REQUIRED");
                if ($parentUserId <= 0 && $inviteCodeIsRequired >= 1) {
                    return $this->toData('100400', 'The invitation code is invalid.', []);
                }
            }

            // 入库
            $userNo = $this->getUniqUserNo();
            $salt = env('ENCRYPT.SALT');
            $password = (new UnqId())->encryptPassword($param['password'], $salt);
            $userInviteCode = $this->getUniqInviteCode();

            // 需要开启事务
            \think\facade\Db::transaction(function () use ($param, $userNo, $userInviteCode, $parentUserId, $password, $ip, $salt, $agentId) {
                // 生成用户数据
                $userId = UserModel::phoneRegister($param['nation'], $param['phone'], $userNo, $userInviteCode, $parentUserId, $password, $ip, $salt, 1, $agentId);
                // 生成钱包地址
                (new UserService())->doRegInitUserInfo($userId, $parentUserId);
            });

            // 删除缓存
            $this->delCache($smsKey);

            // 更新注册个数
            $this->updateHadRegisterNumCache($ipCanRegisterNumPerIpPerDay);

            return $this->toData('0', 'Registration Successful.', []);
        } catch (ValidateException $validateException) {
            // 参数校验失败 异常类
            $message = $validateException->getError();
            return $this->toData('100400', $message);
        } catch (\Exception $exception) {
            return $this->toData('100500', 'The system is busy.', [$exception->getMessage(), $exception->getTrace()]);
        }
    }

    /**
     * @desc 短信验证码登陆
     * @param array $param
     * @return array
     * @throws InvalidArgumentException
     */
    public function loginSms(array $param): array
    {
        try {
            // 邮件注册参数校验
            validate(LoginValidate::class)->scene('smsLogin')->check($param);

            $param['nation'] = trim($param['nation']);
            $param['phone'] = trim($param['phone']);

            // 验证短信验证码
            $mobile = $param['nation'] . $param['phone'];
            $smsKey = 'DB:USER:UNLOGIN:SMS_CODE:' . $mobile;
            if (!$this->checkCode($smsKey, $param['sms_code'])) {
                return $this->toData('100300', 'The verification code is incorrect.', []);
            };

            // 查找手机号
            $userId = UserModel::getUserIdByNationAndPhone($param['nation'], $param['phone']);
            if ($userId <= 0) {
                return $this->toData('100300', 'The user does not exist.', []);
            }

            // 查找用户信息
            $user = UserModel::getFieldsByUserId('invite_code,user_id,user_no,nick_name,is_real,login_password,salt', $userId);
            if (empty($user)) {
                return $this->toData('100300', 'Incorrect account or password.', []);
            }

            // 生成token
            $token = (new Jwt())->getToken($userId, env('ENCRYPT.SALT'));
            if (empty($token)) {
                return $this->toData('100300', 'The system is busy. Please try again later.', []);
            }

            // 用户登陆之后需要进行的操作 异步完成
            Queue::push('app\home\job\LoginDone', ['userId' => $userId,
                'fields' => [
                    'last_login_time' => date('Y-m-d H:i:s'),
                    'ip' => $this->getClientRealIp(),
                    'device' => $param['device'],
                ]
            ], 'loginDone');

            // 将token存致缓存 覆盖新的缓存 实现单设备登陆
            $this->setUserTokenCache($token, $userId);

            // 用户登记关系
            (new UserService())->getUserLevel($userId);

            // 返回结果以及用户信息
            return $this->toData('0', 'Request successful.', [
                'userId' => $userId,
                'userNo' => $user['user_no'],
                'nickName' => $user['nick_name'],
                'isReal' => $user['is_real'],
                'inviteCode' => $user['invite_code'],
                'logo' => env('USER.DEFAULT_HEAD_IMG_PATH'),
                'token' => $token,
            ]);
        } catch (ValidateException $validateException) {
            // 参数校验失败 异常类
            $message = $validateException->getError();
            return $this->toData('100400', $message);
        } catch (\Exception $exception) {
            return $this->toData('100500', 'The system is busy. Please try again later.', [$exception->getMessage(), $exception->getTrace()]);
        }
    }

    /**
     * @desc 忘记密码 根据邮箱设置密码
     * @param array $param
     * @return array
     * @throws InvalidArgumentException
     */
    public function resetPasswordByEmail(array $param): array
    {
        try {
            // 邮件注册参数校验
            validate(LoginValidate::class)->scene('emailForget')->check($param);

            // 验证码
            $emailKey = 'DB:USER:UNLOGIN:EMAIL_CODE:' . $param['email'];
            if (!$this->checkCode($emailKey, $param['email_code'])) {
                return $this->toData('100300', 'The verification code is incorrect', []);
            }

            // 查找邮箱
            $userId = UserModel::getUserIdByEmail($param['email']);
            if ($userId <= 0) {
                return $this->toData('100300', 'The user does not exist.', []);
            }

            // 修改密码
            $salt = env('ENCRYPT.SALT');
            $password = (new UnqId())->encryptPassword($param['password'], $salt);
            UserModel::updatePassword($password, $salt, $userId);

            // 删除缓存
            $this->delCache($emailKey);

            return $this->toData('0', 'Modification successful.', []);
        } catch (ValidateException $validateException) {
            // 参数校验失败 异常类
            $message = $validateException->getError();
            return $this->toData('100400', $message);
        } catch (\Exception $exception) {
            return $this->toData('100500', 'The system is busy. Please try again later.', [$exception->getMessage(), $exception->getTrace()]);
        }
    }

    /**
     * @desc 忘记密码 根据短信设置密码
     * @param array $param
     * @return array
     * @throws InvalidArgumentException
     */
    public function resetPasswordBySms(array $param): array
    {
        try {
            // 邮件注册参数校验
            validate(LoginValidate::class)->scene('smsForget')->check($param);

            // 判断验证码
            $mobile = $param['nation'] . $param['phone'];
            $smsKey = 'DB:USER:UNLOGIN:SMS_CODE:' . $mobile;
            if (!$this->checkCode($smsKey, $param['sms_code'])) {
                return $this->toData('100300', 'The verification code is incorrect', []);
            }

            // 查找用户
            $userId = UserModel::getUserIdByNationAndPhone($param['nation'], $param['phone']);
            if ($userId <= 0) {
                return $this->toData('100300', 'The user does not exist.', []);
            }

            // 修改密码
            $salt = env('ENCRYPT.SALT');
            $password = (new UnqId())->encryptPassword($param['password'], $salt);
            UserModel::updatePassword($password, $salt, $userId);

            // 删除缓存
            $this->delCache($smsKey);

            return $this->toData('0', 'Modification successful.', []);
        } catch (ValidateException $validateException) {
            // 参数校验失败 异常类
            $message = $validateException->getError();
            return $this->toData('100400', $message);
        } catch (\Exception $exception) {
            return $this->toData('100500', 'The system is busy. Please try again later.', [$exception->getMessage(), $exception->getTrace()]);
        }
    }


    /**
     * @desc 手机号 密码登陆
     * @param $param
     * @return array
     */
    public function phoneLogin($param): array
    {
        try {
            // 参数校验
            validate(LoginValidate::class)->scene('smsPasswordLogin')->check($param);

            // 获取用户
            $userId = UserModel::getUserIdByNationAndPhone($param['nation'], $param['phone']);
            if ($userId <= 0) {
                return $this->toData('100300', 'Incorrect account or password.1', []);
            }

            $info = UserModel::getFieldsByUserId('invite_code,is_real,nick_name,user_no,user_id,login_password,salt', $userId);
            if (empty($info)) {
                return $this->toData('100300', 'Incorrect account or password.2', []);
            }

            // 校验密码
            $checkPasswordBool = (new UnqId())->checkPassword($param['password'], $info['login_password'], $info['salt']);
            if (!$checkPasswordBool) {
                return $this->toData('100300', 'Incorrect account or password.3', []);
            }

            // 生成token
            $token = (new Jwt())->getToken($userId, env('ENCRYPT.SALT'));
            if (empty($token)) {
                return $this->toData('100400', 'The system is busy. Please try again later.', []);
            }

            // 用户登陆之后需要进行的操作 异步完成
            Queue::push('app\home\job\LoginDone', ['userId' => $userId,
                'fields' => [
                    'last_login_time' => date('Y-m-d H:i:s'),
                    'ip' => $this->getClientRealIp(),
                    'device' => $param['device'],
                ]
            ], 'loginDone');

            // 将token存致缓存 覆盖新的缓存 实现单设备登陆
            $this->setUserTokenCache($token, $userId);

            // 用户登记关系
            (new UserService())->getUserLevel($userId);

            // 返回结果以及用户信息
            return $this->toData('0', 'Request successful.', [
                'userId' => $userId,
                'userNo' => $info['user_no'],
                'nickName' => $info['nick_name'],
                'isReal' => $info['is_real'],
                'inviteCode' => $info['invite_code'],
                'logo' => env('USER.DEFAULT_HEAD_IMG_PATH'),
                'token' => $token,
            ]);
        } catch (ValidateException $validateException) {
            // 参数校验失败 异常类
            $message = $validateException->getError();
            return $this->toData('100400', $message);
        } catch (\Exception $exception) {
            return $this->toData('100500', 'The system is busy. Please try again later.', []);
        }
    }

    public function autoLogin($param): array
    {
        try {
            $login_token=$param['login_token'];
            $tokenUserKey = 'AUTO:TOKEN:'.$login_token;
            $userId = Cache::store('redis')->get($tokenUserKey);
            if(empty($userId) || $userId <= 0){
                return $this->toData('100300', 'Incorrect token', []);
            }
            $info = UserModel::getFieldsByUserId('invite_code,is_real,nick_name,user_no,user_id,login_password,salt', $userId);
            if (empty($info)) {
                return $this->toData('100300', 'Incorrect account or password.2', []);
            }
             // 生成token
            $token = (new Jwt())->getToken($userId, env('ENCRYPT.SALT'));
            if (empty($token)) {
                return $this->toData('100400', 'The system is busy. Please try again later.', []);
            }

            // 将token存致缓存 覆盖新的缓存 实现单设备登陆
            $this->setUserTokenCache($token, $userId);

            // 用户登记关系
            (new UserService())->getUserLevel($userId);

            // 返回结果以及用户信息
            return $this->toData('0', 'Request successful.', [
                'userId' => $userId,
                'userNo' => $info['user_no'],
                'nickName' => $info['nick_name'],
                'isReal' => $info['is_real'],
                'inviteCode' => $info['invite_code'],
                'logo' => env('USER.DEFAULT_HEAD_IMG_PATH'),
                'token' => $token,
            ]);
        } catch (ValidateException $validateException) {
            // 参数校验失败 异常类
            $message = $validateException->getError();
            return $this->toData('100400', $message);
        } catch (\Exception $exception) {
            return $this->toData('100500', 'The system is busy. Please try again later.', []);
        }

    }
    public function getIP(): array
    {
        $ip=$this->getClientRealIp();
        $countryDb = base_path().'GeoLite2-Country.mmdb';
        $cityDb = base_path().'GeoLite2-City.mmdb';
        $countryReader = new Reader($countryDb);
        $cityReader = new Reader($cityDb);
        try{
            $countryNames = $countryReader->country($ip)->country->names;
            $cityNames = $cityReader->city($ip)->city->names;
            return $this->toData('0', 'Request successful.', [
                'country' => $countryNames['zh-CN'],
                'city' => $cityNames['zh-CN'],
                'ip'=>$ip
            ]);
        }catch (\Exception $exception){
            return $this->toData('0', 'Request successful.', [
                'country' => '未知',
                'city' =>'未知',
                'ip'=>$ip
            ]);
        }
    }
}