<?php
/**
 * SMS-Bus API Wrapper
 * Docs: https://sms-bus.com
 * Base URL: https://sms-bus.com/api/control
 * Auth: ?token=$token (query param on every request)
 */
class SmsBus {

    private string $token;
    private string $base_url;

    public function __construct(string $token, string $base_url = 'https://sms-bus.com/api/control') {
        $this->token    = $token;
        $this->base_url = rtrim($base_url, '/');
    }

    // ── Core HTTP helper ─────────────────────────────────────────
    // Builds URL as base_url/endpoint?token=&...params
    // Returns ['success'=>bool, 'code'=>int, 'data'=>mixed, 'error'=>string]
    private function request(string $endpoint): array
    {
        $url = $this->base_url . '/' . ltrim($endpoint, '/');

        // Append token if not already present
        if (strpos($url, 'token=') === false) {
            $sep  = (strpos($url, '?') !== false) ? '&' : '?';
            $url .= $sep . 'token=' . urlencode($this->token);
        }

        $ch = curl_init();
        curl_setopt_array($ch, [
            CURLOPT_URL            => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT        => 30,
            CURLOPT_CONNECTTIMEOUT => 15,
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_SSL_VERIFYHOST => 0,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_USERAGENT      => 'SmsBus-PHP/1.0',
        ]);

        $raw  = curl_exec($ch);
        $err  = curl_error($ch);
        $code = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        if ($err) {
            return ['success' => false, 'code' => 0, 'data' => null, 'error' => 'cURL error: ' . $err];
        }
        if ($raw === false || $raw === '') {
            return ['success' => false, 'code' => $code, 'data' => null, 'error' => 'Empty response'];
        }

        $json = json_decode($raw, true);
        if ($json === null) {
            return ['success' => false, 'code' => $code, 'data' => null, 'error' => 'Invalid JSON: ' . substr($raw, 0, 200)];
        }

        $api_code = (int)($json['code'] ?? 0);

        // Error codes
        if ($api_code === 401) {
            return ['success' => false, 'code' => $api_code, 'data' => null, 'error' => 'Invalid token (401)'];
        }
        if ($api_code === 50002) {
            return ['success' => false, 'code' => $api_code, 'data' => null, 'error' => 'No number available (50002)'];
        }
        if ($api_code === 50201) {
            return ['success' => false, 'code' => $api_code, 'data' => null, 'error' => 'Insufficient balance (50201)'];
        }
        if ($api_code === 50101) {
            return ['success' => true, 'code' => $api_code, 'data' => null, 'error' => 'Waiting for SMS (50101)'];
        }
        if ($api_code === 50102) {
            return ['success' => false, 'code' => $api_code, 'data' => null, 'error' => 'Number expired/timeout (50102)'];
        }

        if ($api_code !== 200) {
            return ['success' => false, 'code' => $api_code, 'data' => null, 'error' => 'API error code ' . $api_code];
        }

        return ['success' => true, 'code' => 200, 'data' => $json['data'] ?? null, 'error' => ''];
    }

    // ── 1. Get balance ────────────────────────────────────────────
    // GET /get/balance?token=
    // Response: {"code":200,"data":{"balance":2.52,"frozen":0}}
    public function getBalance(): array
    {
        return $this->request('get/balance');
    }

    // ── 2. Get countries ──────────────────────────────────────────
    // GET /list/countries?token=
    // Response: {"code":200,"data":{"1":{"id":1,"title":"...","code":"us"},...}}
    public function getCountries(): array
    {
        return $this->request('list/countries');
    }

    // ── 3. Get projects (services) ────────────────────────────────
    // GET /list/projects?token=
    // Response: {"code":200,"data":{"1":{"id":1,"title":"Telegram","code":"tg"},...}}
    public function getProjects(): array
    {
        return $this->request('list/projects');
    }

    // ── 4. Get prices for a country ───────────────────────────────
    // GET /list/prices?token=&country_id=
    // Response: {"code":200,"data":{"5":{"country_id":5,"project_id":2,"cost":0.9,"total_count":1023,...}}}
    public function getPrices(int $country_id): array
    {
        return $this->request('list/prices?country_id=' . $country_id);
    }

    // ── 5. Get a number ───────────────────────────────────────────
    // GET /get/number?token=&country_id=&project_id=
    // Response: {"code":200,"data":{"request_id":124,"number":"17548003793"}}
    public function getNumber(int $country_id, int $project_id): array
    {
        return $this->request('get/number?country_id=' . $country_id . '&project_id=' . $project_id);
    }

    // ── 6. Get SMS for a request ──────────────────────────────────
    // GET /get/sms?token=&request_id=
    // Response: {"code":200,"data":"429916"}  OR  {"code":50101}  OR  {"code":50102}
    public function getSms(string $request_id): array
    {
        return $this->request('get/sms?request_id=' . $request_id);
    }

    // ── 7. Cancel a request ───────────────────────────────────────
    // GET /cancel?token=&request_id=
    // Response: {"code":200}
    public function cancel(string $request_id): array
    {
        return $this->request('cancel?request_id=' . $request_id);
    }
}
