import React, { useState, useCallback, useEffect } from 'react'; import { useDropzone } from 'react-dropzone'; import { Upload, X, ShieldCheck, Target, TrendingUp, AlertTriangle, Loader2, Zap, BrainCircuit, Camera, ScanLine } from 'lucide-react'; import { motion, AnimatePresence } from 'motion/react'; import { analyzeForexChart } from '../services/geminiService'; import { AnalysisResponse, SignalResult, SignalType } from '../types'; import { cn } from '../lib/utils'; import { ref, uploadBytes, getDownloadURL } from 'firebase/storage'; import { storage, auth, db, handleFirestoreError, OperationType } from '../lib/firebase'; import { collection, addDoc, serverTimestamp, query, where, getDocs, Timestamp } from 'firebase/firestore'; export const AnalysisView: React.FC<{ userData?: any }> = ({ userData }) => { const [file, setFile] = useState(null); const [preview, setPreview] = useState(null); const [isAnalyzing, setIsAnalyzing] = useState(false); const [result, setResult] = useState(null); const [error, setError] = useState(null); const [mode, setMode] = useState<'Técnico' | 'Fundamental' | 'Híbrido'>('Híbrido'); const [usageInfo, setUsageInfo] = useState<{ used: number, limit: number }>({ used: 0, limit: userData?.analysisLimit ?? 8 }); useEffect(() => { const fetchUsage = async () => { if (!auth.currentUser) return; const today = new Date(); today.setHours(0, 0, 0, 0); try { const q = query( collection(db, 'signals'), where('userId', '==', auth.currentUser.uid) ); const snapshot = await getDocs(q).catch(err => { handleFirestoreError(err, OperationType.LIST, 'signals'); throw err; }); const todaySignals = snapshot.docs.filter((doc) => { const data = doc.data(); return data.timestamp >= today.getTime(); }); setUsageInfo({ used: todaySignals.length, limit: userData?.analysisLimit ?? 8 }); } catch (err) { console.error("Error fetching usage stats", err); } }; fetchUsage(); }, [result, userData]); const handleStartAnalysis = async () => { if (!preview || !file) return; if (usageInfo.used >= usageInfo.limit) { setError(`Limite diário atingido (${usageInfo.used}/${usageInfo.limit}). Faça upgrade para análises ilimitadas.`); return; } setIsAnalyzing(true); setError(null); try { let downloadUrl = null; if (auth.currentUser) { const fileRef = ref(storage, `files/${Date.now()}_${file.name}`); await uploadBytes(fileRef, file); downloadUrl = await getDownloadURL(fileRef); } const base64 = preview.split(',')[1]; const analysis = await analyzeForexChart(base64, undefined, mode); setResult(analysis); if (auth.currentUser) { await addDoc(collection(db, 'signals'), { ...analysis, screenshotUrl: downloadUrl, userId: auth.currentUser.uid, createdAt: serverTimestamp(), timestamp: Date.now(), result: SignalResult.PENDING, type: analysis.decision }).catch(err => { handleFirestoreError(err, OperationType.CREATE, 'signals'); throw err; }); } } catch (err: any) { console.error(err); setError(err.message || 'Falha ao analisar imagem. Verifique se o gráfico está claro.'); } finally { setIsAnalyzing(false); } }; const onDrop = useCallback((acceptedFiles: File[]) => { const selectedFile = acceptedFiles[0]; setFile(selectedFile); const reader = new FileReader(); reader.onload = () => { setPreview(reader.result as string); }; reader.readAsDataURL(selectedFile); setError(null); }, []); const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop, accept: { 'image/*': [] }, multiple: false } as any); const reset = () => { setFile(null); setPreview(null); setResult(null); setError(null); }; return (

Novo Scan

Envie um gráfico para análise de IA Pro.

= usageInfo.limit ? "bg-brand-red" : "bg-green-500" )} style={{ width: usageInfo.limit === 999999 ? '100%' : `${Math.min(100, (usageInfo.used / usageInfo.limit) * 100)}%` }} />
{usageInfo.limit === 999999 ? `${usageInfo.used}/∞ Scans` : `${usageInfo.used}/${usageInfo.limit} Scans`}
{!result ? (
{isAnalyzing && (
Logo

Processando Scan Institucional...

)} {!preview ? (
{(['Técnico', 'Fundamental', 'Híbrido'] as const).map((m) => ( ))}

Fazer Upload ou Arrastar

TradingView, MT4/MT5, cTrader

) : (
Preview
{error &&

{error}

}
)}
) : (
{/* Score & Signal Info */}
{result.score}%

= 80 ? (result.decision === SignalType.BUY ? "text-green-500" : "text-brand-red red-text-glow") : result.score >= 60 ? "text-orange-500" : "text-zinc-500" )}> {result.score >= 80 ? '🔥 ALTA PROBABILIDADE' : result.score >= 60 ? '⚖️ MÉDIA PROBABILIDADE' : '❌ EVITAR'}

{result.justification}

⚠️ {result.alerta}

MODO {result.mode}
TF {result.timeframe}
{/* Trading Decision */}
{result.decision === SignalType.BUY ? 'COMPRAR' : result.decision === SignalType.SELL ? 'VENDER' : 'AGUARDAR'} Decisão QuantScan
ENTRADA
{result.entry}
STOP LOSS
{result.stopLoss}
TAKE PROFIT
{result.takeProfit}

ANÁLISE TÉCNICA (SMC + LIQ)

{result.tecnica}

ANÁLISE FUNDAMENTAL

{result.fundamental}

ANALISE GERAL

{result.analiseGeral}

{/* Analysis Illustration */}

Mapeamento Técnico da IA

Technical Analysis Map {/* UI Overlays to simulate AI analysis */}
Fluxo Institucional Detectado HFT Signature

{result.pair} / {result.timeframe}

Ref: AIS-BETA-{Math.floor(Math.random() * 10000)}

Confirmação IA

{result.score}%

{/* Decorative Scanning Line */}
)}
); };