import apiClient from './client' import type { AttachmentResponse, MessageListResponse, MessageResponse, } from '@/types/api.types' export interface MessageFilters { page?: number page_size?: number /** Filtra per Virtual Box assegnata all'utente corrente */ vbox_id?: string mailbox_id?: string direction?: 'inbound' | 'outbound' state?: string pec_type?: string is_read?: boolean is_starred?: boolean is_archived?: boolean is_trashed?: boolean /** Filtra per messaggi in attesa di conservazione (cartella Da Conservare) */ is_pending_conservation?: boolean /** Filtra per messaggi gia' conservati (cartella Storico) */ is_conserved?: boolean search?: string /** Data minima nel formato ISO 8601 (es. "2026-01-01T00:00:00Z") */ date_from?: string /** Data massima nel formato ISO 8601 */ date_to?: string } export interface MessageBulkUpdatePayload { ids: string[] is_read?: boolean is_starred?: boolean is_archived?: boolean is_trashed?: boolean is_pending_conservation?: boolean is_conserved?: boolean } export interface MessageUpdatePayload { is_read?: boolean is_starred?: boolean is_archived?: boolean is_trashed?: boolean is_pending_conservation?: boolean is_conserved?: boolean /** Rischio e Riservatezza (N3) — stringa vuota per resettare a null */ risk_level?: string confidentiality?: string } export interface MessageBulkUpdateResponse { updated: number items: MessageResponse[] } export const messagesApi = { list: (filters: MessageFilters = {}) => apiClient .get('/messages', { params: filters }) .then((r) => r.data), get: (id: string) => apiClient.get(`/messages/${id}`).then((r) => r.data), markRead: (id: string) => apiClient.patch(`/messages/${id}`, { is_read: true }).then((r) => r.data), markUnread: (id: string) => apiClient.patch(`/messages/${id}`, { is_read: false }).then((r) => r.data), toggleStar: (id: string, starred: boolean) => apiClient .patch(`/messages/${id}`, { is_starred: starred }) .then((r) => r.data), archive: (id: string) => apiClient .patch(`/messages/${id}`, { is_archived: true }) .then((r) => r.data), unarchive: (id: string) => apiClient .patch(`/messages/${id}`, { is_archived: false }) .then((r) => r.data), trash: (id: string) => apiClient .patch(`/messages/${id}`, { is_trashed: true }) .then((r) => r.data), untrash: (id: string) => apiClient .patch(`/messages/${id}`, { is_trashed: false }) .then((r) => r.data), /** Sposta un messaggio nella cartella Da Conservare */ conserve: (id: string) => apiClient .patch(`/messages/${id}`, { is_pending_conservation: true }) .then((r) => r.data), /** Rimuove un messaggio dalla cartella Da Conservare */ unconserve: (id: string) => apiClient .patch(`/messages/${id}`, { is_pending_conservation: false }) .then((r) => r.data), /** Aggiorna uno o piu' campi del messaggio (PATCH generico) — include risk_level/confidentiality (N3) */ update: (id: string, payload: MessageUpdatePayload) => apiClient .patch(`/messages/${id}`, payload) .then((r) => r.data), /** Aggiorna in blocco is_starred e/o is_archived e/o is_trashed su più messaggi */ bulkUpdate: (payload: MessageBulkUpdatePayload) => apiClient .patch('/messages/bulk', payload) .then((r) => r.data), getAttachments: (id: string) => apiClient.get(`/messages/${id}/attachments`).then((r) => r.data), /** * Scarica un allegato autenticato e lo salva localmente. * Utilizza apiClient (con Bearer token) per evitare il 401 che si ottiene * navigando direttamente verso l'URL con un . */ downloadAttachment: async (messageId: string, attachmentId: string, filename: string): Promise => { const response = await apiClient.get( `/messages/${messageId}/attachments/${attachmentId}/download`, { responseType: 'blob' }, ) const blobUrl = window.URL.createObjectURL(new Blob([response.data])) const anchor = document.createElement('a') anchor.href = blobUrl anchor.setAttribute('download', filename) document.body.appendChild(anchor) anchor.click() anchor.remove() window.URL.revokeObjectURL(blobUrl) }, getReceipts: (id: string) => apiClient.get(`/messages/${id}/receipts`).then((r) => r.data), // ─── Feature 3: Thread ──────────────────────────────────────────────────── getThread: (id: string) => apiClient.get(`/messages/${id}/thread`).then((r) => r.data), // ─── Feature 7: Preview allegati ───────────────────────────────────────── getAttachmentPreviewUrl: (messageId: string, attachmentId: string) => apiClient.get<{ previewable: boolean content_type: string filename: string url?: string }>(`/messages/${messageId}/attachments/${attachmentId}/preview-url`).then((r) => r.data), // ─── Feature 8: Stampa ──────────────────────────────────────────────────── /** Apre la vista di stampa HTML in una nuova tab. */ openPrint: (messageId: string, token: string) => { const baseUrl = (window as any).__API_BASE_URL__ || '/api/v1' window.open(`${baseUrl}/messages/${messageId}/print?token=${token}`, '_blank') }, /** * Scarica il pacchetto ZIP completo della PEC (postacert.eml, daticert.xml, * ricevute di accettazione/consegna per le mail outbound). */ downloadPackage: async (messageId: string, subject?: string | null): Promise => { const response = await apiClient.get( `/messages/${messageId}/download-package`, { responseType: 'blob' }, ) const blobUrl = window.URL.createObjectURL(new Blob([response.data], { type: 'application/zip' })) const anchor = document.createElement('a') anchor.href = blobUrl const safeSubject = (subject || 'pec').replace(/[/\\]/g, '_').slice(0, 50) anchor.setAttribute('download', `pec_${safeSubject}.zip`) document.body.appendChild(anchor) anchor.click() anchor.remove() window.URL.revokeObjectURL(blobUrl) }, }