import React, { useState, useRef, useEffect } from 'react'; import { ChatIcon, CloseIcon, SendIcon } from './Icons'; import { ChatMessage } from '../types'; interface AIChatProps { onSendMessage: (text: string) => Promise; isOpen: boolean; setIsOpen: (open: boolean) => void; apiKey: string; onApiKeyChange: (key: string) => void; } const ModelMessage: React.FC<{ text: string }> = ({ text }) => { const elements: React.ReactNode[] = []; let listItems: React.ReactNode[] = []; const flushList = () => { if (listItems.length > 0) { elements.push( ); listItems = []; } }; const parseBold = (content: string, keyPrefix: string) => { const parts = content.split(/(\*\*.*?\*\*)/g); return parts.map((part, i) => { if (part.startsWith('**') && part.endsWith('**')) { return {part.slice(2, -2)}; } return part; }); } text.split('\n').forEach((line, index) => { const trimmedLine = line.trim(); if (trimmedLine.startsWith('* ') || trimmedLine.startsWith('- ')) { const content = trimmedLine.substring(2); listItems.push(
  • {parseBold(content, `li-${index}`)}
  • ); } else { flushList(); if (line.trim() !== '') { elements.push(

    {parseBold(line, `p-${index}`)}

    ); } } }); flushList(); // Flush any remaining list items at the end return <>{elements.length > 0 ? elements :

    {text}

    }; }; const SettingsIcon = () => ( ); const AIChat: React.FC = ({ onSendMessage, isOpen, setIsOpen, apiKey, onApiKeyChange }) => { const [messages, setMessages] = useState([ { role: 'model', text: 'Hello! I am your AI Data Analyst. I can answer questions about your data, analyze trends, and perform calculations.', timestamp: new Date() } ]); const [input, setInput] = useState(''); const [isTyping, setIsTyping] = useState(false); const [showConfig, setShowConfig] = useState(!apiKey); const messagesEndRef = useRef(null); const scrollToBottom = () => { messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' }); }; useEffect(() => { if (isOpen) scrollToBottom(); }, [messages, isOpen, showConfig]); useEffect(() => { // If no API key is present when opened, show config if (!apiKey) setShowConfig(true); }, [apiKey]); const handleSend = async () => { if (!input.trim() || !apiKey) return; const userMsg: ChatMessage = { role: 'user', text: input, timestamp: new Date() }; setMessages(prev => [...prev, userMsg]); setInput(''); setIsTyping(true); const responseText = await onSendMessage(userMsg.text); setIsTyping(false); setMessages(prev => [...prev, { role: 'model', text: responseText, timestamp: new Date() }]); }; const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); handleSend(); } }; const handleSaveKey = (e: React.FormEvent) => { e.preventDefault(); // Input value is already bound to parent state via local var, but we use form submission to switch view if (apiKey) setShowConfig(false); }; return ( <> {/* Trigger Button */} {/* Chat Window */}
    {/* Header */}

    AI Data Assistant

    {/* Configuration Screen */} {showConfig ? (

    Connect Gemini AI

    To enable the AI assistant, please enter your Google Gemini API Key.

    onApiKeyChange(e.target.value)} placeholder="AIzaSy..." className="w-full bg-slate-900 border border-slate-700 rounded-lg px-4 py-3 text-white focus:ring-2 focus:ring-indigo-500 outline-none" required />

    Key is stored locally in your browser. Get a key here.

    ) : ( <> {/* Messages */}
    {messages.map((msg, idx) => (
    {msg.role === 'model' ? : msg.text}
    ))} {isTyping && (
    )}
    {/* Input */}
    setInput(e.target.value)} onKeyDown={handleKeyDown} placeholder="Ask about revenue, growth, units..." className="w-full bg-slate-950 border border-slate-700 text-slate-200 rounded-full py-3 pl-4 pr-12 focus:outline-none focus:border-primary transition-colors placeholder-slate-500 text-sm" />
    )}
    ); }; export default AIChat;