<h1>SMS API – <code>SMS</code> Class</h1>
<p>
    The <strong>SMS</strong> class sends text messages through a fully modular driver system.
    Built‑in international providers (Twilio, Vonage, Plivo, etc.) and five top Nepali providers
    are included. A Generic HTTP driver allows any custom gateway, and users can
    <strong>create their own named providers from the SMS Settings UI</strong> without writing code.
</p>

<h2>Contents</h2>
<ul>
    <li><a href="#architecture">Architecture &amp; Design</a></li>
    <li><a href="#quickstart">Quick Start</a></li>
    <li><a href="#builtin">Built‑in Providers</a></li>
    <li><a href="#nepal">Nepali Providers</a></li>
    <li><a href="#custom">Creating Custom Providers (UI)</a></li>
    <li><a href="#http">Generic HTTP Driver</a></li>
    <li><a href="#send">Sending SMS</a></li>
    <li><a href="#extend">Extending with PHP Drivers</a></li>
    <li><a href="#troubleshooting">Troubleshooting</a></li>
</ul>

<!-- =========================================== -->
<h2 id="architecture">Architecture &amp; Design</h2>
<p>
    The SMS system follows a <strong>driver pattern</strong>. Every provider is a single PHP class
    implementing the <code>SmsDriver</code> interface, stored in <code>plugins/SmsDrivers/</code>.
    The core <code>SMS</code> class scans this folder, reads each driver, and builds a registry
    that the Misc module's SMS Settings tab uses to populate the provider dropdown.
</p>
<ul>
    <li><strong>Zero hardcoding</strong> – drop a new PHP file into the folder and it appears instantly.</li>
    <li><strong>UI‑driven custom providers</strong> – non‑developers can add their own gateways via a simple form (Generic HTTP driver under the hood).</li>
    <li><strong>All configuration stored per project</strong> in <code>project.json</code>.</li>
</ul>

<!-- =========================================== -->
<h2 id="quickstart">Quick Start</h2>
<pre><code>use PpPhp\Core\SMS;

// 1. Configure (usually done via Misc → SMS Settings, or programmatically)
SMS::SetConfig([
    'provider'   => 'twilio',
    'accountSid' => 'AC...',
    'authToken'  => 'abc...',
    'from'       => '+1234567890',
]);

// 2. Send
$result = SMS::Send('+9779812345678', 'Hello from pp-php!');
if ($result['success']) {
    echo 'Sent!';
} else {
    echo 'Error: ' . $result['error'];
}</code></pre>

<!-- =========================================== -->
<h2 id="builtin">Built‑in International Providers</h2>
<table>
<tr><th>Provider</th><th>Required Fields</th><th>Notes</th></tr>
<tr><td>Twilio</td><td>accountSid, authToken, from</td><td>Trial accounts can only send to verified numbers.</td></tr>
<tr><td>Vonage (Nexmo)</td><td>apiKey, apiSecret, from</td><td>Supports alphanumeric sender IDs.</td></tr>
<tr><td>MessageBird</td><td>accessKey, from</td><td>Create access key in Developers section.</td></tr>
<tr><td>Plivo</td><td>authId, authToken, from</td><td>Tiered pricing; strong alternative to Twilio.</td></tr>
<tr><td>Sinch</td><td>servicePlanId, bearerToken, from</td><td>Choose region for base URL.</td></tr>
<tr><td>Infobip</td><td>apiKey, baseUrl, from</td><td>Base URL found in Infobip portal.</td></tr>
<tr><td>ClickSend</td><td>username, apiKey</td><td>From is optional; uses shared numbers if blank.</td></tr>
<tr><td>Generic HTTP</td><td>url, method, toParam, msgParam, fromParam</td><td>Works with any gateway accepting HTTP requests.</td></tr>
</table>

<!-- =========================================== -->
<h2 id="nepal">Nepali Providers</h2>
<table>
<tr><th>Provider</th><th>Required Fields</th><th>Endpoint</th></tr>
<tr><td>Sparrow SMS</td><td>token, identity, from</td><td>api.sparrowsms.com/v2/sms/</td></tr>
<tr><td>Aakash SMS</td><td>token, from</td><td>aakashsms.com/admin/public/sms/v3/send</td></tr>
</table>
<p>More Nepali providers can be added by dropping a PHP driver into <code>plugins/SmsDrivers/</code>.</p>

<!-- =========================================== -->
<h2 id="custom">Creating Custom Providers (UI)</h2>
<p>
    In the <strong>Misc → SMS Settings</strong> tab, click <strong>Add Custom Provider</strong>.
    Fill in:
</p>
<ul>
    <li><strong>Provider Key</strong> – a unique ID (e.g., <code>mygateway</code>)</li>
    <li><strong>Display Label</strong> – shown in the dropdown</li>
    <li><strong>API URL</strong> – the gateway's endpoint</li>
    <li><strong>Method</strong> – POST or GET</li>
    <li><strong>Parameter names</strong> for recipient, message, and sender</li>
    <li><strong>Extra params</strong> – any additional key=value pairs required by the gateway (comma separated)</li>
