<?php

namespace App\Services;

use App\Jobs\SendBookingLinkSms;
use App\Models\Booking;
use App\Models\Company;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;

/**
 * Sends SMS through each company's own gateway credentials (Company::
 * sms_provider/sms_api_key/sms_sender_id, set on the settings screen) —
 * unlike the old project, which had one gateway API key hard-coded in
 * source and shared across every tenant. Twilio is the concretely wired
 * provider; anything else logs a clear "not implemented" notice instead of
 * silently doing nothing.
 */
class SmsService
{
    public function send(Company $company, string $to, string $message): bool
    {
        if (! $company->sms_provider || ! $company->sms_api_key) {
            Log::info('SmsService: skipped send, no gateway configured for company.', ['company_id' => $company->id]);

            return false;
        }

        return match (strtolower($company->sms_provider)) {
            'twilio' => $this->sendViaTwilio($company, $to, $message),
            default => tap(false, fn () => Log::warning('SmsService: unsupported provider.', [
                'company_id' => $company->id, 'provider' => $company->sms_provider,
            ])),
        };
    }

    /**
     * PERF-03: queues the actual Twilio call rather than making booking
     * creation wait on it — neither call site inspects the return value.
     */
    public function sendBookingLink(Booking $booking): void
    {
        SendBookingLinkSms::dispatch($booking->id);
    }

    /**
     * Sends the customer a link to their booking — prefers WhatsApp when the
     * company has a WhatsApp-approved sender configured (INT-01: materially
     * higher read-rates than SMS), falling back to plain SMS otherwise. Same
     * template placeholders either way: {customer_name}, {driver_name},
     * {booking_number}, {link}. Still called directly by SendBookingLinkSms's
     * queued handle().
     */
    public function sendBookingLinkNow(Booking $booking): bool
    {
        if (! $booking->customer?->phone) {
            return false;
        }

        $template = $booking->company->sms_template
            ?: 'Hi {customer_name}, your booking {booking_number} is confirmed. Track it: {link}';

        $message = strtr($template, [
            '{customer_name}' => $booking->customer->name,
            '{driver_name}' => $booking->driver->full_name ?? 'TBC',
            '{booking_number}' => $booking->booking_number,
            '{link}' => url('/bookings/'.$booking->id),
        ]);

        if ($booking->company->whatsapp_sender_id) {
            return $this->sendWhatsApp($booking->company, $booking->customer->phone, $message);
        }

        return $this->send($booking->company, $booking->customer->phone, $message);
    }

    /**
     * WhatsApp via Twilio reuses the exact same Messages endpoint and
     * Account SID/Auth Token as SMS — only the "whatsapp:" prefix on the To
     * and From numbers, and a WhatsApp-approved sender, differ.
     */
    public function sendWhatsApp(Company $company, string $to, string $message): bool
    {
        if (! $company->whatsapp_sender_id || ! $company->sms_api_key) {
            Log::info('SmsService: skipped WhatsApp send, not configured for company.', ['company_id' => $company->id]);

            return false;
        }

        [$sid, $token] = array_pad(explode(':', $company->sms_api_key, 2), 2, null);

        if (! $sid || ! $token) {
            Log::warning('SmsService: Twilio credentials malformed.', ['company_id' => $company->id]);

            return false;
        }

        $response = Http::asForm()->withBasicAuth($sid, $token)
            ->post("https://api.twilio.com/2010-04-01/Accounts/{$sid}/Messages.json", [
                'To' => 'whatsapp:'.$to,
                'From' => 'whatsapp:'.$company->whatsapp_sender_id,
                'Body' => $message,
            ]);

        if (! $response->successful()) {
            Log::warning('SmsService: WhatsApp send failed.', ['company_id' => $company->id, 'status' => $response->status(), 'body' => $response->body()]);
        }

        return $response->successful();
    }

    private function sendViaTwilio(Company $company, string $to, string $message): bool
    {
        // sms_api_key is stored as "ACCOUNT_SID:AUTH_TOKEN"; sms_sender_id is the Twilio From number.
        [$sid, $token] = array_pad(explode(':', $company->sms_api_key, 2), 2, null);

        if (! $sid || ! $token || ! $company->sms_sender_id) {
            Log::warning('SmsService: Twilio credentials incomplete.', ['company_id' => $company->id]);

            return false;
        }

        $response = Http::asForm()->withBasicAuth($sid, $token)
            ->post("https://api.twilio.com/2010-04-01/Accounts/{$sid}/Messages.json", [
                'To' => $to,
                'From' => $company->sms_sender_id,
                'Body' => $message,
            ]);

        if (! $response->successful()) {
            Log::warning('SmsService: Twilio send failed.', ['company_id' => $company->id, 'status' => $response->status(), 'body' => $response->body()]);
        }

        return $response->successful();
    }
}
