import { IExpenseRequest, IExpenseResponse } from "../types"; import { API_BASE_URL, EXPENSE_WEBHOOK_ENDPOINT } from "../utils/constants"; import * as FileSystem from "expo-file-system"; export class ExpenseService { private static readonly API_URL = `${API_BASE_URL}${EXPENSE_WEBHOOK_ENDPOINT}`; static async sendExpenseData( data: IExpenseRequest ): Promise { try { const response = await fetch(this.API_URL, { method: "POST", headers: { "Content-Type": "application/json", Accept: "application/json", }, body: JSON.stringify(data), }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const result = await response.json(); return result; } catch (error) { console.error("Error sending expense data:", error); throw new Error( error instanceof Error ? error.message : "Có lỗi xảy ra khi gửi dữ liệu" ); } } static async sendAudioExpense(audioUri: string): Promise { try { // Send audio file as multipart/form-data for n8n workflow return await this.sendAudioToN8N(audioUri); } catch (error) { console.error("Error sending audio expense:", error); throw error; } } static async sendTextExpense(text: string): Promise { try { const requestData: IExpenseRequest = { textInput: text, timestamp: new Date().toISOString(), }; return await this.sendExpenseData(requestData); } catch (error) { console.error("Error sending text expense:", error); throw error; } } private static async sendAudioToN8N( audioUri: string ): Promise { try { const formData = new FormData(); // Get file info const fileInfo = await FileSystem.getInfoAsync(audioUri); if (!fileInfo.exists) { throw new Error("File audio không tồn tại"); } console.log("File info:", fileInfo); console.log("Audio URI:", audioUri); // Extract file name and extension const fileName = audioUri.split("/").pop() || `recording_${Date.now()}.m4a`; const fileExtension = fileName.split(".").pop() || "m4a"; const mimeType = "audio/x-m4a"; const fileSizeBytes = fileInfo.size || 0; const fileSizeMB = (fileSizeBytes / (1024 * 1024)).toFixed(2); // Try different approaches for React Native file upload let audioFile: any; if (audioUri.startsWith("file://")) { // For local files, create proper file object audioFile = { uri: audioUri, type: mimeType, name: fileName, }; } else { // Fallback: read as base64 and convert const base64Data = await FileSystem.readAsStringAsync(audioUri, { encoding: FileSystem.EncodingType.Base64, }); audioFile = { uri: `data:${mimeType};base64,${base64Data}`, type: mimeType, name: fileName, }; } // Append audio file to form data (n8n sẽ nhận như binary data) formData.append("audioFile", audioFile as any); // Append metadata as separate fields formData.append("timestamp", new Date().toISOString()); formData.append("fileName", fileName); formData.append("fileExtension", fileExtension); formData.append("mimeType", mimeType); formData.append("fileSizeBytes", fileSizeBytes.toString()); formData.append("fileSizeMB", `${fileSizeMB} MB`); console.log("File metadata:", { fileName, fileExtension, mimeType, fileSizeBytes, fileSizeMB: `${fileSizeMB} MB`, }); console.log("Sending FormData to:", this.API_URL); const response = await fetch(this.API_URL, { method: "POST", // Không set Content-Type header - fetch sẽ tự động set với boundary body: formData, }); console.log("Response status:", response.status); console.log("Response headers:", response.headers); if (!response.ok) { const errorText = await response.text(); console.error("Error response:", errorText); throw new Error( `HTTP error! status: ${response.status}, message: ${errorText}` ); } const result = await response.json(); return result; } catch (error) { console.error("Error sending audio to n8n:", error); throw new Error( error instanceof Error ? error.message : "Có lỗi xảy ra khi gửi audio" ); } } private static async convertAudioToBase64(audioUri: string): Promise { try { const base64 = await FileSystem.readAsStringAsync(audioUri, { encoding: FileSystem.EncodingType.Base64, }); return base64; } catch (error) { console.error("Error converting audio to base64:", error); throw new Error("Không thể chuyển đổi file audio"); } } }