<?php

namespace App\Mail\Concerns;

use App\Services\Mail\MailboxResolver;
use App\Services\Mail\MailRoute;
use Illuminate\Mail\Mailables\Address;
use Illuminate\Mail\Mailables\Envelope;

/**
 * From and Reply-To, taken from the mailbox behind a purpose — or, with a
 * $mailKey, from whatever MailRoute has that ONE mail type pointed at instead.
 *
 * Reply-To is the whole reason sending alone is enough: a customer answering a
 * support reply lands in the support mailbox, read in an ordinary mail client,
 * so no IMAP is needed to close the loop.
 *
 * Except on a no-reply mailbox. A "no-reply" address you can reply to is a lie
 * in the sender, and the one place the promise is made is the address itself.
 */
trait SendsFromMailbox
{
    protected function mailboxEnvelope(string $purpose, string $subject, ?string $mailKey = null): Envelope
    {
        [$from, $replyTo] = $this->mailboxAddresses($purpose, $mailKey);

        return new Envelope(
            from: $from,
            replyTo: $replyTo ? [$replyTo] : [],
            subject: $subject,
        );
    }

    /**
     * The From and Reply-To addresses for $purpose's mailbox — the ONE place
     * that decides "no configured mailbox means no sender fields at all" and
     * "no_reply means no Reply-To". Shared by every consumer of a purpose
     * mailbox regardless of the shape it builds — an Envelope here (a
     * Mailable), a MailMessage in CloudReady (a Notification, which cannot
     * use mailboxEnvelope() directly since it is not building an Envelope).
     * Two independent copies of this same decision is exactly the shape of
     * gap Task 4 found and fixed in MailboxTransport::resolution().
     *
     * $mailKey names this ONE mail type in MailCatalogue and lets MailRoute
     * override the purpose's mailbox for it alone. Left null (every caller
     * before this parameter existed, and every one that still has no reason
     * to be overridden individually), behaviour is exactly what it was: the
     * purpose alone decides.
     *
     * @return array{0: ?Address, 1: ?Address} [from, replyTo]
     */
    protected function mailboxAddresses(string $purpose, ?string $mailKey = null): array
    {
        $box = $mailKey !== null
            ? MailRoute::purposeOrMailbox($mailKey, $purpose)
            : app(MailboxResolver::class)->for($purpose);

        if ($box === null) {
            // No mailbox configured yet — both null, so a caller falls back
            // to its own framework default rather than dereferencing null.
            return [null, null];
        }

        $from = new Address($box->address, $box->display_name ?: null);

        return [$from, $box->no_reply ? null : $from];
    }
}
