import apiClient from "./client"; import type { GenerateResponse, BatchResponse, MatrixGenerateResponse, TestingMatrixResponse, AnglesResponse, ConceptsResponse, CompatibleConceptsResponse, AngleInfo, ConceptInfo, DbStatsResponse, AdsListResponse, AdCreativeDB, HealthResponse, ApiRootResponse, ImageCorrectResponse, ImageRegenerateResponse, ModelsListResponse, LoginResponse, Niche, CreativeAnalysisResponse, CreativeModifyResponse, FileUploadResponse, ModificationMode, CreativeAnalysisData, MotivatorGenerateRequest, MotivatorGenerateResponse, } from "../../types/api"; // Health & Info export const getHealth = async (): Promise => { const response = await apiClient.get("/health"); return response.data; }; export const getApiInfo = async (): Promise => { const response = await apiClient.get("/"); return response.data; }; // Generation Endpoints export const generateAd = async (params: { niche: Niche; num_images: number; image_model?: string | null; target_audience?: string | null; offer?: string | null; use_trending?: boolean; trending_context?: string | null; }): Promise => { const response = await apiClient.post("/generate", params); return response.data; }; export const generateBatch = async (params: { niche: Niche; count: number; image_model?: string | null; method?: "standard" | "matrix" | null; target_audience?: string | null; offer?: string | null; }): Promise => { const response = await apiClient.post("/generate/batch", params); return response.data; }; // Matrix Endpoints export const generateMatrixAd = async (params: { niche: Niche; angle_key?: string | null; concept_key?: string | null; custom_angle?: string | null; custom_concept?: string | null; num_images: number; image_model?: string | null; target_audience?: string | null; offer?: string | null; core_motivator?: string; }): Promise => { const response = await apiClient.post("/matrix/generate", params); return response.data; }; export const generateMotivators = async ( params: MotivatorGenerateRequest ): Promise => { const response = await apiClient.post( "/api/motivator/generate", { ...params, count: params.count ?? 6 } ); return response.data; }; // Extensive Endpoints (async job pattern to avoid connection timeout on HF Spaces) const EXTENSIVE_POLL_INTERVAL_MS = 5500; const EXTENSIVE_POLL_TIMEOUT_MS = 20 * 60 * 1000; // 20 minutes export const getExtensiveJobStatus = async (jobId: string): Promise<{ job_id: string; status: "running" | "completed" | "failed"; error?: string }> => { const response = await apiClient.get(`/extensive/status/${jobId}`); return response.data; }; export const getExtensiveJobResult = async (jobId: string): Promise => { const response = await apiClient.get(`/extensive/result/${jobId}`); return response.data; }; export const generateExtensiveAd = async (params: { niche: Niche; custom_niche?: string | null; target_audience?: string | null; offer?: string | null; num_images: number; image_model?: string | null; num_strategies: number; }): Promise => { const requestParams = { niche: params.niche, num_images: params.num_images || 1, num_strategies: params.num_strategies || 1, ...(params.custom_niche && { custom_niche: params.custom_niche }), ...(params.target_audience && { target_audience: params.target_audience }), ...(params.offer && { offer: params.offer }), ...(params.image_model && { image_model: params.image_model }), }; const response = await apiClient.post<{ job_id: string; message?: string }>("/extensive/generate", requestParams); const jobId = response.data?.job_id; if (!jobId) { throw new Error("Server did not return a job ID"); } const deadline = Date.now() + EXTENSIVE_POLL_TIMEOUT_MS; for (;;) { const status = await getExtensiveJobStatus(jobId); if (status.status === "completed") { return getExtensiveJobResult(jobId); } if (status.status === "failed") { throw new Error(status.error || "Extensive generation failed"); } if (Date.now() >= deadline) { throw new Error("Extensive generation timed out. Try fewer strategies or images."); } await new Promise((r) => setTimeout(r, EXTENSIVE_POLL_INTERVAL_MS)); } }; export const generateTestingMatrix = async (params: { niche: Niche; angle_count: number; concept_count: number; strategy: "balanced" | "top_performers" | "diverse"; }): Promise => { const response = await apiClient.post("/matrix/testing", params); return response.data; }; export const getAllAngles = async (): Promise => { const response = await apiClient.get("/matrix/angles"); return response.data; }; export const getAllConcepts = async (): Promise => { const response = await apiClient.get("/matrix/concepts"); return response.data; }; export const getAngle = async (angleKey: string): Promise => { const response = await apiClient.get(`/matrix/angle/${angleKey}`); return response.data; }; export const getConcept = async (conceptKey: string): Promise => { const response = await apiClient.get(`/matrix/concept/${conceptKey}`); return response.data; }; export const getCompatibleConcepts = async (angleKey: string): Promise => { const response = await apiClient.get(`/matrix/compatible/${angleKey}`); return response.data; }; // Refine custom angle or concept using AI export const refineCustomAngleOrConcept = async (params: { text: string; type: "angle" | "concept"; niche: Niche; goal?: string; }): Promise<{ status: string; type: "angle" | "concept"; refined?: any; error?: string }> => { const response = await apiClient.post("/matrix/refine-custom", params); return response.data; }; // Database Endpoints export const getDbStats = async (): Promise => { const response = await apiClient.get("/db/stats"); return response.data; }; export const listAds = async (params?: { niche?: string | null; generation_method?: string | null; limit?: number; offset?: number; }): Promise => { const response = await apiClient.get("/db/ads", { params }); return response.data; }; export const getAd = async (adId: string): Promise => { const response = await apiClient.get(`/db/ad/${adId}`); return response.data; }; export const deleteAd = async (adId: string): Promise<{ success: boolean; deleted_id: string }> => { const response = await apiClient.delete<{ success: boolean; deleted_id: string }>(`/db/ad/${adId}`); return response.data; }; // Strategies export const getStrategies = async (niche: Niche): Promise => { const response = await apiClient.get(`/strategies/${niche}`); return response.data; }; // Image Correction Endpoints export const correctImage = async (params: { image_id: string; image_url?: string; user_instructions?: string; auto_analyze?: boolean; }): Promise => { const response = await apiClient.post("/api/correct", params); return response.data; }; // Image Regeneration Endpoints export const regenerateImage = async (params: { image_id: string; image_model?: string | null; preview_only?: boolean; }): Promise => { const response = await apiClient.post("/api/regenerate", { ...params, preview_only: params.preview_only ?? true, // Default to preview mode }); return response.data; }; // Confirm Image Selection after Regeneration export const confirmImageSelection = async (params: { image_id: string; selection: "new" | "original"; new_image_url?: string | null; new_r2_url?: string | null; new_filename?: string | null; new_model?: string | null; new_seed?: number | null; }): Promise<{ status: string; message: string; selection: string; new_image_url?: string }> => { const response = await apiClient.post("/api/regenerate/confirm", params); return response.data; }; // Get Available Image Models export const getImageModels = async (): Promise => { const response = await apiClient.get("/api/models"); return response.data; }; // Auth Endpoints export const login = async (username: string, password: string): Promise => { const response = await apiClient.post("/auth/login", { username, password, }); return response.data; }; // Edit Ad Copy Endpoint export const editAdCopy = async (params: { ad_id: string; field: "title" | "headline" | "primary_text" | "description" | "body_story" | "cta"; value: string; mode: "manual" | "ai"; user_suggestion?: string; }): Promise<{ edited_value: string; success: boolean }> => { const response = await apiClient.post<{ edited_value: string; success: boolean }>("/db/ad/edit", params); return response.data; }; // Download Image Endpoint (proxy to avoid CORS) export const downloadImageProxy = async (params: { image_url?: string; image_id?: string; }): Promise => { const response = await apiClient.get("/api/download-image", { params, responseType: "blob", }); return response.data as Blob; }; // Creative Modifier Endpoints // Upload a creative image export const uploadCreative = async (file: File): Promise => { const formData = new FormData(); formData.append("file", file); const response = await apiClient.post( "/api/creative/upload", formData, { headers: { "Content-Type": "multipart/form-data", }, } ); return response.data; }; // Analyze a creative image (via URL) export const analyzeCreativeByUrl = async (params: { image_url: string; }): Promise => { const response = await apiClient.post( "/api/creative/analyze", params ); return response.data; }; // Analyze a creative image (via file upload) export const analyzeCreativeByFile = async ( file: File ): Promise => { const formData = new FormData(); formData.append("file", file); const response = await apiClient.post( "/api/creative/analyze/upload", formData, { headers: { "Content-Type": "multipart/form-data", }, } ); return response.data; }; // Modify a creative with new angle/concept export const modifyCreative = async (params: { image_url: string; analysis?: CreativeAnalysisData | null; angle?: string; concept?: string; mode: ModificationMode; image_model?: string | null; user_prompt?: string; }): Promise => { const response = await apiClient.post( "/api/creative/modify", params ); return response.data; }; // Bulk Export Endpoint export const exportBulkAds = async (adIds: string[]): Promise => { const response = await apiClient.post( "/api/export/bulk", { ad_ids: adIds }, { responseType: "blob" } ); return response.data as Blob; };