<?php
/**
+-----------------------------------------------------------------------------------------------------------------------
 * 短信工厂类:发送短信并记录短信发送日志
+-----------------------------------------------------------------------------------------------------------------------
 *
 * PHP version 7
 *
 * @category  App\Sms
 * @package   App\Sms
 * @author    Richer <yangzi1028@163.com>
 * @date      2020年4月23日,10:47:39
 * @copyright 2020-2022 Richer (http://www.Richer.com/)
 * @license   http://www.Richer.com/ License
 * @link      http://www.Richer.com/
 */
namespace App\Sms;

use App\Models\System\SmsLog;
use Exception;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Log;
use Overtrue\EasySms\EasySms;

/**
 * Class Sms
 *
 * @category  App\Sms
 * @package   App\Sms
 * @author    Richer <yangzi1028@163.com>
 * @date      2020年4月23日,10:47:39
 * @copyright 2020-2022 Richer (http://www.Richer.com/)
 * @license   http://www.Richer.com/ License
 * @link      http://www.Richer.com/
 */
class Sms
{
    protected $message = '短信发送成功!';

    protected $easySms = null;

    /**
     * Sms constructor.
     */
    public function __construct()
    {
        $this->easySms = new EasySms(config('sms'));
    }

    /**
     * @return string
     */
    public function getMessage()
    {
        return $this->message;
    }

    /**
     * 发送消息
     *
     * @param string $module  模块
     * @param Model  $model   对象模型
     * @param string $target  发送目标
     * @param string $operate 操作
     *
     * @return bool
     */
    public function pushNotification($module, $model, $target = 'user', $operate = 'warning')
    {

//        \Log::info('福安分发生科技');
//        \Log::info(config('app.open_SMS'));
        // 本地环境以外的环境才进行短信消息推送
        if (request('test') === 'test' || (config('app.env') !== 'local' && config('app.open_SMS'))) {
            $template = Template::getTemplate($module, $model, $target, $operate);
            if (!$template) {
                return false;
            }

            //发送确认消息给用户
            $mobile     = Arr::get($template, 'mobile');
            $params     = Arr::get($template, 'params');
            $content    = Arr::get($template, 'content');
            $type       = Arr::get($template, 'type');

            if ($params) {
                $content = preg_replace_array('/\{s\d+\}+/', $params, $content);
            }

            // 判断是否发送了短信,
//            $log = $model->smsLogs()->where('mobile', $mobile)->where('type', $type)->first();
//            if ($log) {
//                return true;
//            }
            // 发送短信
            $result = $this->send($mobile, $content, $params);
//            \Log::info($result);
            if ($result) {
                //添加日志
                $smsLogs[] = [
                    'user_id'   => optional($model->user)->id,
                    'mobile'    => $mobile,
                    'type'      => $type,
                    'result'    => $result,
                    'body'      => $params,
                ];
                $model->smsLogs()->createMany($smsLogs);
                return true;
            } else {
                return false;
            }
        }
    }

    /**
     * 群发消息
     *
     * @param string $module  模块
     * @param Model  $model   对象模型
     * @param string $target  发送目标
     * @param string $operate 操作
     *
     * @return bool
     */
    public function batchPushNotification($module, $model, $target = 'users', $operate = 'warning')
    {

//        \Log::info('福安分发生科技');
//        \Log::info(config('app.open_SMS'));
        // 本地环境以外的环境才进行短信消息推送
        if (request('test') === 'test' || (config('app.env') !== 'local' && config('app.open_SMS'))) {
            $data       = Template::getContent($module, $model, $target, $operate);
            $mobiles    = Arr::get($data, 'mobiles') ?? [];
            $params     = Arr::get($data, 'params');
            $content    = Arr::get($data, 'content');
            $type       = Arr::get($data, 'type');

            if ($params) {
                $content = preg_replace_array('/\{s\d+\}+/', $params, $content);
            }

            if (empty($mobiles)) {
                return true;
            }

            // 判断是否发送了短信,
            $logs = $model->smsLogs()->whereIn('mobile', $mobiles)->where('type', $type)->all()->pluck('mobile');
            $mobiles = array_diff($mobiles, $logs);
            if (empty($mobiles)) {
                return true;
            }
            // 发送短信
            $phones = implode(",", array_unique($mobiles));
            $result = $this->send($phones, $content, $params);
//            \Log::info($result);
            if ($result) {
                $smsLogs = [];
                $model->$target->map(function ($item) use (
                    &$smsLogs,
                    $type,
                    $result,
                    $params
                ) {
                    $smsLogs[] = [
                        'user_id'   => $item->id,
                        'mobile'    => $item->mobile,
                        'type'      => $type,
                        'result'    => $result,
                        'body'      => $params,
                    ];
                });
                //添加日志
                $model->smsLogs()->createMany($smsLogs);
                return true;
            } else {
                return false;
            }
        }
    }

    /**
     * 发送验证码
     *
     * @param $mobile
     * @param $code
     * @return bool
     */
    public function pushSmsCode($mobile, $code)
    {
        // 发送短信
        return $result = $this->send($mobile, ['code' => $code]);
    }

    /**
     * 发送短信验证码,并返回
     *
     * @param string $mobile 手机号
     * @param array|string $content 发送内容
     * @param array $params
     * @return bool
     */
    public function send($mobile, $content, $params = [])
    {
        if (!$mobile) {
            $this->message = '手机号码为空!';
            return false;
        }

        if (!$content) {
            $this->message = '发送内容为空!';
            return false;
        }

        $data = [
            'content'   => $content,
        ];

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

        // 发送短信
        try {
            // 以下方式兼容所有的短信平台
            $result = $this->easySms->send($mobile, $data);

            // 发送状态
            $status = Arr::first(array_values($result));

            return $status;

        } catch (Exception $e) {
            $exception = $e->getExceptions();
            $gateway = head(config('sms.default.gateways'));
            $messenger = Arr::get($exception, $gateway);
            $message = $messenger->getMessage();
            $error = json_decode($message, true);

            if ($error) {
                Log::info('发送短信错误信息', $error);
                Log::info('发送手机号:' . $mobile);
                Log::info('发送短信内容:' . json_encode($content));
                $this->message = Arr::get($error, 'errorMsg');
            } else {
                $this->message = $message;
            }
            return false;
        }
    }
}