<?php

namespace App\Services;

use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use InvalidArgumentException;

class SmsService
{
    public function sendByPatternKey(string $patternKey, string $receptor, array $tokens = []): array
    {
        $pattern = config('sms.patterns.' . $patternKey);

        if (!$pattern || !isset($pattern['template'])) {
            throw new InvalidArgumentException('Unknown SMS pattern key: ' . $patternKey);
        }

        return $this->sendPattern($receptor, (string) $pattern['template'], $tokens, [
            'pattern_key' => $patternKey,
            'pattern_id' => Arr::get($pattern, 'id'),
        ]);
    }

    public function sendPattern(string $receptor, string $template, array $tokens = [], array $meta = []): array
    {
        $apiKey = (string) config('sms.api_key', '');

        if ($apiKey === '') {
            return [
                'success' => false,
                'message' => 'SMS api key is not configured.',
            ];
        }

        $normalizedReceptor = $this->normalizePhone($receptor);
        if ($normalizedReceptor === null) {
            return [
                'success' => false,
                'message' => 'Invalid receptor phone number format.',
            ];
        }

        $payload = [
            'receptor' => $normalizedReceptor,
            'template' => $template,
            'type' => 'sms',
        ];

        foreach ($tokens as $key => $value) {
            $tokenKey = strtolower((string) $key);
            if ($tokenKey === 'token' || preg_match('/^token\d+$/', $tokenKey) === 1) {
                $payload[$tokenKey] = (string) $value;
            }
        }

        try {
            $endpoint = sprintf('https://api.kavenegar.com/v1/%s/verify/lookup.json', $apiKey);
            $response = Http::asForm()->timeout(20)->post($endpoint, $payload);

            if (!$response->ok()) {
                Log::warning('SMS provider HTTP error', [
                    'status' => $response->status(),
                    'body' => $response->body(),
                    'meta' => $meta,
                    'receptor' => $normalizedReceptor,
                    'template' => $template,
                ]);

                return [
                    'success' => false,
                    'message' => 'SMS provider returned HTTP error.',
                    'status' => $response->status(),
                ];
            }

            $json = $response->json();
            $entry = Arr::get($json, 'entries.0', []);

            return [
                'success' => true,
                'message' => 'SMS sent successfully.',
                'provider_message_id' => Arr::get($entry, 'messageid'),
                'provider_status' => Arr::get($entry, 'status'),
                'provider_status_text' => Arr::get($entry, 'statustext'),
                'response' => $json,
            ];
        } catch (\Throwable $exception) {
            Log::error('SMS provider exception', [
                'message' => $exception->getMessage(),
                'meta' => $meta,
                'receptor' => $normalizedReceptor,
                'template' => $template,
            ]);

            return [
                'success' => false,
                'message' => $exception->getMessage(),
            ];
        }
    }

    public function sendCargoRequestRegistered(string $receptor, string $trackingCode): array
    {
        return $this->sendByPatternKey('cargo_request_registered', $receptor, [
            'token' => $trackingCode,
        ]);
    }

    public function sendCargoRequestNotifToAdmin(string $receptor, string $trackingCode, string $origin, string $destination): array
    {
        return $this->sendByPatternKey('cargo_request_notif_to_admin', $receptor, [
            'token' => $trackingCode,
            'token2' => $origin,
            'token3' => $destination,
        ]);
    }

    public function sendCancelRequest(string $receptor, string $trackingCode, string $senderName, string $receiverName): array
    {
        return $this->sendByPatternKey('cancel_request', $receptor, [
            'token' => $trackingCode,
            'token10' => $senderName,
            'token20' => $receiverName,
        ]);
    }

    public function sendIssuanceBillLandingFromBita24(string $receptor, string $trackingCode, string $supportPhone): array
    {
        return $this->sendByPatternKey('issuance_bill_landing_from_bita24', $receptor, [
            'token' => $trackingCode,
            'token2' => $supportPhone,
        ]);
    }

    public function sendIssuanceBillLandingFromSite(string $receptor, string $trackingCode, string $downloadLink, string $supportPhone): array
    {
        return $this->sendByPatternKey('issuance_bill_landing_from_site', $receptor, [
            'token' => $trackingCode,
            'token2' => $downloadLink,
            'token3' => $supportPhone,
        ]);
    }

    public function sendCompanyOtpLogin(string $receptor, string $code): array
    {
        return $this->sendByPatternKey('company_otp_login', $receptor, [
            'token' => $code,
        ]);
    }

    public function sendDriverReceiveWaybill(string $receptor, string $trackingCode, string $driverName): array
    {
        return $this->sendByPatternKey('driver_receive_waybill', $receptor, [
            'token' => $trackingCode,
            'token2' => $driverName,
        ]);
    }

    public function sendDriverCompleteInformation(string $receptor, string $driverName): array
    {
        return $this->sendByPatternKey('driver_complete_information', $receptor, [
            'token' => $driverName,
        ]);
    }

    public function sendDriverLoginOtp(string $receptor, string $code): array
    {
        return $this->sendByPatternKey('driver_login_otp', $receptor, [
            'token' => $code,
        ]);
    }

    private function normalizePhone(string $phone): ?string
    {
        $digits = preg_replace('/\D+/', '', $phone) ?? '';

        if (str_starts_with($digits, '98') && strlen($digits) === 12) {
            $digits = '0' . substr($digits, 2);
        }

        if (strlen($digits) === 10 && str_starts_with($digits, '9')) {
            $digits = '0' . $digits;
        }

        if (preg_match('/^09\d{9}$/', $digits) !== 1) {
            return null;
        }

        return $digits;
    }
}
