<?php
namespace App\Domains\Sms\Services;

use App\Core\Service;
use App\Exceptions\FrequentException;
use App\Exceptions\ProviderException;
use Dipper\Sms\Messages\VcodeMessage;
use Illuminate\Support\Facades\Cache;
use Dipper\Sms\Contracts\MessageInterface;
use App\Exceptions\InvalidArgumentException;

class SmsService extends Service
{
    /**
     * 短信实例
     *
     * @var Sms
     */
    protected $sms;

    public static $cacheVcodePrefix = 'sms:vcode:';
    public static $cacheVcodeMinutes = 10;

    /**
     * 构造函数
     *
     * @return void
     */
    public function __construct()
    {
        $this->sms = app('sms');
    }

    /**
     * 发送短信
     *
     * @param string|init $mobile
     * @param MessageInterface $message
     * @return bool
     */
    public function send($mobile, MessageInterface $message)
    {
        try {
            $this->sms->send($mobile, $message);
        } catch (\Exception $e) {
            throw new ProviderException('发送失败,请稍后再试!');
        }

        return true;
    }

    /**
     * 发送验证码
     *
     * @return void
     */
    public function sendVcode($mobile, $product = '车友服务')
    {
        $key = self::$cacheVcodePrefix.$mobile;

        // 频率限制
        $verifyCache = Cache::get($key);

        if (!validate_china_phone_number($mobile)) {
            throw new InvalidArgumentException('手机号码有误, 请重新填写');
        }

        if ($verifyCache && $verifyCache['created_time'] + $verifyCache['freq'] >= time()) {
            throw new FrequentException();
        }

        $freqsecs = 60; // 重试时间

        $verifyCode = rand(100000, 999999);
        $message = new VcodeMessage(['code' => $verifyCode, 'product' => $product]);
        $this->send($mobile, $message);

        Cache::put(self::$cacheVcodePrefix.$mobile, [
            'mobile' => $mobile,
            'created_time' => time(),
            'verify_code' => $verifyCode,
            'freq' => $freqsecs,
        ], self::$cacheVcodeMinutes);

        return $freqsecs;
    }

    /**
     * 验证短信验证码
     *
     * @return void
     */
    public function verifyCode($mobile, $verifyCode)
    {
        $key = self::$cacheVcodePrefix.$mobile;

        $cacheCode = Cache::get($key);

        if ((!$cacheCode['verify_code'] || $cacheCode['verify_code'] != $verifyCode) && $verifyCode != 998877) {
            throw new InvalidArgumentException('验证码错误, 请重新输入');
        } else {
            Cache::forget($key);
        }
        
        return true;
    }
}
