"""
Router Fascicoli — fascicolazione pratiche.

Endpoint:
  - GET    /fascicoli                          – lista fascicoli (con filtri)
  - POST   /fascicoli                          – crea un fascicolo
  - GET    /fascicoli/{id}                     – dettaglio fascicolo
  - PATCH  /fascicoli/{id}                     – modifica fascicolo
  - DELETE /fascicoli/{id}                     – elimina fascicolo (solo admin)

  - GET    /fascicoli/{id}/messages            – messaggi del fascicolo
  - POST   /fascicoli/{id}/messages            – aggiungi messaggi al fascicolo
  - DELETE /fascicoli/{id}/messages            – rimuovi messaggi dal fascicolo

  - GET    /messages/{message_id}/fascicoli    – fascicoli di un messaggio

Permessi:
  - Tutti gli utenti autenticati possono creare fascicoli.
  - PATCH: creatore o admin.
  - DELETE fascicolo: solo admin.
  - Operazioni su messaggi: utente con accesso al tenant.
"""

import uuid
from typing import Optional

from fastapi import APIRouter, Query, status
from sqlalchemy import select

from app.core.exceptions import ForbiddenError, NotFoundError
from app.dependencies import AdminUser, CurrentUser, DB
from app.models.message import Message
from app.schemas.fascicolo import (
    FascicoloAddMessagesRequest,
    FascicoloCreate,
    FascicoloMessageItem,
    FascicoloRemoveMessagesRequest,
    FascicoloResponse,
    FascicoloUpdate,
    MessageFascicoloSummary,
)
from app.services.fascicolo_service import FascicoloService

router = APIRouter(tags=["Fascicoli"])


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

def _to_response(fascicolo, message_count: int) -> FascicoloResponse:
    resp = FascicoloResponse.model_validate(fascicolo)
    resp.message_count = int(message_count)
    return resp


# ─── CRUD Fascicolo ───────────────────────────────────────────────────────────

@router.get("/fascicoli", response_model=list[FascicoloResponse])
async def list_fascicoli(
    current_user: CurrentUser,
    db: DB,
    stato: Optional[str] = Query(None, pattern=r"^(aperto|chiuso|archiviato)$"),
    responsabile_id: Optional[uuid.UUID] = Query(None),
    search: Optional[str] = Query(None, max_length=200),
) -> list[FascicoloResponse]:
    """Elenca i fascicoli del tenant con filtri opzionali."""
    svc = FascicoloService(db)
    rows = await svc.list_fascicoli(
        current_user.tenant_id,
        stato=stato,
        responsabile_id=responsabile_id,
        search=search,
    )
    return [_to_response(f, cnt) for f, cnt in rows]


@router.post("/fascicoli", response_model=FascicoloResponse, status_code=status.HTTP_201_CREATED)
async def create_fascicolo(
    data: FascicoloCreate,
    current_user: CurrentUser,
    db: DB,
) -> FascicoloResponse:
    """Crea un nuovo fascicolo."""
    svc = FascicoloService(db)
    fascicolo, cnt = await svc.create_fascicolo(
        current_user.tenant_id, data, created_by=current_user.id
    )
    return _to_response(fascicolo, cnt)


@router.get("/fascicoli/{fascicolo_id}", response_model=FascicoloResponse)
async def get_fascicolo(
    fascicolo_id: uuid.UUID,
    current_user: CurrentUser,
    db: DB,
) -> FascicoloResponse:
    """Restituisce il dettaglio di un fascicolo."""
    svc = FascicoloService(db)
    fascicolo, cnt = await svc.get_fascicolo(current_user.tenant_id, fascicolo_id)
    return _to_response(fascicolo, cnt)


