<?php

namespace App\Mail;

use App\Models\MailingBounce;
use Illuminate\Mail\PendingMail;
use Illuminate\Support\Facades\Log;

class BounceAwarePendingMail extends PendingMail
{
    /**
     * Send a new mailable message instance with bounce checking
     */
    public function send($mailable)
    {
        // Filter out suppressed recipients before sending
        $this->filterSuppressedRecipients();

        // If no valid recipients remain, don't send
        if (empty($this->to) && empty($this->cc) && empty($this->bcc)) {
            Log::info("All recipients suppressed, skipping email send", [
                'mailable_class' => get_class($mailable)
            ]);
            return;
        }

        // Add bounce tracking headers if the mailable supports it
        if (method_exists($mailable, 'configureBounceTracking') || $this->usesBounceTrackingTrait($mailable)) {
            $this->addBounceTrackingToMailable($mailable);
        }

        return parent::send($mailable);
    }

    /**
     * Queue a new e-mail message for sending with bounce checking
     */
    public function queue($mailable)
    {
        // Filter out suppressed recipients before queuing
        $this->filterSuppressedRecipients();

        // If no valid recipients remain, don't queue
        if (empty($this->to) && empty($this->cc) && empty($this->bcc)) {
            Log::info("All recipients suppressed, skipping email queue", [
                'mailable_class' => get_class($mailable)
            ]);
            return;
        }

        // Add bounce tracking headers if the mailable supports it
        if (method_exists($mailable, 'configureBounceTracking') || $this->usesBounceTrackingTrait($mailable)) {
            $this->addBounceTrackingToMailable($mailable);
        }

        return parent::queue($mailable);
    }

    /**
     * Filter out suppressed email addresses from recipients
     */
    protected function filterSuppressedRecipients(): void
    {
        $this->to = $this->filterRecipientList($this->to);
        $this->cc = $this->filterRecipientList($this->cc);
        $this->bcc = $this->filterRecipientList($this->bcc);
    }

    /**
     * Filter a specific recipient list
     */
    protected function filterRecipientList(array $recipients): array
    {
        $filtered = [];

        foreach ($recipients as $recipient) {
            $email = $this->extractEmailAddress($recipient);

            if ($email && MailingBounce::isSuppressed($email)) {
                Log::info("Email sending blocked for suppressed address: {$email}", [
                    'suppressed' => true
                ]);
                continue;
            }

            $filtered[] = $recipient;
        }

        return $filtered;
    }

    /**
     * Extract email address from recipient
     */
    protected function extractEmailAddress($recipient): ?string
    {
        if (is_string($recipient)) {
            return $recipient;
        }

        if (is_array($recipient)) {
            return $recipient['address'] ?? null;
        }

        if (is_object($recipient)) {
            return $recipient->email ?? null;
        }

        return null;
    }

    /**
     * Check if mailable uses the bounce tracking trait
     */
    protected function usesBounceTrackingTrait($mailable): bool
    {
        return in_array('App\Mail\Concerns\TracksBounces', class_uses_recursive($mailable));
    }

    /**
     * Add bounce tracking to mailable
     */
    protected function addBounceTrackingToMailable($mailable): void
    {
        // Mark that bounce tracking should be enabled
        if (property_exists($mailable, 'bounceTrackingEnabled')) {
            $mailable->bounceTrackingEnabled = true;
        }
    }
}