<?php

namespace App\Services\Communications\Providers;

use App\Contracts\Communications\EmailChannelProvider;
use App\Enum\Contact\MessageProvider;
use App\Models\Contact\Hub\ContactMessage;
use App\Services\SendGridEmailService;
use App\ValueObjects\Communications\ProviderSendResult;
use RuntimeException;

class SendGridEmailProvider implements EmailChannelProvider
{
    public function __construct(
        protected SendGridEmailService $sendgrid,
    ) {}

    public function identifier(): MessageProvider
    {
        return MessageProvider::SENDGRID;
    }

    public function send(ContactMessage $message): ProviderSendResult
    {
        if (empty($message->recipient_email)) {
            throw new RuntimeException('ContactMessage is missing recipient_email.');
        }
        if (empty($message->sender_value)) {
            throw new RuntimeException('ContactMessage is missing sender_value (from email).');
        }

        $payload = [
            'to_email' => $message->recipient_email,
            'to_name' => $message->recipient_name,
            'from_email' => $message->sender_value,
            'from_name' => $message->sender_display,
            'subject' => $message->subject,
            'html' => $message->body_html,
            'text' => $message->body_text,
            'reply_to' => $message->reply_to,
            'attachments' => $message->attachments->map(fn ($a) => [
                'content' => $a->base64Contents(),
                'mime' => $a->mime,
                'name' => $a->filename,
            ])->all(),
        ];

        $response = $this->sendgrid->send($payload);

        $providerMessageId = $this->extractMessageId($response);

        return new ProviderSendResult(
            providerMessageId: $providerMessageId,
            payload: $response,
            accepted: $response['status'] >= 200 && $response['status'] < 300,
        );
    }

    private function extractMessageId(array $response): string
    {
        $headers = $response['headers'] ?? [];
        // Laravel Http wraps header values in arrays.
        foreach (['X-Message-Id', 'x-message-id'] as $key) {
            if (!empty($headers[$key])) {
                $value = $headers[$key];
                return is_array($value) ? (string) ($value[0] ?? '') : (string) $value;
            }
        }

        // Fallback: use a synthetic id so we still have something to correlate on.
        return 'sg_' . uniqid('', true);
    }
}
