<?php

namespace Kylin\Sms\Gateways;

use Kylin\Sms\Exceptions\GatewayException;

/**
 * 短信宝网关
 * 
 * 支持短信宝服务的发送功能
 * 短信宝是国内老牌的短信服务平台，提供稳定可靠的短信发送服务
 * 
 * 文档：https://www.smsbao.com/kaihu.html
 * 
 * @package Kylin\Sms\Gateways
 */
class SmsbaoGateway extends BaseGateway
{
    /**
     * 网关名称标识
     */
    protected static string $name = 'smsbao';

    /**
     * API 请求地址
     */
    protected const API_URL = 'https://api.smsbao.com/sms';

    /**
     * 短信宝用户名
     * 
     * @var string
     */
    protected string $username;

    /**
     * 短信宝密码
     * 
     * @var string
     */
    protected string $password;

    /**
     * 短信签名
     * 
     * @var string
     */
    protected string $signName;

    /**
     * 状态码映射表
     * 
     * 短信宝 API 返回的状态码对应的中文描述
     * 
     * @var array
     */
    protected static array $statusMessages = [
        '0' => '发送成功',
        '-1' => '参数不全',
        '-2' => '服务器空间不支持,请确认支持curl或者fsocket，联系您的空间商解决或者更换空间',
        '30' => '密码错误',
        '40' => '账号不存在',
        '41' => '余额不足',
        '42' => '账户已过期',
        '43' => 'IP地址限制',
        '50' => '内容含有敏感词',
        '51' => '手机号码不正确',
    ];

    /**
     * 构造函数
     * 
     * 初始化短信宝网关配置
     * 
     * @param array $config 网关配置数组
     */
    public function __construct(array $config = [])
    {
        parent::__construct($config);
        $this->username = $config['username'] ?? '';
        $this->password = $config['password'] ?? '';
        $this->signName = $config['sign_name'] ?? '';
    }

    /**
     * 发送短信
     * 
     * 发送普通短信内容到指定手机号
     * 
     * @param string $to 接收手机号
     * @param string $content 短信内容
     * @param array $data 附加数据
     * @return array 发送结果
     */
    public function send(string $to, string $content, array $data = []): array
    {
        $signName = $data['sign_name'] ?? $this->signName;
        $text = '【' . $signName . '】' . $content;

        $params = [
            'u' => $this->username,
            'p' => md5($this->password),
            'm' => $this->formatPhone($to),
            'c' => $text,
        ];

        try {
            $response = $this->request('GET', self::API_URL . '?' . http_build_query($params));
            return $this->parseResponse($response);
        } catch (GatewayException $e) {
            return $this->buildErrorResponse($e->getMessage(), $e->getCode(), $e->getContext());
        }
    }

    /**
     * 发送模板短信
     * 
     * 使用模板内容发送短信，模板参数将被替换
     * 
     * @param string $to 接收手机号
     * @param string $templateId 模板内容（短信宝使用模板内容而非模板 ID）
     * @param array $params 模板参数
     * @return array 发送结果
     */
    public function sendTemplate(string $to, string $templateId, array $params = []): array
    {
        $content = $templateId;
        foreach ($params as $key => $value) {
            $content = str_replace('{' . $key . '}', $value, $content);
        }
        return $this->send($to, $content);
    }

    /**
     * 批量发送短信
     * 
     * 向多个手机号发送相同内容的短信
     * 
     * @param array $recipients 接收手机号数组
     * @param string $content 短信内容
     * @param array $data 附加数据
     * @return array 发送结果
     */
    public function sendBatch(array $recipients, string $content, array $data = []): array
    {
        $signName = $data['sign_name'] ?? $this->signName;
        $text = '【' . $signName . '】' . $content;

        $params = [
            'u' => $this->username,
            'p' => md5($this->password),
            'm' => implode(',', array_map([$this, 'formatPhone'], $recipients)),
            'c' => $text,
        ];

        try {
            $response = $this->request('GET', self::API_URL . '?' . http_build_query($params));
            return $this->parseResponse($response);
        } catch (GatewayException $e) {
            return $this->buildErrorResponse($e->getMessage(), $e->getCode(), $e->getContext());
        }
    }

    /**
     * 解析响应结果
     * 
     * 将短信宝 API 响应转换为标准化的结果格式
     * 
     * @param array $response API 响应
     * @return array 标准化的响应结果
     */
    protected function parseResponse(array $response): array
    {
        $code = (string)($response['code'] ?? $response['status'] ?? '-1');
        if ($code === '0') {
            return $this->buildSuccessResponse([]);
        }

        return $this->buildErrorResponse(
            self::$statusMessages[$code] ?? '发送失败',
            $code,
            $response
        );
    }
}
