"""
Job arq: sync_mailbox – trigger manuale per forzare la sincronizzazione di una casella.

Questo job viene usato per:
  - Forzare una sync immediata dopo la creazione di una nuova casella
  - Resync manuale da parte dell'admin
  - Retry dopo un errore (called dal pool monitor)

Non sostituisce il loop IMAP continuo (IMAPConnection); è un one-shot job.

Sincronizza sia INBOX (per rilevare ricevute PEC e messaggi in arrivo)
sia la cartella Sent (per aggiornare imap_uid sul record send_pec ed
evitare duplicati outbound che rompono il binding delle ricevute).
"""

import logging
from typing import Any

from app.database import AsyncSessionLocal
from app.imap.sync import sync_new_messages, sync_sent_messages
from app.models import Mailbox

logger = logging.getLogger(__name__)


async def sync_mailbox(ctx: dict[str, Any], mailbox_id: str) -> dict:
    """
    Job arq: sincronizza una singola casella PEC (INBOX + Sent).

    Args:
        ctx: contesto arq (contiene redis, pool reference)
        mailbox_id: UUID della casella da sincronizzare

    Returns:
        dict con risultato del job
    """
    redis_client = ctx.get("redis")

    async with AsyncSessionLocal() as db:
        mailbox = await db.get(Mailbox, mailbox_id)

        if not mailbox:
            return {"status": "error", "message": f"Mailbox {mailbox_id} non trovata"}

        if mailbox.status not in ("active", "error"):
            return {
                "status": "skipped",
                "message": f"Mailbox status={mailbox.status}, skip",
            }

        from app.imap.connection import IMAPConnection

        creds = IMAPConnection._decrypt_creds(mailbox)

        try:
            conn = IMAPConnection(mailbox_id=mailbox_id, redis_client=redis_client)
            client = await conn._connect(creds)

            # Sync INBOX: ricevute PEC e messaggi in arrivo
            n_inbox = await sync_new_messages(client, mailbox, db, redis_client)

            # Sync Sent: aggiorna imap_uid sui record send_pec e previene duplicati.
            # Fondamentale per il corretto binding delle ricevute PEC successive.
            n_sent = 0
            try:
                n_sent = await sync_sent_messages(client, mailbox, db, redis_client)
            except Exception as sent_err:
                logger.warning(
                    f"[sync_mailbox] {mailbox.email_address} errore sync Sent "
                    f"(non critico): {sent_err}"
                )

            try:
                await client.logout()
            except Exception:
                pass

            logger.info(
                f"[sync_mailbox] {mailbox.email_address}: "
                f"INBOX={n_inbox} nuovi, Sent={n_sent} nuovi"
            )

            return {
                "status": "ok",
                "mailbox": mailbox.email_address,
                "new_messages_inbox": n_inbox,
                "new_messages_sent": n_sent,
            }

        except Exception as e:
            logger.error(f"[sync_mailbox] {mailbox_id} errore: {e}", exc_info=True)
            return {
                "status": "error",
                "mailbox": mailbox.email_address if mailbox else mailbox_id,
                "message": str(e),
            }
