<?php

namespace App\Modules\Message;

use App\Consts\SysConsts;
use Exception;
use GuzzleHttp\Client;
use Illuminate\Support\Facades\Log;

/**
 * 邮件通知
 */
class MailNotify
{
    /**
     * code
     */
    private $project_code = SysConsts::PROJECT_CODE;
    /**
     * key
     */
    private $project_key = SysConsts::PROJECT_KEY;
    /**
     * 通知地址
     */
    private $url = SysConsts::MESSAGE_NOTIFY_BASE_URI;
    /**
     * 收件人
     */
    private $to_emails;
    /**
     * 抄送
     */
    private $cc_emails;
    /**
     * 主题
     */
    private $subject;
    /**
     * 邮件内容
     */
    private $body;
    /**
     * 邮件附件
     */
    private $attaches;
    /**
     * 时间戳
     */
    private $timestamps;
    /**
     * 通知方式
     */
    private $method;
    /**
     * 请求路由
     */
    private $path;

    public function __construct(array $data)
    {
        $this->to_emails = $data['to_emails'];
        $this->cc_emails = isset($data['cc_emails']) ? $data['cc_emails'] : '';
        $this->subject = $data['subject'];
        $this->body = $data['body'];
        $this->delay_times = isset($data['delay_times']) ? $data['delay_times'] : 0;
        $this->method = 'POST';
        $this->path = 'send_raw_email';
        $this->timestamps = time();
    }

    /**
     * 添加附件
     */
    public function addAttach(string $file_path, string $file_name = '')
    {
        if (!$this->attaches) {
            $this->attaches = [];
        }
        if (!$file_name) {
            preg_match('/([0-9a-zA-Z\x{4e00}-\x{9fa5}]+)\.?\w*$/u', $file_path, $mathes);
            $file_name = $mathes[0];
        }
        $this->attaches[] = ['file_name' => $file_name, 'file_path' => $file_path];
    }

    /**
     * 生成签名
     */
    private function makeSign()
    {
        return md5($this->project_code . $this->timestamps . $this->project_key);
    }

    /**
     * 设置请求参数
     */
    private function setRequestOptions()
    {
        $project_code = $this->project_code;
        $timestamp = $this->timestamps;
        $sign = $this->makeSign();
        $to_email = $this->to_emails;
        $cc_email = $this->cc_emails;
        $subject = $this->subject;
        $body = $this->body;
        $delay_times = $this->delay_times;
        $params = compact('project_code', 'timestamp', 'sign', 'to_email', 'cc_email', 'subject', 'body', 'delay_times');
        if ($this->attaches) {
            $mults = collect($params)->map(function ($item, $k) {
                return ['name' => $k, 'contents' => $item];
            })->all();
            foreach ($this->attaches as $attach) {
                $mults[] = [
                    'name' => str_replace('.', '_', $attach['file_name']),
                    'contents' => fopen(storage_path($attach['file_path']), 'r+'),
                    'filename' => $attach['file_name'],
                ];
            }
            return ['multipart' => $mults];
        } else {
            return ['form_params' => $params];
        }
    }

    /**
     * 发送消息通知
     */
    public function notify()
    {
        $client = new Client(['base_uri' => $this->url, 'timesout' => 10]);
        try {
            $options =  $this->setRequestOptions();
            $response = $client->request($this->method, $this->path, $options);
            $contents = $response->getBody()->getContents();
            if ($contents) {
                $result = json_decode($contents);
                if ($result->code === 0) {
                    return true;
                } else {
                    Log::error('email_notify: ' . $contents);
                }
            } else {
                Log::error('email_notify: no response');
            }
        } catch (Exception $e) {
            Log::error('email_notify: ' . $e->getMessage());
        }
    }
}
