import React, { useState, useEffect, useRef } from 'react'; import { AstroData } from '../types'; import { getAstroInsight, chatWithAstro, summarizeAstroData } from '../services/geminiService'; import ReactMarkdown from 'react-markdown'; import { Send, Loader2, MessageSquare, ChevronRight, ChevronLeft, Plus, X, Download, Copy, Check } from 'lucide-react'; import { motion, AnimatePresence } from 'motion/react'; interface Props { step: number; userData: AstroData; onNext: () => void; onPrev: () => void; onUpdateData: (newData: AstroData) => void; } const VARGA_INQUIRIES = [ { id: 'D9', name: 'Marriage & Path', varga: 'D9', desc: 'Navamsa: Deep dive into Dharma, committed partnerships, and inner devotion.' }, { id: 'D10', name: 'Career & Status', varga: 'D10', desc: 'Dashamsha: Analyze your capacity to impact the world and achieve public honor.' }, { id: 'D2', name: 'Wealth & Resources', varga: 'D2', desc: 'Hora: Capacity to manage resources and maintain physical security.' }, { id: 'D30', name: 'Health & Misfortune', varga: 'D30', desc: 'Trishamsha: Analyze fated diseases and deep subconscious karmic blocks.' }, { id: 'D4', name: 'Home & Assets', varga: 'D4', desc: 'Chaturthamsha: Fixed assets, property, land, and foundational happiness.' }, { id: 'D7', name: 'Children & Creativity', varga: 'D7', desc: 'Saptamsha: Creative output and co-creative relationships.' }, { id: 'D16', name: 'Luxuries & Contentment', varga: 'D16', desc: 'Shodashamsha: Inner emotional contentment and vehicles.' }, ]; export default function AstroStep({ step, userData, onNext, onPrev, onUpdateData }: Props) { const [insight, setInsight] = useState(''); const [technicalAudit, setTechnicalAudit] = useState(''); const [showTechnical, setShowTechnical] = useState(false); const [subStep, setSubStep] = useState(userData.currentSubStep || 0); const [loading, setLoading] = useState(true); const [question, setQuestion] = useState(''); const [chatHistory, setChatHistory] = useState<{ role: string, text: string }[]>([]); const [chatLoading, setChatLoading] = useState(false); const [showAddChart, setShowAddChart] = useState(false); const [copied, setCopied] = useState(false); const [newChartName, setNewChartName] = useState(''); const [newChartText, setNewChartText] = useState(''); const chatEndRef = useRef(null); const lastFetchedStepRef = useRef(null); useEffect(() => { setSubStep(userData.currentSubStep || 0); }, [userData.currentSubStep]); useEffect(() => { const fetchInitialInsight = async () => { // Check cache first const cacheKey = step === 2 ? `2.${subStep}` : `${step}`; if (userData.fullInterpretations?.[cacheKey]) { setInsight(userData.fullInterpretations[cacheKey].guidance); setTechnicalAudit(userData.fullInterpretations[cacheKey].audit); setLoading(false); return; } setLoading(true); setInsight(''); setTechnicalAudit(''); try { let currentData = { ...userData, currentSubStep: subStep }; if (!currentData.summary) { const summary = await summarizeAstroData(currentData); currentData.summary = summary.text; onUpdateData(currentData); } const result = await getAstroInsight(step, currentData); // Split result into Guidance and Technical Audit const guidancePart = result.fullText.split('---')[0] || result.fullText; const auditPart = result.fullText.split('---')[1] || ""; setInsight(guidancePart); setTechnicalAudit(auditPart); setChatHistory([{ role: 'model', text: result.fullText }]); // Save BOTH memory hook (for AI) and full interpretation (for UI cache) const updatedData = { ...currentData, stepInterpretations: { ...currentData.stepInterpretations, [result.memoryKey]: result.memoryHook }, fullInterpretations: { ...currentData.fullInterpretations, [result.memoryKey]: { guidance: guidancePart, audit: auditPart } } }; onUpdateData(updatedData); lastFetchedStepRef.current = step; } catch (error: any) { console.error(error); if (error?.message?.includes('429')) { setInsight('**Sky is Overcast (Rate Limit reached)**:\n\nYou have reached the daily free limit of your Gemini API key. Please wait until tomorrow, or consider setting up a billing account in Google AI Studio to increase your capacity.'); } else if (error?.message?.includes('API_KEY_INVALID') || error?.message?.includes('API key not found')) { setInsight('Failed to load astrological insight. Please check your **VITE_GEMINI_API_KEY** in the `.env` file.'); } else { setInsight('Failed to load astrological insight. There was an error consulting the stars.'); } } finally { setLoading(false); } }; fetchInitialInsight(); }, [step, subStep]); useEffect(() => { chatEndRef.current?.scrollIntoView({ behavior: 'smooth' }); }, [chatHistory]); const handleChat = async (e: React.FormEvent) => { e.preventDefault(); if (!question.trim() || chatLoading) return; const userMsg = { role: 'user', text: question }; setChatHistory(prev => [...prev, userMsg]); setQuestion(''); setChatLoading(true); try { const response = await chatWithAstro(step, userData, question, chatHistory); setChatHistory(prev => [...prev, { role: 'model', text: response.text }]); } catch (error: any) { console.error(error); let errorMsg = 'Error communicating with the stars...'; if (error?.message?.includes('API_KEY_INVALID') || error?.message?.includes('API key not found')) { errorMsg += ' Please check your `GEMINI_API_KEY` in the Secrets menu.'; } setChatHistory(prev => [...prev, { role: 'model', text: errorMsg }]); } finally { setChatLoading(false); } }; const handleDeepDive = async (inquiry: typeof VARGA_INQUIRIES[0]) => { if (!userData.divisionalCharts[inquiry.varga]) { setNewChartName(inquiry.varga); setShowAddChart(true); return; } setChatLoading(true); const deepDiveQuestion = `DEEP DIVE REQUEST: I want to analyze my ${inquiry.name} using the ${inquiry.varga} chart. Please perform Step 3.2-3.5 analysis as defined in the rules: Evaluate Varga Dignity Shifts and specific Karakas.`; // Add prompt to chat setChatHistory(prev => [...prev, { role: 'user', text: `Deep Dive: ${inquiry.name}` }]); try { const response = await chatWithAstro(step, userData, deepDiveQuestion, chatHistory); setChatHistory(prev => [...prev, { role: 'model', text: response.text }]); } catch (err) { console.error(err); setChatHistory(prev => [...prev, { role: 'model', text: 'Error performing deep dive calculation.' }]); } finally { setChatLoading(false); } }; const handleAddChart = () => { if (!newChartName || !newChartText) return; const newData = { ...userData, divisionalCharts: { ...userData.divisionalCharts, [newChartName.toUpperCase()]: newChartText } }; onUpdateData(newData); setShowAddChart(false); setNewChartName(''); setNewChartText(''); }; const handleCopy = () => { navigator.clipboard.writeText(insight); setCopied(true); setTimeout(() => setCopied(false), 2000); }; const handleExport = () => { const blob = new Blob([insight], { type: 'text/markdown' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `Vedic_Astro_Step_${step}_Interpretation.md`; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); }; return (

Step {step}

{step === 1 && "Foundational Analysis"} {step === 2 && "Rashi Chart Promise"} {step === 3 && "Varga Verification"} {step === 4 && "Event Timing"}

{step === 3 && ( )}
{/* Main Insight Area */}
{loading ? (

Consulting the celestial alignment...

) : (
{showTechnical ? (
{technicalAudit || insight}
) : (
{step === 3 && (

Step 3.1: Selective Deep Dive

Choose an area of life to examine through the mathematical micro-lens of Divisional Charts (Vargas).

{VARGA_INQUIRIES.map((inquiry) => { const hasChart = !!userData.divisionalCharts[inquiry.varga]; return ( ); })}
)} {insight}
)}
{!loading && (
{step === 2 && subStep < 3 ? ( ) : step < 4 && ( )} {step === 2 && (
{[0, 1, 2, 3].map(i => (
))}
)}
)} )} {/* Display current charts info */}

Available Charts

D1 (Rasi) {Object.keys(userData.divisionalCharts).map(key => ( {key} ))}
{/* Deep Dive Chat */}

Deep Dive Chat

{chatHistory.slice(1).map((msg, idx) => (
{msg.text}
))} {chatLoading && (
)}
setQuestion(e.target.value)} />
{/* Add Chart Modal */} {showAddChart && (

Add Divisional Chart

setNewChartName(e.target.value)} />