<?php

namespace App\Http\Controllers\V1;

use App\Models\User;
use App\Services\Api\ErrorMsgServive;
use App\Services\SmsServer;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Mail;
use App\Models\MailCode;
use Illuminate\Support\Facades\Validator;
use libphonenumber\PhoneNumberUtil;

class SmsController extends Controller
{
    //发送短信验证码
    public function send(Request $request)
    {
        $checkResult = $this->checkMobile($request->mobile);

        if ($checkResult['prefix'] == '-1') { //手机号不合法
            return $this->error('手机号不合法');
        }
        $request->event = $request->event ?: 'login';
        if ($request->event == "forget") {
            if (!User::where(['mobile' => $request->mobile])->first()) {
                return $this->error('手机号未注册');
            }
        }
        $prefix = $checkResult['prefix'];
        $result = SmsServer::send($request->mobile, $request->event, $prefix);
        if (isset($result['error'])) {
            return $this->error('短信发送失败');
        }
        $data = [
            'smsCode' => $result['smsCode'], //注意：实际不适合把验证码返回，主要是开发方便测试，生产环境请变为 ""
            'verifyKey' => $result['verifyKey'],
        ];
        return $this->success($data);
    }


    /**
     * @param $mobile
     * @return array
     * 验证手机号是否合法（支持全球手机号验证）$phoneUtil->parse($mobile, "CN")，两个参数：（要验证的手机号，国家区号）
     * 国际区号映射关系在 vendor\giggsey\libphonenumber-for-php\src\CountryCodeToRegionCodeMap.php
     * 可以 在 PhoneNumberUtil::getInstance() 方法中 点击 CountryCodeToRegionCodeMap::$countryCodeToRegionCodeMap 跳过去
     */
    public static function checkMobile($mobile)
    {
        $phoneUtil = PhoneNumberUtil::getInstance();
        try {
            $cnNumberProto = $phoneUtil->parse($mobile, "CN"); //大陆
            $prefix = '-1';
            if ($isValid_CN = $phoneUtil->isValidNumber($cnNumberProto)) {
                $prefix = '86';
            }
            $checkResult = [
                'prefix' => $prefix
            ];
            return $checkResult;
        } catch (\libphonenumber\NumberParseException $exception) {
            ErrorMsgServive::write($exception, request()->url());
        }
    }


    /**
     发送邮箱验证码
     在 .env 文件配置如下，可测试邮件发送（最好自己申请一个邮箱获取信息）
     MAIL_MAILER=smtp
     MAIL_HOST=ssl://smtp.163.com
     MAIL_PORT=465
     MAIL_USERNAME=18738190585@163.com
     MAIL_PASSWORD=VIBTDHQAYLKJYIGC
     MAIL_ENCRYPTION=
     MAIL_FROM_ADDRESS=18738190585@163.com
     MAIL_FROM_NAME="${APP_NAME}"
     *
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function sendEmailCode(Request $request)
    {
        $email = $request->input('email');

        $validator = Validator::make($request->all(), [
            'email' => 'required|email',
        ]);
        if ($validator->fails()) {
            return $this->error($validator->errors()->first());
        }
        $code = rand(1000, 9999);
        $notice = '本次验证码是' . '【 ' . $code . ' 】 ' . '有效期 5 分钟';
        $subject = '邮箱验证通知';
        try {
            Mail::raw($notice, function ($message) use ($email, $subject) {
                $message->subject($subject);
                $message->to($email);
            });
            $mailCode = new MailCode();
            $mailCode->account = $email;
            $mailCode->code = $code;
            $mailCode->state = 0;
            $mailCode->created_at = date('Y-m-d H:i:s');
            $mailCode->save();
            return $this->success();
        } catch (\Exception $e) {
            return $this->error($e->getMessage());
        }
    }

    //判断邮箱验证码 5分钟有效期 （这不是个API接口：哪里需要就放到哪里验证）
    public static function isEmailCodeRight($email, $code)
    {
        $result = MailCode::query()
            ->where('account', $email)
            ->where('code', $code)
            ->where('state', 0)
            ->where('created_at', '>', Carbon::now()->subMinutes(5))
            ->orderBy('id', 'desc')
            ->first();

        if (!$result) {
            return false;
        }
        $result->state = 1; //验证通过就失效
        $result->save();

        return true;
    }

}
