<?php

declare(strict_types=1);

/*
 * This file is part of the Ferienpass package.
 *
 * (c) Richard Henkenjohann <richard@ferienpass.online>
 *
 * For more information visit the project website <https://ferienpass.online>
 * or the documentation under <https://docs.ferienpass.online>.
 */

namespace Ferienpass\CoreBundle\Comment;

use Psr\Log\LoggerInterface;
use Symfony\Contracts\HttpClient\Exception\ExceptionInterface as HttpClientException;
use Symfony\Contracts\HttpClient\HttpClientInterface;

/**
 * Fetches an inbound attachment's bytes from Brevo. Inbound Parse never inlines
 * the file; it hands us a {@see https://developers.brevo.com/reference/get-inbound-email-attachment DownloadToken}
 * to pull it from `GET /v3/inbound/attachments/{token}` (api-key auth, raw bytes).
 *
 * The download is streamed and hard-capped at $maxBytes so a hostile sender
 * cannot exhaust memory with an oversized (or lying-about-its-size) attachment.
 */
final readonly class BrevoAttachmentDownloader
{
    public function __construct(
        private HttpClientInterface $brevoClient,
        private LoggerInterface $logger,
    ) {
    }

    public function download(string $token, int $maxBytes): ?string
    {
        if ('' === $token) {
            return null;
        }

        try {
            $response = $this->brevoClient->request('GET', '/v3/inbound/attachments/'.rawurlencode($token));
            if (200 !== $response->getStatusCode()) {
                $this->logger->warning('Inbound attachment download failed.', ['status' => $response->getStatusCode()]);

                return null;
            }

            $buffer = '';
            foreach ($this->brevoClient->stream($response) as $chunk) {
                $buffer .= $chunk->getContent();
                if (\strlen($buffer) > $maxBytes) {
                    $response->cancel();
                    $this->logger->warning('Inbound attachment exceeds the size limit; discarded.');

                    return null;
                }
            }

            return $buffer;
        } catch (HttpClientException $e) {
            $this->logger->warning('Inbound attachment download error: '.$e->getMessage());

            return null;
        }
    }
}
