<?php

namespace Kylin\Sms\Messages;

/**
 * 短信消息类
 * 
 * 用于构建短信消息的值对象，支持内容短信和模板短信
 * 提供流式接口，便于链式调用
 * 
 * 示例：
 * ```php
 * // 内容短信
 * $message = SmsMessage::create()
 *     ->content('您的验证码是123456')
 *     ->signName('签名');
 * 
 * // 模板短信
 * $message = SmsMessage::create()
 *     ->template('SMS_123456', ['code' => '123456'])
 *     ->gateway('aliyun');
 * ```
 * 
 * @package Kylin\Sms\Messages
 */
class SmsMessage
{
    /**
     * 短信内容
     * 
     * 用于内容短信模式，直接发送文本内容
     * 
     * @var string|null
     */
    protected ?string $content = null;

    /**
     * 模板 ID
     * 
     * 用于模板短信模式，指定短信平台的模板编号
     * 
     * @var string|null
     */
    protected ?string $templateId = null;

    /**
     * 模板参数
     * 
     * 用于填充模板中的变量，键值对形式
     * 
     * @var array
     */
    protected array $templateParams = [];

    /**
     * 附加数据
     * 
     * 其他需要传递给网关的附加信息
     * 
     * @var array
     */
    protected array $data = [];

    /**
     * 指定网关
     * 
     * 发送时使用的短信网关名称，为 null 时使用默认网关
     * 
     * @var string|null
     */
    protected ?string $gateway = null;

    /**
     * 短信签名
     * 
     * 短信签名名称，部分平台需要
     * 
     * @var string|null
     */
    protected ?string $signName = null;

    /**
     * 创建短信消息实例
     * 
     * 静态工厂方法，便于快速创建消息实例
     * 
     * @return self 消息实例
     */
    public static function create(): self
    {
        return new self();
    }

    /**
     * 设置短信内容
     * 
     * 用于内容短信模式，设置要发送的文本内容
     * 
     * @param string $content 短信内容
     * @return self 支持链式调用
     */
    public function content(string $content): self
    {
        $this->content = $content;
        return $this;
    }

    /**
     * 获取短信内容
     * 
     * @return string|null 短信内容
     */
    public function getContent(): ?string
    {
        return $this->content;
    }

    /**
     * 设置模板短信
     * 
     * 用于模板短信模式，设置模板 ID 和参数
     * 
     * @param string $templateId 模板 ID
     * @param array $params 模板参数，默认为空数组
     * @return self 支持链式调用
     */
    public function template(string $templateId, array $params = []): self
    {
        $this->templateId = $templateId;
        $this->templateParams = $params;
        return $this;
    }

    /**
     * 获取模板 ID
     * 
     * @return string|null 模板 ID
     */
    public function getTemplateId(): ?string
    {
        return $this->templateId;
    }

    /**
     * 获取模板参数
     * 
     * @return array 模板参数数组
     */
    public function getTemplateParams(): array
    {
        return $this->templateParams;
    }

    /**
     * 检查是否为模板短信
     * 
     * @return bool 是模板短信返回 true，否则返回 false
     */
    public function hasTemplate(): bool
    {
        return !empty($this->templateId);
    }

    /**
     * 设置附加数据
     * 
     * 合并附加数据到现有数据中
     * 
     * @param array $data 附加数据
     * @return self 支持链式调用
     */
    public function data(array $data): self
    {
        $this->data = array_merge($this->data, $data);
        return $this;
    }

    /**
     * 获取所有数据
     * 
     * 返回包含签名、模板信息的完整数据数组
     * 
     * @return array 数据数组
     */
    public function getData(): array
    {
        $data = $this->data;

        if ($this->signName) {
            $data['sign_name'] = $this->signName;
        }

        if ($this->templateId) {
            $data['template_code'] = $this->templateId;
            $data['template_params'] = $this->templateParams;
        }

        return $data;
    }

    /**
     * 设置网关
     * 
     * 指定发送短信时使用的网关
     * 
     * @param string|null $gateway 网关名称，为 null 时使用默认网关
     * @return self 支持链式调用
     */
    public function gateway(?string $gateway): self
    {
        $this->gateway = $gateway;
        return $this;
    }

    /**
     * 获取网关名称
     * 
     * @return string|null 网关名称
     */
    public function getGateway(): ?string
    {
        return $this->gateway;
    }

    /**
     * 设置短信签名
     * 
     * @param string $signName 签名名称
     * @return self 支持链式调用
     */
    public function signName(string $signName): self
    {
        $this->signName = $signName;
        return $this;
    }

    /**
     * 获取短信签名
     * 
     * @return string|null 签名名称
     */
    public function getSignName(): ?string
    {
        return $this->signName;
    }

    /**
     * 设置验证码内容
     * 
     * 快捷方法，用于生成验证码短信内容
     * 
     * @param string $code 验证码
     * @param int $expireMinutes 有效期（分钟），默认为 5 分钟
     * @return self 支持链式调用
     */
    public function withVerificationCode(string $code, int $expireMinutes = 5): self
    {
        return $this->content("您的验证码是{$code}，有效期{$expireMinutes}分钟，请勿泄露给他人。");
    }

    /**
     * 合并模板参数
     * 
     * 将新参数合并到现有模板参数中
     * 
     * @param array $params 模板参数
     * @return self 支持链式调用
     */
    public function withTemplateParams(array $params): self
    {
        $this->templateParams = array_merge($this->templateParams, $params);
        return $this;
    }
}
