import React, { useEffect, useState, useCallback } from 'react'; import { Box, Typography, Alert, Container, CircularProgress, Stack, Card, CardContent, Chip, Fade, Divider, } from '@mui/material'; import { CheckCircleOutline as CheckCircleIcon, ErrorOutline as ErrorIcon, InfoOutlined as InfoIcon, WarningAmberOutlined as WarningIcon, Key as KeyIcon, Star as StarIcon, } from '@mui/icons-material'; import OnboardingButton from './common/OnboardingButton'; import { apiClient } from '../../api/client'; import { useSubscription } from '../../contexts/SubscriptionContext'; interface ApiKeyValidationStepProps { onContinue: (stepData?: any) => void; updateHeaderContent: (content: { title: string; description: string }) => void; onValidationChange?: (isValid: boolean) => void; } interface ApiKeyStatus { valid: boolean; status: 'configured' | 'missing' | 'invalid' | 'checking'; error?: string; } interface ValidationResponse { api_keys: Record; validation_results: Record; all_valid: boolean; total_providers: number; configured_providers: string[]; missing_keys: string[]; } const ApiKeyValidationStep: React.FC = ({ onContinue, updateHeaderContent, onValidationChange, }) => { const [loading, setLoading] = useState(true); const [validationData, setValidationData] = useState(null); const [error, setError] = useState(null); const [isValid, setIsValid] = useState(false); const { subscription } = useSubscription(); const validateApiKeys = useCallback(async () => { setLoading(true); setError(null); try { const response = await apiClient.get('/api/onboarding/api-keys/validate'); setValidationData(response.data); setIsValid(response.data.all_valid); if (onValidationChange) { onValidationChange(response.data.all_valid); } } catch (err: any) { console.error('Error validating API keys:', err); setError(err.response?.data?.detail || 'Failed to validate API keys. Please check backend logs.'); setIsValid(false); if (onValidationChange) { onValidationChange(false); } } finally { setLoading(false); } }, [onValidationChange]); useEffect(() => { updateHeaderContent({ title: 'API Keys Configured', description: 'Your AI service API keys have been successfully configured in the backend environment.', }); validateApiKeys(); }, [updateHeaderContent, validateApiKeys]); const handleContinue = () => { if (isValid) { onContinue(); } }; const getStatusIcon = (status: 'configured' | 'missing' | 'invalid' | 'checking') => { switch (status) { case 'configured': return ; case 'missing': return ; case 'invalid': return ; case 'checking': return ; default: return ; } }; const getStatusColor = (status: 'configured' | 'missing' | 'invalid' | 'checking') => { switch (status) { case 'configured': return 'success'; case 'missing': return 'warning'; case 'invalid': return 'error'; case 'checking': return 'info'; default: return 'info'; } }; const formatProviderName = (provider: string) => { return provider .replace(/_API_KEY/g, '') .replace(/_/g, ' ') .replace(/\b\w/g, l => l.toUpperCase()); }; return ( API Key Validation {loading && ( Validating API key configurations... )} {!loading && error && ( {error} )} {!loading && validationData && ( {isValid ? ( All API Keys Configured Successfully! Your AI services are ready to use. You can now proceed to the next step. {/* Subscription Plan Details */} {subscription && ( Your Subscription Plan {subscription.active ? 'Active' : 'Inactive'} Monthly API calls: {subscription.limits.gemini_calls.toLocaleString()} Gemini, {subscription.limits.openai_calls.toLocaleString()} OpenAI )} ) : ( Some required API keys are missing or invalid. Please configure them in your backend .env file. )} {/* Compact API Key Status Grid */} {Object.entries(validationData.validation_results).map(([provider, status]) => ( {formatProviderName(provider)} {getStatusIcon(status.status)} Status: {status.status === 'configured' && ( Ready to use )} {status.error && ( {status.error} )} ))} {/* Compact Summary Section */} {validationData.configured_providers.length > 0 && ( } label={`${validationData.configured_providers.length} Configured`} color="success" variant="outlined" sx={{ fontWeight: 600, '& .MuiChip-icon': { color: 'success.main' } }} /> )} {validationData.missing_keys.length > 0 && ( } label={`${validationData.missing_keys.length} Missing`} color="warning" variant="outlined" sx={{ fontWeight: 600, '& .MuiChip-icon': { color: 'warning.main' } }} /> )} )} {/* Continue button is handled by the main wizard, not here */} ); }; export default ApiKeyValidationStep;