</ul>
<p>
    After saving, the new provider appears in the dropdown and works like any built‑in driver.
    All settings are stored in <code>project.json</code>.
</p>

<h3>Example: Creating a Custom Provider for "BulkSMS"</h3>
<ol>
    <li>Click <strong>Add Custom Provider</strong>.</li>
    <li>Key: <code>bulksms</code></li>
    <li>Label: <code>BulkSMS Gateway</code></li>
    <li>API URL: <code>https://bulksms.example.com/api/v1/send</code></li>
    <li>Method: POST</li>
    <li>to param: <code>recipient</code></li>
    <li>message param: <code>content</code></li>
    <li>from param: <code>sender</code></li>
    <li>Extra params: <code>api_key=MY_API_KEY,type=text</code></li>
    <li>Click <strong>Save</strong>.</li>
</ol>
<p>
    Now select "BulkSMS Gateway" from the provider dropdown, fill in the required fields
    (like <code>from</code>), and send a test SMS.
</p>

<!-- =========================================== -->
<h2 id="http">Generic HTTP Driver</h2>
<p>
    The <strong>Generic HTTP</strong> driver allows any SMS gateway that accepts HTTP requests.
    Use it directly from the SMS Settings tab (select "Generic HTTP") or programmatically:
</p>
<pre><code>SMS::SetConfig([
    'provider'     => 'http',
    'url'          => 'https://sms.example.com/api/send',
    'method'       => 'POST',
    'toParam'      => 'phone',
    'msgParam'     => 'text',
    'fromParam'    => 'sender',
    'extraParams'  => 'api_key=abc123,priority=high',
    'from'         => 'MyApp',
]);

$result = SMS::Send('+9779812345678', 'Your OTP is 123456');</code></pre>

<!-- =========================================== -->
<h2 id="send">Sending SMS</h2>
<p>The <code>SMS::Send($to, $message)</code> method returns an associative array:</p>
<pre><code>// Success
['success' => true]

// Failure
['success' => false, 'error' => 'Description of the error']</code></pre>

<h3>Example: Sending with a custom provider configured via the UI</h3>
<pre><code>// The UI already saved this config. In your code, just load the project state.
$state = ProjectState::load('my-project');
$smsConfig = $state['misc']['sms'] ?? [];
SMS::SetConfig($smsConfig);

$result = SMS::Send('+9779812345678', 'Hello!');
if ($result['success']) {
    echo 'OK';
} else {
    echo $result['error'];
}</code></pre>

<!-- =========================================== -->
<h2 id="extend">Extending with PHP Drivers</h2>
<p>Create a new file in <code>plugins/SmsDrivers/</code> (e.g., <code>MyProvider.php</code>) implementing the <code>SmsDriver</code> interface:</p>
<pre><code>&lt;?php
declare(strict_types=1);
namespace PpPhp\Plugins\SmsDrivers;
use PpPhp\Core\SmsDriver;

class MyProvider implements SmsDriver
{
    public function label(): string { return 'My SMS Provider'; }
    public function helpText(): string { return 'Enter your API credentials.'; }
    public function requiredFields(): array {
        return ['apiKey' => 'API Key', 'from' => 'Sender ID'];
    }

    public function send(string $to, string $message, array $config): array {
        $apiKey = $config['apiKey'] ?? '';
        $from   = $config['from']   ?? '';
        if (empty($apiKey) || empty($from)) {
            return ['success' => false, 'error' => 'API Key and Sender ID are required.'];
        }

        $url  = 'https://api.myprovider.com/send';
        $data = http_build_query(['key' => $apiKey, 'to' => $to, 'from' => $from, 'msg' => $message]);

        // cURL logic (copy from any existing driver)
        $ch = curl_init(); /* ... */ curl_close($ch);
        return ['success' => true];
    }
}
</code></pre>
<p>Save the file, refresh the Misc → SMS Settings page, and your provider appears.</p>

<!-- =========================================== -->
<h2 id="troubleshooting">Troubleshooting</h2>
<ul>
    <li><strong>"No SMS provider selected"</strong> – select a provider in the Misc module's SMS tab.</li>
    <li><strong>"Driver not found for provider 'X'"</strong> – the PHP driver file is missing or has a syntax error. Check <code>plugins/SmsDrivers/</code>.</li>
    <li><strong>"HTTP 401 / 403"</strong> – check your API key, token, or credentials.</li>
    <li><strong>"cURL error"</strong> – ensure your server allows outbound HTTPS connections.</li>
    <li><strong>Twilio trial accounts</strong> – only verified numbers can receive SMS.</li>
    <li><strong>Custom provider not working</strong> – verify the API URL and parameter names match exactly what the gateway expects.</li>
</ul>

<hr>
<h3>🔗 Related Help Topics</h3>
<p>
    <a href="Email" class="btn btn-sm btn-outline-primary me-1">Email API</a>
    <a href="Notification" class="btn btn-sm btn-outline-primary">Notification API</a>
</p>