import { buildApiUrl, API_BASE_URL, API_ENDPOINTS } from "../config/api"; import { DocumentoChecksum, DocumentosChecksumsResponse, ReservaDocumentos } from "../types"; import AsyncStorage from "@react-native-async-storage/async-storage"; import * as FileSystem from "expo-file-system/legacy"; const DOCUMENTOS_DIR = `${FileSystem.documentDirectory}documentos/`; // Devolve o caminho local de um documento const getLocalPath = (idDocumento: string, caminhoFicheiro: string): string => { const fileName = caminhoFicheiro.split("/").pop() || `documento_${idDocumento}.pdf`; return `${DOCUMENTOS_DIR}${idDocumento}_${fileName}`; }; // Garante que o diretório de documentos existe const ensureDir = async (): Promise => { const info = await FileSystem.getInfoAsync(DOCUMENTOS_DIR); if (!info.exists) { await FileSystem.makeDirectoryAsync(DOCUMENTOS_DIR, { intermediates: true }); } }; // Constrói URL completa a partir de um caminho relativo const buildUrl = (path: string | null | undefined): string => { if (!path) return ""; if (path.startsWith("http")) return path; const base = API_BASE_URL.replace(/\/pt\/app$/, ""); return `${base}${path.startsWith("/") ? path : `/${path}`}`; }; // Checksum guardado localmente para um documento export const getStoredChecksum = async (idDocumento: string): Promise => { try { return await AsyncStorage.getItem(`@cruiseLovers:documento:${idDocumento}:checksum`); } catch { return null; } }; // Guarda o checksum localmente export const saveStoredChecksum = async (idDocumento: string, checksum: string): Promise => { try { await AsyncStorage.setItem(`@cruiseLovers:documento:${idDocumento}:checksum`, checksum); } catch { // silencioso } }; /** * Devolve o URI local de um documento se este já estiver descarregado, ou null caso contrário. */ export const getLocalDocumentUri = async (idDocumento: string, caminhoFicheiro: string): Promise => { try { const localPath = getLocalPath(idDocumento, caminhoFicheiro); const info = await FileSystem.getInfoAsync(localPath); return info.exists ? localPath : null; } catch { return null; } }; // Faz download de um único documento export const downloadDocumento = async (documento: DocumentoChecksum): Promise => { try { const url = buildUrl(documento.caminhoFicheiro); if (!url) return null; await ensureDir(); const localPath = getLocalPath(documento.idDocumento, documento.caminhoFicheiro); const result = await FileSystem.downloadAsync(url, localPath); if (result.status < 200 || result.status >= 300) { console.error(`Download falhou com status ${result.status}`); return null; } if (documento.checksum) { await saveStoredChecksum(documento.idDocumento, documento.checksum); } return localPath; } catch (error) { console.error("Erro ao fazer download:", error); return null; } }; // Busca checksums do servidor export const getDocumentosChecksums = async (token: string): Promise => { try { const formData = new FormData(); formData.append("token", token); const response = await fetch(buildApiUrl(API_ENDPOINTS.GET_DOCUMENTOS_CHECKSUMS), { method: "POST", headers: { Accept: "application/json" }, body: formData, }); return (await response.json()) as DocumentosChecksumsResponse; } catch (error) { console.error("Erro ao buscar checksums de documentos:", error); return null; } }; // Verifica quais documentos precisam ser (re)descarregados export const verificarDocumentosParaDownload = async ( reservaDocumentos: ReservaDocumentos[] ): Promise => { const para: DocumentoChecksum[] = []; for (const reserva of reservaDocumentos) { for (const doc of reserva.documentos) { if (!doc.caminhoFicheiro || !doc.checksum) continue; const storedChecksum = await getStoredChecksum(doc.idDocumento); const localPath = getLocalPath(doc.idDocumento, doc.caminhoFicheiro); const info = await FileSystem.getInfoAsync(localPath); if (doc.checksum !== storedChecksum || !info.exists) { para.push(doc); } } } return para; }; /** Remove documentos descarregados e checksums (ex.: no logout). */ export const clearDownloadedDocuments = async (): Promise => { try { const keys = await AsyncStorage.getAllKeys(); const docKeys = keys.filter((key) => key.startsWith("@cruiseLovers:documento:")); if (docKeys.length > 0) { await AsyncStorage.multiRemove(docKeys); } const info = await FileSystem.getInfoAsync(DOCUMENTOS_DIR); if (info.exists) { await FileSystem.deleteAsync(DOCUMENTOS_DIR, { idempotent: true }); } } catch (error) { console.error("Erro ao limpar documentos locais:", error); } }; // Descarrega múltiplos documentos export const downloadDocumentos = async ( documentos: DocumentoChecksum[], onProgress?: (current: number, total: number) => void ): Promise<{ sucesso: number; falhas: number }> => { let sucesso = 0; let falhas = 0; for (let i = 0; i < documentos.length; i++) { if (onProgress) onProgress(i + 1, documentos.length); const resultado = await downloadDocumento(documentos[i]); resultado ? sucesso++ : falhas++; } return { sucesso, falhas }; };