import React, { useState } from "react"; import { ApiService } from "../utils/apiService"; import { debugLog } from "../utils/config"; import DataViewer from "./DataViewer"; const Step4 = ({ apiKey, s3Link, config: generationConfig, fileMetadata, generatedDataLink, setGeneratedDataLink, stepNumber, stepTitle, stepIcon, enabled = true, }) => { const [isGenerating, setIsGenerating] = useState(false); const [generationStatus, setGenerationStatus] = useState(""); const [generationProgress, setGenerationProgress] = useState(0); const [hasError, setHasError] = useState(false); const [errorMessage, setErrorMessage] = useState(""); const generateSyntheticData = async () => { // Prevent action if step is disabled if (!enabled) { debugLog("Generation attempted but step is disabled"); return; } setIsGenerating(true); setGenerationStatus("Initializing generation..."); setGenerationProgress(0); setHasError(false); setErrorMessage(""); try { debugLog("Starting synthetic data generation", { s3Link, config: generationConfig, fileMetadata, apiKeyPrefix: apiKey.substring(0, 8) + "...", }); // Use the ApiService with retry logic const result = await ApiService.retryRequest(async () => { // Update progress during API call setGenerationStatus("Sending request to AI model..."); setGenerationProgress(10); return await ApiService.generateSyntheticData(apiKey, s3Link, { ...generationConfig, fileSizeBytes: fileMetadata?.fileSizeBytes || 0, sourceFileRows: fileMetadata?.sourceFileRows || 0, }); }); // If the API returns progress updates, handle them if (result.jobId) { // For now, simulate progress since polling is not implemented await simulateProgress(); // In a real implementation, you would poll for job status here setGeneratedDataLink( result.data?.fileUrl || result.fileUrl || result.download_link || result.link || result.s3_url ); } else { // Simulate progress for immediate results await simulateProgress(); // Handle the specific response format: { "status": "success", "data": { "fileUrl": "..." } } const dataLink = result.data?.fileUrl || result.fileUrl || result.s3_url || result.download_link || result.link; if (!dataLink) { throw new Error( "No download link received from the API. The generation may have failed on the server side." ); } setGeneratedDataLink(dataLink); } setGenerationStatus("Generation completed successfully!"); setGenerationProgress(100); debugLog("Synthetic data generation completed", { downloadLink: result.data?.fileUrl || result.fileUrl || result.s3_url || result.download_link || result.link, status: result.status, message: result.message, fullResult: result, }); } catch (error) { debugLog("Synthetic data generation failed", error); setHasError(true); setGenerationProgress(0); // Create a user-friendly error message let friendlyErrorMessage = "An error occurred during generation."; if (error.message.includes("403") || error.message.includes("401")) { friendlyErrorMessage = "Authentication failed. Please check your API key and try again."; } else if (error.message.includes("404")) { friendlyErrorMessage = "Generation service not found. Please try again later."; } else if (error.message.includes("500")) { friendlyErrorMessage = "Server error occurred. The service may be temporarily unavailable."; } else if ( error.message.includes("timeout") || error.message.includes("TimeoutError") ) { friendlyErrorMessage = "Request timed out. The generation process may take longer than expected. Please try again."; } else if ( error.message.includes("Network") || error.message.includes("fetch") ) { friendlyErrorMessage = "Network error. Please check your internet connection and try again."; } else if (error.message.includes("No download link")) { friendlyErrorMessage = "Generation completed but no download link was provided. Please try generating again."; } else if (error.message) { friendlyErrorMessage = error.message; } setErrorMessage(friendlyErrorMessage); setGenerationStatus(`❌ Generation failed: ${friendlyErrorMessage}`); } finally { setIsGenerating(false); } }; const simulateProgress = async () => { const steps = [ { progress: 25, message: "Analyzing data structure..." }, { progress: 50, message: "Training AI model..." }, { progress: 75, message: "Generating synthetic data..." }, { progress: 90, message: "Finalizing output..." }, ]; for (const step of steps) { setGenerationProgress(step.progress); setGenerationStatus(step.message); await new Promise((resolve) => setTimeout(resolve, 1500)); } }; const handleDownload = () => { if (generatedDataLink) { debugLog("Downloading generated data", { link: generatedDataLink }); // Open in new tab so user can see if download works const newWindow = window.open(generatedDataLink, "_blank"); // If popup blocked, provide fallback if (!newWindow) { // Fallback: create a temporary download link const link = document.createElement("a"); link.href = generatedDataLink; link.download = `synthetic_data_${Date.now()}.csv`; document.body.appendChild(link); link.click(); document.body.removeChild(link); } } }; const handleCopyLink = async () => { if (generatedDataLink) { try { await navigator.clipboard.writeText(generatedDataLink); // You could add a toast notification here debugLog("Link copied to clipboard"); } catch (error) { debugLog("Failed to copy link:", error); // Fallback for older browsers const textArea = document.createElement("textarea"); textArea.value = generatedDataLink; document.body.appendChild(textArea); textArea.select(); document.execCommand("copy"); document.body.removeChild(textArea); } } }; const isReadyForGeneration = apiKey && s3Link && generationConfig.targetColumn && generationConfig.numRows; return (

{stepNumber} {stepIcon} {stepTitle}

Generate high-quality synthetic data based on your configuration

{!generatedDataLink && !isGenerating && !hasError && (
{isReadyForGeneration ? "✅" : "⚠️"}

{isReadyForGeneration ? "Ready for Generation" : "Configuration Required"}

{!isReadyForGeneration && (

Please complete all previous steps before generating data.

)}
🔑 API Key: {apiKey ? "✓ Valid" : "⚠ Required"}
📊 Data: {s3Link ? "✓ Uploaded" : "⚠ Required"}
🎯 Target: {generationConfig.targetColumn ? `✓ ${generationConfig.targetColumn}` : "⚠ Not set"}
📥 Source: {fileMetadata?.sourceFileRows || 0} rows
📤 Generate: {generationConfig.numRows} rows
)} {isGenerating && (
{generationStatus}
{generationProgress}% Complete • This may take a few minutes
)} {hasError && !isGenerating && (

Generation Failed

There was an error generating your synthetic data.

Error: {errorMessage}
What you can try:
  • Check your internet connection and try again
  • Verify your API key is valid and has sufficient credits
  • Try reducing the number of rows to generate
  • Contact support if the problem persists
)} {generatedDataLink && !isGenerating && (
🎉

Generation Complete!

Successfully generated {generationConfig.numRows} rows of synthetic data targeting the{" "} {generationConfig.targetColumn} column.

📊 Data Preview

💡 Showing preview of first few rows. Download the complete file ({generationConfig.numRows} rows) using the button above.
)}
); }; export default Step4;