<?php

namespace App\Integrations\Notification\Providers;

use App\Integrations\Notification\Contracts\SmsProvider;
use Illuminate\Http\Client\ConnectionException;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use InvalidArgumentException;

class MnotifySmsProvider implements SmsProvider
{
    public function __construct(private array $config = [])
    {
        if (!Arr::get($config, 'api_key')) {
            throw new InvalidArgumentException('mNotify API key is not configured.');
        }

        if (!Arr::get($config, 'sender_id')) {
            throw new InvalidArgumentException('mNotify sender ID is not configured.');
        }
    }

    public function send(string|array $recipients, string $message, array $options = []): void
    {
        $numbers = is_array($recipients) ? $recipients : [$recipients];
        $numbers = array_values(array_filter(array_unique(array_map([$this, 'normalizeMsisdn'], $numbers))));

        if (empty($numbers)) {
            throw new InvalidArgumentException('No valid recipient phone numbers provided for mNotify.');
        }

        $baseUrl = rtrim(Arr::get($this->config, 'base_url', 'https://api.mnotify.com'), '/');
        $endpoint = $baseUrl.'/api/sms/quick?key='.urlencode(Arr::get($this->config, 'api_key'));

        $payload = [
            'recipient' => $numbers,
            'sender' => Arr::get($this->config, 'sender_id'),
            'message' => $message,
            'is_schedule' => !empty($options['schedule_time']),
        ];

        if (!empty($options['schedule_time'])) {
            $payload['schedule_date'] = $options['schedule_time'];
        }

        $http = Http::asJson();

        $verify = (bool) Arr::get($this->config, 'verify_ssl', true);
        $proxy = Arr::get($this->config, 'proxy');
        $timeout = (int) Arr::get($this->config, 'timeout', 30);
        $connectTimeout = (int) Arr::get($this->config, 'connect_timeout', 10);

        $options = ['verify' => $verify];
        if (!empty($proxy)) {
            $options['proxy'] = $proxy;
        }

        $http = $http->timeout($timeout)->connectTimeout($connectTimeout)->withOptions($options);

        try {
            $response = $http->post($endpoint, $payload);
        } catch (ConnectionException $e) {
            Log::error('mNotify connection failed', [
                'endpoint' => $endpoint,
                'error' => $e->getMessage(),
            ]);
            throw new InvalidArgumentException('Unable to reach mNotify (connection timeout).');
        }

        $status = $response->status();
        $json = $response->json();
        $ok = $status === 200 && is_array($json) && Arr::get($json, 'status') === 'success';

        if (!$ok) {
            Log::error('mNotify SMS send failed', [
                'status' => $status,
                'body' => $response->body(),
                'payload' => $payload,
            ]);

            throw new InvalidArgumentException('Unable to send SMS via mNotify.');
        }
    }

    private function normalizeMsisdn($number): ?string
    {
        if ($number === null || $number === '') {
            return null;
        }

        $digits = preg_replace('/\D+/', '', (string) $number);
        if ($digits === '') {
            return null;
        }

        if (str_starts_with($digits, '0')) {
            return '233'.substr($digits, 1);
        }

        if (!str_starts_with($digits, '233') && strlen($digits) <= 9) {
            return '233'.$digits;
        }

        return $digits;
    }
}
