<?php

declare(strict_types=1);

namespace App\Framework\Mail;

final class PooledSmtpTransport implements TransportInterface
{
    private array $connections = [];

    private int $currentConnection = 0;

    public function __construct(
        private readonly SmtpConfig $config,
        private readonly int $maxConnections = 3,
    ) {
    }

    public function send(Message $message): TransportResult
    {
        $transport = $this->getConnection();

        return $transport->send($message);
    }

    public function isAvailable(): bool
    {
        // Test with a fresh connection
        $transport = new SmtpTransport($this->config);

        return $transport->isAvailable();
    }

    public function getName(): string
    {
        return 'Pooled SMTP Transport (' . $this->config->host . ':' . $this->config->port . ', pool: ' . $this->maxConnections . ')';
    }

    public function sendBatch(array $messages): array
    {
        $results = [];

        foreach ($messages as $index => $message) {
            if (! $message instanceof Message) {
                $results[$index] = TransportResult::failure('Invalid message at index ' . $index);

                continue;
            }

            $results[$index] = $this->send($message);
        }

        return $results;
    }

    private function getConnection(): SmtpTransport
    {
        // Round-robin connection selection
        $connectionId = $this->currentConnection % $this->maxConnections;
        $this->currentConnection++;

        if (! isset($this->connections[$connectionId])) {
            $this->connections[$connectionId] = new SmtpTransport($this->config);
        }

        return $this->connections[$connectionId];
    }

    public function closeAllConnections(): void
    {
        foreach ($this->connections as $transport) {
            // Connections will be closed when transport is destroyed
            unset($transport);
        }

        $this->connections = [];
        $this->currentConnection = 0;
    }

    public function getActiveConnections(): int
    {
        return count($this->connections);
    }

    public function __destruct()
    {
        $this->closeAllConnections();
    }
}
