"""The mail seam: a `Mailer` sends one plain-text message; `none` is the launch provider.

Sources of truth: this module, `app/config.py` (`MAIL_PROVIDER`, `MAIL_FROM`, `RESEND_API_KEY`),
`docs/ACCOUNTS.md`. Design: `.logs/planning/accounts-2026-09.md` §4.5.

With no provider every send raises `MailNotConfigured` before anything is written, which the
directory turns into a refusal the People panel can show. There is deliberately no console
provider: printing a link to stdout is logging a token, and the container's stdout is an
access log. The recipient is always the address stored on the account, never one from a
request. The test suite injects a recording mailer through `set_mailer`; nothing under test
reads `MAIL_PROVIDER`.
"""

from __future__ import annotations

import logging
from typing import Protocol

from app.config import settings

log = logging.getLogger(__name__)


class MailNotConfigured(RuntimeError):
    """No provider on this host: invites and resets go by CLI link or generated password."""


class Mailer(Protocol):
    def send(self, to: str, subject: str, text: str) -> None: ...


class NoMailer:
    def send(self, to: str, subject: str, text: str) -> None:
        raise MailNotConfigured(
            "No mail provider is configured on this host. Use `accounts invite-link` or "
            "`accounts reset-link` from the CLI, or add the person with a generated password."
        )


_override: Mailer | None = None


def set_mailer(mailer: Mailer | None) -> None:
    """Tests inject a recorder; None restores the configured provider."""
    global _override
    _override = mailer


def mailer() -> Mailer:
    if _override is not None:
        return _override
    provider = (settings.mail_provider or "none").strip().lower()
    if provider == "resend":
        from app.services.mail_resend import ResendMailer

        return ResendMailer()
    return NoMailer()


def configured() -> bool:
    """Whether a send could succeed, for the CLI's advice; never sends."""
    if _override is not None:
        return True
    return (settings.mail_provider or "none").strip().lower() == "resend" and settings.mail_ready
