# retoor <retoor@molodetz.nl>

from __future__ import annotations

from .spec import Action, Param

REMOTE_NOTE = (
    "This reaches the user's OWN external mailbox over IMAP/SMTP, not this platform. The "
    "account must be configured first with email_account_set."
)


def arg(
    name: str, description: str, required: bool = False, kind: str = "string"
) -> Param:
    return Param(
        name=name,
        location="body",
        description=description,
        required=required,
        type=kind,
    )


ACCOUNT = arg(
    "account",
    "The label of the configured email account to use (see email_accounts_list).",
    required=True,
)
FOLDER = arg("folder", "Mailbox folder; defaults to INBOX when omitted.")
UID = arg("uid", "The message UID returned by email_list_messages / email_search.", required=True)
FILTERS = (
    arg("unseen", "Only unread messages.", kind="boolean"),
    arg("seen", "Only read messages.", kind="boolean"),
    arg("flagged", "Only flagged messages.", kind="boolean"),
    arg("from", "Match the sender address or name."),
    arg("subject", "Match text in the subject."),
    arg("since", "Only messages on or after this date, formatted DD-Mon-YYYY (e.g. 01-Jan-2026)."),
    arg("text", "Match text anywhere in the message."),
)

EMAIL_ACTIONS: tuple[Action, ...] = (
    Action(
        name="email_accounts_list",
        method="LOCAL",
        path="",
        summary="List the user's configured email accounts (passwords are never returned)",
        description="Returns each saved account's connection settings without the password.",
        handler="email",
        requires_auth=True,
        read_only=True,
    ),
    Action(
        name="email_account_get",
        method="LOCAL",
        path="",
        summary="Read one configured email account's connection settings",
        description="Returns the account settings without the password (password_set indicates whether one is stored).",
        handler="email",
        requires_auth=True,
        read_only=True,
        params=(ACCOUNT,),
    ),
    Action(
        name="email_account_set",
        method="LOCAL",
        path="",
        summary="Create or update an email account connection (IMAP + SMTP)",
        description=(
            "Saves an IMAP/SMTP connection under a label. Sensible defaults are applied when a "
            "field is omitted: imap_port 993 with imap_ssl on, smtp_port 587 with smtp_starttls on, "
            "from_address falls back to username. Provide host, username and password at minimum. "
            + REMOTE_NOTE
        ),
        handler="email",
        requires_auth=True,
        params=(
            ACCOUNT,
            arg("imap_host", "IMAP server hostname (e.g. imap.gmail.com)."),
            arg("imap_port", "IMAP port (default 993).", kind="integer"),
            arg("imap_ssl", "Use implicit SSL/TLS for IMAP (default true).", kind="boolean"),
            arg("imap_starttls", "Upgrade a plain IMAP connection with STARTTLS (default false).", kind="boolean"),
            arg("smtp_host", "SMTP server hostname (e.g. smtp.gmail.com)."),
            arg("smtp_port", "SMTP port (default 587).", kind="integer"),
            arg("smtp_ssl", "Use implicit SSL/TLS for SMTP (default false; set true for port 465).", kind="boolean"),
            arg("smtp_starttls", "Upgrade a plain SMTP connection with STARTTLS (default true).", kind="boolean"),
            arg("username", "Login username (usually the full email address)."),
            arg("password", "Login password or app-specific password."),
            arg("from_address", "From address for sent mail (defaults to the username)."),
            arg("from_name", "Display name for sent mail."),
        ),
    ),
    Action(
        name="email_account_delete",
        method="LOCAL",
        path="",
        summary="Delete a saved email account connection (confirmation required)",
        description="Removes the stored connection. Does not touch the remote mailbox.",
        handler="email",
        requires_auth=True,
        params=(
            ACCOUNT,
            arg(
                "confirm",
                "Set to true only after the user has confirmed the deletion.",
                required=True,
                kind="boolean",
            ),
        ),
    ),
    Action(
        name="email_list_folders",
        method="LOCAL",
        path="",
        summary="List the mailbox folders on the account",
        description=REMOTE_NOTE,
        handler="email",
        requires_auth=True,
        read_only=True,
        params=(ACCOUNT,),
    ),
    Action(
        name="email_list_messages",
        method="LOCAL",
        path="",
        summary="List messages in a folder, newest first, with optional filters",
        description=(
            "Returns message summaries (uid, from, subject, date, flags). Use the filters to narrow "
            "the set and limit/offset to page. " + REMOTE_NOTE
        ),
        handler="email",
        requires_auth=True,
        read_only=True,
        params=(
            ACCOUNT,
            FOLDER,
            *FILTERS,
            arg("limit", "Maximum messages to return (1-100, default 25).", kind="integer"),
            arg("offset", "Number of messages to skip for paging (default 0).", kind="integer"),
        ),
    ),
    Action(
        name="email_read_message",
        method="LOCAL",
        path="",
        summary="Read the full body, headers and attachment list of one message",
        description="Fetches the decoded text/html body and attachment metadata. " + REMOTE_NOTE,
        handler="email",
        requires_auth=True,
        read_only=True,
        params=(ACCOUNT, FOLDER, UID),
    ),
    Action(
        name="email_search",
        method="LOCAL",
        path="",
        summary="Search a folder by sender, subject, date, text or read/flag state",
        description="Returns matching message summaries. " + REMOTE_NOTE,
        handler="email",
        requires_auth=True,
        read_only=True,
        params=(
            ACCOUNT,
            FOLDER,
            *FILTERS,
            arg("limit", "Maximum messages to return (1-100, default 25).", kind="integer"),
        ),
    ),
    Action(
        name="email_mark",
        method="LOCAL",
        path="",
        summary="Mark a message read, unread, flagged or unflagged",
        description="Convenience wrapper over the IMAP \\Seen and \\Flagged flags. " + REMOTE_NOTE,
        handler="email",
        requires_auth=True,
        params=(
            ACCOUNT,
            FOLDER,
            UID,
            arg("state", "One of: read, unread, flagged, unflagged.", required=True),
        ),
    ),
    Action(
        name="email_set_flags",
        method="LOCAL",
        path="",
        summary="Add or remove arbitrary IMAP flags on a message",
        description="For advanced use; prefer email_mark for read/flagged. " + REMOTE_NOTE,
        handler="email",
        requires_auth=True,
        params=(
            ACCOUNT,
            FOLDER,
            UID,
            arg("flags", "Comma-separated IMAP flags (e.g. \\Seen, \\Flagged, \\Answered).", required=True),
            arg("add", "true to add the flags, false to remove them (default true).", kind="boolean"),
        ),
    ),
    Action(
        name="email_move_message",
        method="LOCAL",
        path="",
        summary="Move a message to another folder",
        description="Copies the message to the destination folder and removes it from the source. " + REMOTE_NOTE,
        handler="email",
        requires_auth=True,
        params=(
            ACCOUNT,
            FOLDER,
            UID,
            arg("destination", "Destination folder name.", required=True),
        ),
    ),
    Action(
        name="email_delete_message",
        method="LOCAL",
        path="",
        summary="Delete a message (confirmation required)",
        description=(
            "Deletes the message. If 'trash' is given the message is moved there; otherwise it is "
            "flagged \\Deleted and expunged. " + REMOTE_NOTE
        ),
        handler="email",
        requires_auth=True,
        params=(
            ACCOUNT,
            FOLDER,
            UID,
            arg("trash", "Optional Trash folder to move the message into instead of expunging."),
            arg(
                "confirm",
                "Set to true only after the user has confirmed the deletion.",
                required=True,
                kind="boolean",
            ),
        ),
    ),
    Action(
        name="email_send",
        method="LOCAL",
        path="",
        summary="Send an email via the account's SMTP server",
        description="Composes and sends a message. " + REMOTE_NOTE,
        handler="email",
        requires_auth=True,
        params=(
            ACCOUNT,
            arg("to", "Recipient address or comma-separated list.", required=True),
            arg("subject", "Email subject."),
            arg("body", "Plain-text body."),
            arg("cc", "CC recipients (comma-separated)."),
            arg("bcc", "BCC recipients (comma-separated)."),
            arg("html", "Optional HTML alternative body."),
            arg("in_reply_to", "Optional Message-ID this email replies to."),
        ),
    ),
)