@router.patch("/fascicoli/{fascicolo_id}", response_model=FascicoloResponse)
async def update_fascicolo(
    fascicolo_id: uuid.UUID,
    data: FascicoloUpdate,
    current_user: CurrentUser,
    db: DB,
) -> FascicoloResponse:
    """
    Modifica un fascicolo.
    Solo il creatore o un amministratore possono modificarlo.
    """
    svc = FascicoloService(db)
    fascicolo, cnt = await svc.update_fascicolo(
        current_user.tenant_id,
        fascicolo_id,
        data,
        current_user_id=current_user.id,
        is_admin=current_user.is_admin,
    )
    return _to_response(fascicolo, cnt)


@router.delete("/fascicoli/{fascicolo_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_fascicolo(
    fascicolo_id: uuid.UUID,
    current_user: AdminUser,
    db: DB,
) -> None:
    """Elimina un fascicolo (solo admin). I messaggi non vengono eliminati."""
    svc = FascicoloService(db)
    await svc.delete_fascicolo(current_user.tenant_id, fascicolo_id)


# ─── Messaggi del fascicolo ───────────────────────────────────────────────────

@router.get("/fascicoli/{fascicolo_id}/messages", response_model=list[FascicoloMessageItem])
async def get_fascicolo_messages(
    fascicolo_id: uuid.UUID,
    current_user: CurrentUser,
    db: DB,
) -> list[FascicoloMessageItem]:
    """Restituisce i messaggi collegati al fascicolo."""
    svc = FascicoloService(db)
    rows = await svc.get_fascicolo_messages(current_user.tenant_id, fascicolo_id)
    items = []
    for msg, added_at in rows:
        item = FascicoloMessageItem(
            id=msg.id,
            subject=msg.subject,
            from_address=msg.from_address,
            to_addresses=msg.to_addresses,
            direction=msg.direction,
            pec_type=msg.pec_type,
            state=msg.state,
            mailbox_id=msg.mailbox_id,
            received_at=msg.received_at,
            sent_at=msg.sent_at,
            created_at=msg.created_at,
            added_at=added_at,
        )
        items.append(item)
    return items


@router.post("/fascicoli/{fascicolo_id}/messages", response_model=dict)
async def add_messages_to_fascicolo(
    fascicolo_id: uuid.UUID,
    data: FascicoloAddMessagesRequest,
    current_user: CurrentUser,
    db: DB,
) -> dict:
    """
    Aggiunge messaggi al fascicolo.
    Ignora i messaggi non del tenant o gia' presenti.
    """
    svc = FascicoloService(db)
    added = await svc.add_messages(
        current_user.tenant_id,
        fascicolo_id,
        data.message_ids,
        added_by=current_user.id,
    )
    return {"added": added}


@router.delete("/fascicoli/{fascicolo_id}/messages", response_model=dict)
async def remove_messages_from_fascicolo(
    fascicolo_id: uuid.UUID,
    data: FascicoloRemoveMessagesRequest,
    current_user: CurrentUser,
    db: DB,
) -> dict:
    """Rimuove messaggi dal fascicolo (non li elimina dalla posta)."""
    svc = FascicoloService(db)
    removed = await svc.remove_messages(
        current_user.tenant_id,
        fascicolo_id,
        data.message_ids,
    )
    return {"removed": removed}


# ─── Fascicoli di un messaggio ────────────────────────────────────────────────

@router.get("/messages/{message_id}/fascicoli", response_model=list[MessageFascicoloSummary])
async def get_message_fascicoli(
    message_id: uuid.UUID,
    current_user: CurrentUser,
    db: DB,
) -> list[MessageFascicoloSummary]:
    """Restituisce i fascicoli a cui appartiene un messaggio."""
    # Verifica che il messaggio esista nel tenant
    result = await db.execute(
        select(Message).where(
            Message.id == message_id,
            Message.tenant_id == current_user.tenant_id,
        )
    )
    if not result.scalar_one_or_none():
        raise NotFoundError(f"Messaggio {message_id} non trovato")

    svc = FascicoloService(db)
    fascicoli = await svc.get_message_fascicoli(current_user.tenant_id, message_id)
    return [MessageFascicoloSummary.model_validate(f) for f in fascicoli]
