"""
Router API – Invio PEC (Fase 4).

Endpoint:
  POST   /send          – invia una nuova PEC (crea Message + SendJob, accoda job)
  GET    /send/jobs     – lista job di invio del tenant (paginata)
  GET    /send/jobs/{id} – dettaglio di un singolo job
  DELETE /send/jobs/{id} – annulla job se ancora pending/retrying
"""

import uuid
from typing import Annotated

from fastapi import APIRouter, Query, status

from app.core.exceptions import ForbiddenError
from app.dependencies import AdminUser, CurrentUser, DB
from app.schemas.send import SendJobListResponse, SendJobResponse, SendPecRequest
from app.services.permission_service import PermissionService
from app.services.send_service import SendService

router = APIRouter(prefix="/send", tags=["Invio PEC"])


# ─── Helpers ──────────────────────────────────────────────────────────────────

def _svc(db) -> SendService:
    return SendService(db)


def _job_response(job) -> SendJobResponse:
    return SendJobResponse.model_validate(job)


# ─── Endpoints ────────────────────────────────────────────────────────────────


@router.post(
    "",
    response_model=SendJobResponse,
    status_code=status.HTTP_201_CREATED,
    summary="Invia una PEC",
    description=(
        "Crea un messaggio PEC in uscita e accoda il job di invio SMTP. "
        "Il job viene eseguito in background con retry automatico. "
        "Richiede permesso **can_send** sulla casella (gli admin possono inviare da qualsiasi casella del tenant)."
    ),
)
async def create_send_job(
    data: SendPecRequest,
    current_user: CurrentUser,
    db: DB,
) -> SendJobResponse:
    svc = _svc(db)
    job = await svc.create_send_job(current_user=current_user, data=data)
    await db.commit()
    # Refresh per ottenere tutti i valori default dal DB
    await db.refresh(job)
    return _job_response(job)


@router.get(
    "/jobs",
    response_model=SendJobListResponse,
    summary="Lista job di invio",
)
async def list_send_jobs(
    current_user: CurrentUser,
    db: DB,
    page: int = Query(1, ge=1),
    page_size: int = Query(50, ge=1, le=200),
    mailbox_id: uuid.UUID | None = Query(None),
    status_filter: str | None = Query(
        None,
        alias="status",
        description="Filtra per stato: pending | sending | sent | failed | retrying",
    ),
) -> SendJobListResponse:
    """
    Elenca i job di invio del tenant.

    Gli admin vedono tutti i job; gli operatori vedono solo i job
    delle caselle su cui hanno permesso can_read.
    """
    svc = _svc(db)

    # Filtro opzionale per casella: verifica accesso se non admin
    if mailbox_id and not current_user.is_admin:
        perm_svc = PermissionService(db)
        if not await perm_svc.check_can_read(current_user, mailbox_id):
            raise ForbiddenError("Accesso alla casella non autorizzato")

    items, total = await svc.list_send_jobs(
        tenant_id=current_user.tenant_id,
        page=page,
        page_size=page_size,
        mailbox_id=mailbox_id,
        status_filter=status_filter,
    )
    return SendJobListResponse(
        items=[_job_response(j) for j in items],
        total=total,
        page=page,
        page_size=page_size,
    )


@router.get(
    "/jobs/{job_id}",
    response_model=SendJobResponse,
    summary="Dettaglio job di invio",
)
async def get_send_job(
    job_id: uuid.UUID,
    current_user: CurrentUser,
    db: DB,
) -> SendJobResponse:
    """Recupera lo stato di un singolo job di invio."""
    svc = _svc(db)
    job = await svc.get_send_job(job_id, current_user.tenant_id)

    # Verifica accesso alla casella se non admin
    if not current_user.is_admin:
        perm_svc = PermissionService(db)
        if not await perm_svc.check_can_read(current_user, job.mailbox_id):
            raise ForbiddenError("Accesso non autorizzato")

    return _job_response(job)


@router.delete(
    "/jobs/{job_id}",
    status_code=status.HTTP_204_NO_CONTENT,
    summary="Annulla job di invio",
)
async def cancel_send_job(
    job_id: uuid.UUID,
    current_user: CurrentUser,
    db: DB,
) -> None:
    """
    Annulla un job di invio se è ancora in stato **pending** o **retrying**.

    Non è possibile annullare un invio già partito (stato sending) o
    completato (sent).
    """
    svc = _svc(db)

    # Verifica che l'utente possa agire su questo job
    job = await svc.get_send_job(job_id, current_user.tenant_id)
    if not current_user.is_admin:
        perm_svc = PermissionService(db)
        if not await perm_svc.check_can_send(current_user, job.mailbox_id):
            raise ForbiddenError("Autorizzazione insufficiente per annullare questo invio")

    await svc.cancel_send_job(job_id, current_user.tenant_id)
    await db.commit()
