<?php
declare(strict_types=1);

namespace FreshCloud\Mail\SmtpClient;

use FreshCloud\Mail\Log\Logger;
use FreshCloud\Mail\PocketBaseAdapter\PocketBaseAdapter;
use Throwable;

final class InMemorySmtpClient implements SmtpClientInterface
{
    private array $connectionPool = [];

    public function __construct(
        private PocketBaseAdapter $pb,
        private Logger $logger,
    ) {
    }

    public function connect(SmtpCredentials $creds): SmtpConnectionResult
    {
        $key = $this->getPoolKey($creds->userId, $creds->accountId);

        // Validate credentials format
        if (empty($creds->host) || $creds->port < 1 || $creds->port > 65535) {
            return new SmtpConnectionResult(false, 'Invalid credentials format');
        }

        // Store in pool (simulate connection)
        $this->connectionPool[$key] = true;
        return new SmtpConnectionResult(true, capabilities: ['AUTH LOGIN', 'STARTTLS']);
    }

    public function send(SmtpMessage $msg, SmtpCredentials $creds): SmtpResult
    {
        $key = $this->getPoolKey($creds->userId, $creds->accountId);

        if (!isset($this->connectionPool[$key])) {
            throw new SmtpException('Not connected');
        }

        // Simulate send (90% success, 10% failure)
        $rand = mt_rand(1, 100);
        $success = $rand <= 90;

        // Log send attempt
        $logData = [
            'from' => $msg->from,
            'to' => $msg->to,
            'subject' => $msg->subject,
            'success' => $success,
            'timestamp' => date('Y-m-d H:i:s'),
        ];
        $this->logger->log('smtp_send_attempt', $logData);

        if ($success) {
            return SmtpResult::sent('msg_' . bin2hex(random_bytes(8)));
        }

        // For failure, write to email_outbox via the standard CollectionAdapter
        try {
            $outbox = $this->pb->collection('email_outbox');
            $outbox->create([
                'user_id' => $creds->userId,
                'account_id' => $creds->accountId,
                'from' => $msg->from,
                'to' => json_encode($msg->to),
                'cc' => json_encode($msg->cc),
                'bcc' => json_encode($msg->bcc),
                'subject' => $msg->subject,
                'body' => $msg->body,
                'retry_count' => 0,
                'next_retry_at' => date('Y-m-d H:i:s', time() + 300),
            ]);
            return SmtpResult::queued('queued_' . bin2hex(random_bytes(8)));
        } catch (Throwable $e) {
            $this->logger->log('smtp_queue_failed', ['error' => $e->getMessage()]);
            return SmtpResult::failed('Queue failed: ' . $e->getMessage());
        }
    }

    public function disconnect(): void
    {
        // Clear all pool entries (simulate disconnection)
        $this->connectionPool = [];
    }

    public function getQueueCount(string $userId, string $accountId): int
    {
        // In-memory queue is always empty
        return 0;
    }

    private function getPoolKey(string $userId, string $accountId): string
    {
        return $userId . ':' . $accountId;
    }
}