<?php

namespace App\Services;

use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Str;
use Throwable;

class NotificationTransportService
{
    public function __construct(private IntegrationSignature $signature) {}

    public function send(string $channel, ?string $recipient, ?string $subject, string $body, array $context = []): array
    {
        if (blank($recipient)) {
            return [
                'status' => 'skipped',
                'provider' => 'none',
                'reference' => 'NTF-'.now()->format('ymd').'-'.Str::upper(Str::random(8)),
                'payload' => ['reason' => 'missing_recipient'],
            ];
        }

        return match ($channel) {
            'email' => $this->sendEmail($recipient, $subject, $body, $context),
            'sms' => $this->sendSms($recipient, $body, $context),
            default => $this->logged('unsupported_'.$channel, $recipient, $subject, $body, $context),
        };
    }

    private function sendEmail(string $recipient, ?string $subject, string $body, array $context): array
    {
        $driver = config('raseednow.notifications.email_driver', 'log');

        if ($driver === 'mail') {
            try {
                Mail::raw($body, function ($message) use ($recipient, $subject) {
                    $message->to($recipient)->subject($subject ?: config('app.name'));
                });

                return $this->result('sent', 'laravel_mail', ['to' => $recipient, 'subject' => $subject, 'context' => $context]);
            } catch (Throwable $exception) {
                return $this->result('failed', 'laravel_mail', ['error' => $exception->getMessage(), 'context' => $context]);
            }
        }

        return $this->logged('log_email', $recipient, $subject, $body, $context);
    }

    private function sendSms(string $recipient, string $body, array $context): array
    {
        $driver = config('raseednow.notifications.sms_driver', 'log');

        if ($driver === 'generic_http') {
            $payload = [
                'to' => $recipient,
                'body' => $body,
                'sender' => config('raseednow.notifications.sms_http.sender'),
                'context' => $context,
            ];

            $signature = $this->signature->sign($payload, config('raseednow.notifications.sms_http.api_secret'));

            try {
                $response = Http::timeout(config('raseednow.notifications.sms_http.timeout'))
                    ->withHeaders(array_filter([
                        'Accept' => 'application/json',
                        'X-Api-Key' => config('raseednow.notifications.sms_http.api_key'),
                        'X-Signature' => $signature,
                    ]))
                    ->post((string) config('raseednow.notifications.sms_http.endpoint'), $payload);

                return $this->result($response->successful() ? 'sent' : 'failed', 'generic_sms_http', [
                    'status' => $response->status(),
                    'response' => $response->json() ?? $response->body(),
                ]);
            } catch (Throwable $exception) {
                return $this->result('failed', 'generic_sms_http', ['error' => $exception->getMessage()]);
            }
        }

        return $this->logged('log_sms', $recipient, null, $body, $context);
    }

    private function logged(string $provider, string $recipient, ?string $subject, string $body, array $context): array
    {
        return $this->result('sent', $provider, compact('recipient', 'subject', 'body', 'context'));
    }

    private function result(string $status, string $provider, array $payload): array
    {
        return [
            'status' => $status,
            'provider' => $provider,
            'reference' => 'NTF-'.now()->format('ymd').'-'.Str::upper(Str::random(8)),
            'payload' => $payload,
        ];
    }
}
