<?php
/**
 * @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
 * @license https://opensource.org/licenses/GPL-2.0
 * @link https://www.koogua.com
 */

namespace App\Services;

use Phalcon\Logger\Adapter\File as FileLogger;
abstract class Smser extends Service
{

    /**
     * @var array
     */
    protected $settings;

    /**
     * @var FileLogger
     */
    protected $logger;

    public function __construct()
    {
        $this->settings = $this->getSettings('sms');

        $this->logger = $this->getLogger('sms');
    }

    /**
     * 发送短信
     *
     * @param string $phoneNumber
     * @param string $templateId
     * @param array $params
     * @return bool
     */
    public function send($phoneNumber, $templateId, $params)
    {
        $requestUrl = 'https://api.ihuyi.com/sms/Submit.json';
        $fields = array(
            'account' => $this->settings['ihuyi_api_id'],
            'password' => $this->settings['ihuyi_api_key'],
            'mobile' => $phoneNumber,
            'content' => $this->templateReplace($templateId, $params),
        );

        $requestBody = $this->buildRequestBody($fields);
        $this->logger->debug('Send Message Request: POST ' . $requestUrl);

        $response = $this->postForm($requestUrl, $requestBody);
        if ($response === false || $response === '') {
            $this->logger->error('Send Message Failed: empty or network response');
            return false;
        }

        $payload = json_decode($response, true);
        if (!is_array($payload) || !array_key_exists('code', $payload)) {
            $this->logger->error('Send Message Failed: malformed JSON response');
            return false;
        }

        $code = (int) $payload['code'];
        $message = isset($payload['msg']) ? (string) $payload['msg'] : '';
        $messageId = isset($payload['smsid']) ? (string) $payload['smsid'] : '';
        $result = ($code === 2);

        if ($result) {
            $this->logger->debug('Send Message Success: smsid=' . $messageId);
        } else {
            $this->logger->error(sprintf('Send Message Failed: code=%d, msg=%s', $code, $message));
        }

        return $result;
    }

    /**
     * 按 RFC 3986 生成 application/x-www-form-urlencoded 请求体。
     *
     * @param array $fields
     * @return string
     */
    protected function buildRequestBody($fields)
    {
        return http_build_query($fields, '', '&', PHP_QUERY_RFC3986);
    }

    /**
     * 向互亿无线发送 UTF-8 表单请求。
     *
     * @param string $url
     * @param string $requestBody
     * @return string|false
     */
    protected function postForm($url, $requestBody)
    {
        $ch = curl_init();
        curl_setopt_array($ch, array(
            CURLOPT_URL => $url,
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => $requestBody,
            CURLOPT_HTTPHEADER => array('Content-Type: application/x-www-form-urlencoded'),
            CURLOPT_SSL_VERIFYPEER => true,
            CURLOPT_SSL_VERIFYHOST => 2,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => 10,
        ));

        $response = curl_exec($ch);
        if ($response === false) {
            $this->logger->error('Send Message Transport Failed: ' . curl_error($ch));
        }
        curl_close($ch);

        return $response;
    }

    /**
     * 模板占位符替换 {1}{2}{3}
     * @param string $template 模板
     * @param array $params 参数数组
     * @return string
     */
    protected function templateReplace($template, $params)
    {
        $search = [];
        foreach ($params as $k => $_) {
            $search[] = '{'.($k+1).'}';
        }
        return str_replace($search, $params, $template);
    }

    protected function formatTemplateParams($params)
    {
        if (!empty($params)) {
            $params = array_map(function ($value) {
                return strval($value);
            }, $params);
        }

        return $params;
    }

    protected function getTemplateId($code)
    {
        $template = json_decode($this->settings['template'], true);

        return $template[$code]['id'] ?? null;
    }

}
