import React, { useState, useRef, useEffect } from 'react';
import { useDropzone } from 'react-dropzone';
import { useNavigate, useLocation } from 'react-router-dom';
import { motion, AnimatePresence } from 'framer-motion';
import {
  Send,
  FileText,
  TrendingUp,
  Network,
  Mic,
  Paperclip,
  X,
  Plus,
  Trash2,
  MessageSquare,
  Pencil,
  Check,
  Copy,
  CheckCheck,
  Sparkles,
  ChevronDown,
  ArrowLeft,
  Settings,
  Menu,
  Database,
  Eye,
  Layers,
  RefreshCw,
  Square,
  Zap,
  Bot,
} from 'lucide-react';
import apiService, { api as axiosApi } from '@/services/api';
import { useUserStore } from '@/store/userStore';
import { useConfirmModal } from '@/components/ui/ConfirmModal';
import { useToast } from '@/contexts/ToastContext';
import { getUserIdSync, getAuthHeadersSync } from '@/utils/userId';

// Lazy load PlotlyChart for performance
const PlotlyChart = React.lazy(() => import('@/components/PlotlyChart'));

// ============================================================================
// 🎯 DIRECT ANSWER BADGE - ChatGPT/Claude Style Highlighted Answer
// Shows the key answer prominently (percentage, value, etc.) before full response
// ============================================================================
interface DirectAnswer {
  value: string;
  type: 'percentage' | 'number' | 'currency' | 'text';
  label?: string;
  trend?: 'up' | 'down' | 'stable';
}

const DirectAnswerBadge: React.FC<{ answer: DirectAnswer }> = ({ answer }) => {
  const getTrendIcon = () => {
    if (answer.trend === 'up') return '📈';
    if (answer.trend === 'down') return '📉';
    return '';
  };

  const getTrendColor = () => {
    if (answer.trend === 'up') return 'text-green-400';
    if (answer.trend === 'down') return 'text-red-400';
    return 'text-blue-400';
  };

  return (
    <div className="mb-4 p-4 rounded-xl bg-gradient-to-r from-green-500/20 to-emerald-500/10 border border-green-500/30 animate-fadeIn">
      <div className="flex items-center gap-3">
        {answer.label && (
          <span className="text-sm text-gray-400">{answer.label}</span>
        )}
        <span className={`text-3xl font-bold ${getTrendColor()}`}>
          {answer.value}
        </span>
        {answer.trend && <span className="text-2xl">{getTrendIcon()}</span>}
      </div>
    </div>
  );
};

// ============================================================================
// 🔍 EXTRACT DIRECT ANSWER - Finds key values to highlight
// ============================================================================
const extractDirectAnswer = (content: string, query: string): DirectAnswer | null => {
  const queryLower = query.toLowerCase();
  
  // Check if user is asking for a specific metric
  const percentageKeywords = ['percent', '%', 'rate', 'growth', 'increase', 'decrease', 'ratio', 'proportion', 'share'];
  const currencyKeywords = ['revenue', 'sales', 'profit', 'cost', 'price', 'total', 'amount', 'value', '$', '₹', '€'];
  const countKeywords = ['count', 'number', 'how many', 'total', 'quantity'];
  
  const isPercentageQuery = percentageKeywords.some(kw => queryLower.includes(kw));
  const isCurrencyQuery = currencyKeywords.some(kw => queryLower.includes(kw));
  const isCountQuery = countKeywords.some(kw => queryLower.includes(kw));
  
  // Extract percentage values (e.g., "45.2%", "45%", "45.2 percent")
  const percentMatch = content.match(/(\d+\.?\d*)\s*%/);
  if (percentMatch && isPercentageQuery) {
    const value = parseFloat(percentMatch[1]);
    return {
      value: `${value}%`,
      type: 'percentage',
      trend: content.toLowerCase().includes('increase') || content.toLowerCase().includes('growth') || content.toLowerCase().includes('up') 
        ? 'up' 
        : content.toLowerCase().includes('decrease') || content.toLowerCase().includes('decline') || content.toLowerCase().includes('down')
        ? 'down'
        : undefined
    };
  }
  
  // Extract currency values (e.g., "$1,234.56", "₹45,000", "€1.2M")
  const currencyMatch = content.match(/[\$€₹£¥][\d,]+\.?\d*\s*[KMBkmb]?/);
  if (currencyMatch && isCurrencyQuery) {
    return {
      value: currencyMatch[0],
      type: 'currency',
      trend: content.toLowerCase().includes('increase') || content.toLowerCase().includes('growth') ? 'up' : 
             content.toLowerCase().includes('decrease') || content.toLowerCase().includes('decline') ? 'down' : undefined
    };
  }
  
  // Extract large numbers with formatting (e.g., "1,234", "45K", "2.5M")
  const numberMatch = content.match(/\b(\d{1,3}(?:,\d{3})*(?:\.\d+)?)\s*([KMBkmb])?\b/);
  if (numberMatch && isCountQuery) {
    let value = numberMatch[0];
    return {
      value: value,
      type: 'number'
    };
  }
  
  return null;
};

// ============================================================================
// 🛡️ USER-FRIENDLY ERROR MESSAGE FORMATTER
// Shows nice messages like Claude/ChatGPT instead of raw API errors
// ============================================================================
const formatUserFriendlyError = (error: string | any): string => {
  const errorStr = typeof error === 'string' ? error.toLowerCase() : 
    (error?.message || error?.response?.data?.detail || String(error)).toLowerCase();
  
  // Rate limit / Service busy errors
  if (errorStr.includes('rate') || errorStr.includes('limit') || errorStr.includes('429') || 
      errorStr.includes('quota') || errorStr.includes('too many requests')) {
    return `⏳ **Service Temporarily Busy**

Our AI service is experiencing high demand. Please wait a moment and try again.

💡 **Tips:**
• Wait 30 seconds before retrying
• Try asking a simpler question
• Your data is safe and ready`;
  }
  
  // API Key / Auth errors
  if (errorStr.includes('api_key') || errorStr.includes('unauthorized') || 
      errorStr.includes('authentication') || errorStr.includes('401') || errorStr.includes('invalid key')) {
    return `🔑 **Configuration Required**

The AI service needs to be configured. Please contact your administrator.

_This is a server-side configuration issue._`;
  }
  
  // Connection / Timeout errors
  if (errorStr.includes('timeout') || errorStr.includes('connection') || 
      errorStr.includes('network') || errorStr.includes('fetch') || errorStr.includes('econnrefused')) {
    return `🌐 **Connection Issue**

Unable to reach the AI service. Please check your internet connection and try again.

💡 **Tips:**
• Check your internet connection
• Refresh the page
• Try again in a few moments`;
  }
  
  // Context too large
  if (errorStr.includes('context') || errorStr.includes('too large') || 
      errorStr.includes('token') || errorStr.includes('length') || errorStr.includes('maximum')) {
    return `📏 **Request Too Large**

Your question or data exceeds the model's capacity.

💡 **Tips:**
• Try asking a more specific question
• Break down complex queries into smaller parts
• Focus on specific columns or time periods`;
  }
  
  // Server errors
  if (errorStr.includes('500') || errorStr.includes('502') || errorStr.includes('503') || 
      errorStr.includes('504') || errorStr.includes('internal server')) {
    return `🔧 **Service Maintenance**

Our AI service is temporarily unavailable. We're working on it!

Please try again in a few minutes.`;
  }
  
  // Model not found
  if (errorStr.includes('model') && (errorStr.includes('not found') || errorStr.includes('unavailable'))) {
    return `🤖 **AI Model Unavailable**

The requested AI model is temporarily unavailable. Trying alternative models...

Please try again in a moment.`;
  }
  
  // Generic fallback - don't show raw technical errors
  if (errorStr.includes('error') || errorStr.includes('exception') || errorStr.includes('failed')) {
    return `⚠️ **Something Went Wrong**

I encountered an issue processing your request. Please try again.

💡 **Tips:**
• Rephrase your question
• Try a simpler query
• If the problem persists, refresh the page`;
  }
  
  // If nothing matches, return a clean generic message
  return `⚠️ **Unable to Process Request**

Please try again in a moment. If the issue persists, try refreshing the page.`;
};

// Helper function to format inline text (bold, italic, code)
const formatInlineText = (text: string): string => {
  return text
    .replace(/\*\*(.+?)\*\*/g, '<strong class="font-semibold">$1</strong>')
    .replace(/\*(.+?)\*/g, '<em>$1</em>')
    .replace(/`([^`]+)`/g, '<code class="inline-code-highlight">$1</code>');
};

// Component to render formatted text with inline styles
const InlineFormattedText: React.FC<{ text: string; className?: string }> = ({ text, className = '' }) => {
  const formatted = formatInlineText(text);
  return <span className={className} dangerouslySetInnerHTML={{ __html: formatted }} />;
};

// Image with download/copy buttons
const ChartImage: React.FC<{ src: string; alt: string }> = ({ src, alt }) => {
  const [copied, setCopied] = React.useState(false);

  const handleDownload = () => {
    const link = document.createElement('a');
    link.href = src;
    link.download = `chart_${Date.now()}.png`;
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
  };

  const handleCopy = async () => {
    try {
      if (src.startsWith('data:image')) {
        const response = await fetch(src);
        const blob = await response.blob();
        await navigator.clipboard.write([
          new ClipboardItem({ [blob.type]: blob })
        ]);
      }
      setCopied(true);
      setTimeout(() => setCopied(false), 2000);
    } catch (err) {
      console.error('Failed to copy image:', err);
    }
  };

  return (
    <div className="my-4 relative group chart-fade-in">
      <img
        src={src}
        alt={alt}
        className="max-w-full rounded-xl border border-[var(--border-color)] shadow-lg transition-transform duration-300 group-hover:scale-[1.02]"
        style={{ maxHeight: '450px' }}
      />
      <div className="absolute top-3 right-3 flex gap-2 opacity-0 group-hover:opacity-100 transition-opacity">
        <button
          onClick={handleDownload}
          className="p-2 bg-[var(--bg-card)]/90 hover:bg-green-600 rounded-lg text-white text-xs flex items-center gap-1 backdrop-blur-sm border border-[var(--border-color)]"
          title="Download Chart"
        >
          <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" />
          </svg>
          Download
        </button>
        <button
          onClick={handleCopy}
          className="p-2 bg-[var(--bg-card)]/90 hover:bg-green-600 rounded-lg text-white text-xs flex items-center gap-1 backdrop-blur-sm border border-[var(--border-color)]"
          title="Copy Chart"
        >
          {copied ? (
            <>
              <svg className="w-4 h-4 text-green-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
              </svg>
              Copied!
            </>
          ) : (
            <>
              <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z" />
              </svg>
              Copy
            </>
          )}
        </button>
      </div>
      {alt && <p className="text-xs text-gray-500 text-center mt-2">{alt}</p>}
    </div>
  );
};

// =============================================================================
// 🖥️ V5: INTERACTIVE CODE BLOCK — Inline Python Execution (AI Chat v2)
// =============================================================================
const InteractiveCodeBlock: React.FC<{
  code: string;
  language: string;
  isPython: boolean;
}> = ({ code, language, isPython }) => {
  const [isRunning, setIsRunning] = React.useState(false);
  const [result, setResult] = React.useState<{
    success?: boolean;
    stdout?: string;
    stderr?: string;
    figures?: { base64: string; format: string }[];
    tables?: { columns: string[]; data: any[][]; shape?: number[] }[];
    error?: string;
    execution_time_ms?: number;
  } | null>(null);
  const [copied, setCopied] = React.useState(false);

  const handleRun = async () => {
    setIsRunning(true);
    setResult(null);
    try {
      const userId = getUserIdSync();
      const headers = getAuthHeadersSync();
      const baseUrl = axiosApi.defaults.baseURL || '';
      const res = await fetch(`${baseUrl}/api/v1/chat/execute-code`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', ...headers },
        body: JSON.stringify({ code, user_id: userId }),
      });
      const data = await res.json();
      setResult(data);
    } catch (err: any) {
      setResult({ success: false, error: err.message, stdout: '', stderr: err.message, figures: [], tables: [] });
    } finally {
      setIsRunning(false);
    }
  };

  const handleCopy = () => {
    navigator.clipboard.writeText(code);
    setCopied(true);
    setTimeout(() => setCopied(false), 2000);
  };

  return (
    <div className="my-3 rounded-xl border overflow-hidden" style={{ borderColor: 'var(--border-color)', background: 'var(--bg-card)' }}>
      {/* Header */}
      <div className="flex items-center justify-between px-3 py-2 border-b" style={{ borderColor: 'var(--border-color)', background: isPython ? 'rgba(59, 130, 246, 0.05)' : 'transparent' }}>
        <span className="text-xs font-mono font-bold uppercase tracking-wider" style={{ color: 'var(--text-muted)' }}>
          {language || 'code'}
        </span>
        <div className="flex items-center gap-2">
          <button onClick={handleCopy} className="text-xs px-2 py-1 rounded-md hover:bg-white/10 transition-colors flex items-center gap-1" style={{ color: 'var(--text-muted)' }}>
            {copied ? <><CheckCheck className="w-3 h-3 text-green-400" /> Copied</> : <><Copy className="w-3 h-3" /> Copy</>}
          </button>
          {isPython && (
            <button
              onClick={handleRun}
              disabled={isRunning}
              className={`text-xs px-3 py-1 rounded-md font-semibold flex items-center gap-1.5 transition-all ${
                isRunning ? 'bg-blue-500/20 text-blue-300 cursor-wait' : 'bg-emerald-500/20 hover:bg-emerald-500/30 text-emerald-400 hover:text-emerald-300'
              }`}
            >
              {isRunning ? (
                <><span className="w-3 h-3 border-2 border-blue-400/30 border-t-blue-400 rounded-full animate-spin inline-block" /> Running...</>
              ) : (
                <><Zap className="w-3 h-3" /> Run</>
              )}
            </button>
          )}
        </div>
      </div>
      {/* Code */}
      <pre className="p-4 overflow-x-auto">
        <code className="text-sm font-mono" style={{ color: 'var(--text-secondary)' }}>{code}</code>
      </pre>
      {/* Execution Result */}
      {result && (
        <div className="border-t" style={{ borderColor: 'var(--border-color)' }}>
          <div className="px-3 py-1.5 flex items-center justify-between" style={{ background: result.success ? 'rgba(16,185,129,0.05)' : 'rgba(239,68,68,0.05)' }}>
            <span className={`text-xs font-semibold ${result.success ? 'text-emerald-400' : 'text-red-400'}`}>
              {result.success ? '✓ Output' : '✗ Error'}
            </span>
            {result.execution_time_ms != null && (
              <span className="text-xs" style={{ color: 'var(--text-muted)' }}>{result.execution_time_ms}ms</span>
            )}
          </div>
          {result.stdout && (
            <pre className="px-4 py-3 text-sm font-mono overflow-x-auto whitespace-pre-wrap" style={{ color: 'var(--text-primary)', maxHeight: '300px', overflowY: 'auto' }}>
              {result.stdout}
            </pre>
          )}
          {(result.stderr || result.error) && (
            <pre className="px-4 py-3 text-sm font-mono text-red-400 overflow-x-auto whitespace-pre-wrap" style={{ maxHeight: '200px', overflowY: 'auto' }}>
              {result.stderr || result.error}
            </pre>
          )}
          {result.figures && result.figures.length > 0 && (
            <div className="px-4 py-3 space-y-3">
              {result.figures.map((fig, i) => (
                <img key={i} src={`data:image/png;base64,${fig.base64}`} alt={`Figure ${i+1}`}
                  className="max-w-full rounded-lg border shadow-lg" style={{ borderColor: 'var(--border-color)', maxHeight: '400px' }} />
              ))}
            </div>
          )}
          {result.tables && result.tables.length > 0 && (
            <div className="px-4 py-3 overflow-x-auto">
              {result.tables.map((table, i) => (
                <div key={i}>
                  {table.shape && <p className="text-xs mb-1" style={{ color: 'var(--text-muted)' }}>DataFrame: {table.shape[0]} rows × {table.shape[1]} cols</p>}
                  <table className="w-full text-xs border-collapse">
                    <thead><tr>{table.columns.map((col, ci) => (
                      <th key={ci} className="text-left px-2 py-1.5 border-b font-semibold" style={{ borderColor: 'var(--border-color)', color: 'var(--text-primary)' }}>{col}</th>
                    ))}</tr></thead>
                    <tbody>{table.data.slice(0,20).map((row, ri) => (
                      <tr key={ri} className="hover:bg-white/[0.03]">{row.map((cell, ci) => (
                        <td key={ci} className="px-2 py-1 border-b" style={{ borderColor: 'var(--border-color)', color: 'var(--text-secondary)' }}>{cell != null ? String(cell) : '—'}</td>
                      ))}</tr>
                    ))}</tbody>
                  </table>
                </div>
              ))}
            </div>
          )}
        </div>
      )}
    </div>
  );
};

// Lazy-loaded ForecastChartBlock for rendering prediction charts
const ForecastChartBlock: React.FC<{ payload: Record<string, unknown> }> = ({ payload }) => {
  const PredictionChart = React.lazy(() =>
    import('@/components/PredictionChartRenderer').then(m => ({ default: m.PredictionChartRenderer }))
  );

  return (
    <React.Suspense fallback={
      <div className="animate-pulse bg-[var(--bg-card)] rounded-xl h-64 flex items-center justify-center">
        <span className="text-gray-500">Loading chart...</span>
      </div>
    }>
      <PredictionChart payload={payload as unknown as string} />
    </React.Suspense>
  );
};

// PlotlyChartBlock for rendering interactive Plotly charts - MEMOIZED for performance
const PlotlyChartBlock: React.FC<{ data: any[]; layout: any }> = React.memo(({ data, layout }) => {
  // PERFORMANCE FIX: Memoize chart data to prevent unnecessary re-renders
  const chartData = React.useMemo(() => data, [JSON.stringify(data)]);
  const chartLayout = React.useMemo(() => ({
    ...layout,
    autosize: true,
    // Disable animations for better performance
    transition: { duration: 0 },
  }), [JSON.stringify(layout)]);

  return (
    <React.Suspense fallback={
      <div className="animate-pulse bg-[var(--bg-card)] rounded-xl h-64 flex items-center justify-center">
        <span className="text-gray-500">Loading interactive chart...</span>
      </div>
    }>
      <div className="my-4 p-4 glass-card rounded-xl border border-[var(--border-color)]">
        <PlotlyChart data={chartData} layout={chartLayout} />
      </div>
    </React.Suspense>
  );
}, (prevProps, nextProps) => {
  // Custom comparison - only re-render if data/layout actually changed
  return JSON.stringify(prevProps.data) === JSON.stringify(nextProps.data) &&
         JSON.stringify(prevProps.layout) === JSON.stringify(nextProps.layout);
});

// MLChartBlock - Renders matplotlib/seaborn charts from Predict mode (base64 PNG)
const MLChartBlock: React.FC<{
  chart: { type: string; image: string; title?: string }
}> = ({ chart }) => {
  const typeIcons: Record<string, string> = {
    'ml_forecast': '📈',
    'ml_importance': '🔑',
    'ml_correlation': '🔗',
    'ml_distribution': '📊',
    'ml_residual': '📉',
    'ml_summary': '🤖'
  };

  const icon = typeIcons[chart.type] || '📊';

  if (!chart.image) return null;

  return (
    <div className="my-4 p-4 glass-card rounded-xl border border-[var(--border-color)] shadow-lg">
      <div className="flex items-center gap-2 mb-3">
        <span className="text-lg">{icon}</span>
        <span className="text-sm font-medium text-green-400">
          {chart.title || 'ML Visualization'}
        </span>
        <span className="text-xs text-gray-500 ml-auto">
          Powered by scikit-learn + matplotlib
        </span>
      </div>
      <ChartImage src={chart.image} alt={chart.title || 'ML Chart'} />
    </div>
  );
};

// MLChartsContainer - Renders multiple ML charts from response
const MLChartsContainer: React.FC<{
  charts: Array<{ type: string; image: string; title?: string }>
}> = ({ charts }) => {
  if (!charts || charts.length === 0) return null;

  return (
    <div className="space-y-4 mt-4">
      <div className="flex items-center gap-2 text-sm text-green-400">
        <Zap className="w-4 h-4" />
        <span>ML Visualizations • Real scikit-learn analysis</span>
      </div>
      {charts.map((chart, index) => (
        <MLChartBlock key={index} chart={chart} />
      ))}
    </div>
  );
};

// Typewriter Animation Component - ChatGPT-like word-by-word reveal - Memoized for Performance
const TypewriterText: React.FC<{
  content: string;
  isNew?: boolean;
  onComplete?: () => void;
}> = React.memo(({ content, isNew = false, onComplete }) => {
  const [displayedContent, setDisplayedContent] = useState(isNew ? '' : content);
  const [isComplete, setIsComplete] = useState(!isNew);
  const hasAnimatedRef = useRef(false);
  const intervalRef = useRef<NodeJS.Timeout | null>(null);
  const onCompleteRef = useRef(onComplete);

  // Keep onComplete ref updated without causing re-renders
  useEffect(() => {
    onCompleteRef.current = onComplete;
  }, [onComplete]);

  useEffect(() => {
    // Clear any existing interval
    if (intervalRef.current) {
      clearInterval(intervalRef.current);
      intervalRef.current = null;
    }

    // If not a new message OR already animated, show full content immediately
    if (!isNew || hasAnimatedRef.current) {
      setDisplayedContent(content);
      setIsComplete(true);
      return;
    }

    // PERFORMANCE FIX: Skip animation for content with charts/visualizations
    // Charts cause heavy re-renders during typewriter animation
    const hasCharts = content.includes('plotly_chart') || 
                      content.includes('forecast_chart') || 
                      content.includes('"data"') && content.includes('"layout"') ||
                      content.includes('```') && content.length > 2000;
    
    if (hasCharts) {
      // Show immediately without animation for chart content
      setDisplayedContent(content);
      setIsComplete(true);
      hasAnimatedRef.current = true;
      onCompleteRef.current?.();
      return;
    }

    // Mark as animating
    hasAnimatedRef.current = true;

    // Reset for new content
    setDisplayedContent('');
    setIsComplete(false);

    // Split content into words for word-by-word animation
    const words = content.split(/(\s+)/);
    let currentIndex = 0;

    // PERFORMANCE FIX: Use larger chunks (8 words) and longer interval (35ms)
    intervalRef.current = setInterval(() => {
      if (currentIndex < words.length) {
        // Add 8 words at a time for faster, less CPU-intensive animation
        const nextIndex = Math.min(currentIndex + 8, words.length);
        const wordsToAdd = words.slice(currentIndex, nextIndex).join('');
        setDisplayedContent(prev => prev + wordsToAdd);
        currentIndex = nextIndex;
      } else {
        if (intervalRef.current) {
          clearInterval(intervalRef.current);
          intervalRef.current = null;
        }
        setIsComplete(true);
        onCompleteRef.current?.();
      }
    }, 35); // 35ms per chunk - less CPU intensive

    return () => {
      if (intervalRef.current) {
        clearInterval(intervalRef.current);
        intervalRef.current = null;
      }
    };
  }, [content, isNew]); // Removed onComplete from deps - using ref instead

  return (
    <>
      <FormattedMessage content={displayedContent} />
      {!isComplete && <span className="typing-cursor"></span>}
    </>
  );
});

// Component to format markdown-like responses - Memoized for Performance
const FormattedMessage: React.FC<{ content: string }> = React.memo(({ content }) => {
  const formatContent = (text: string) => {
    let normalizedText = text.replace(/\r\n/g, '\n');

    // PRE-PROCESS: Compact any pretty-printed JSON in chart blocks
    // This fixes the issue where JSON gets split across paragraphs
    normalizedText = normalizedText.replace(
      /```plotly_chart\s*([\s\S]*?)```/gi,
      (match, jsonContent) => {
        try {
          // Try to parse and re-stringify as compact JSON
          const parsed = JSON.parse(jsonContent.trim());
          return '```plotly_chart\n' + JSON.stringify(parsed) + '\n```';
        } catch (e) {
          // If parsing fails, try to compact manually (remove newlines/spaces in JSON)
          const compacted = jsonContent.replace(/\n\s*/g, '').replace(/\s{2,}/g, ' ').trim();
          return '```plotly_chart\n' + compacted + '\n```';
        }
      }
    );

    // Also handle JSON blocks that might have "type":"plotly"
    normalizedText = normalizedText.replace(
      /(\{[^{}]*"type"\s*:\s*"plotly"[^{}]*"data"[\s\S]*?"layout"[\s\S]*?\}(?:\s*\})*)/gi,
      (match) => {
        try {
          // Find complete JSON by brace matching
          let braceCount = 0;
          let startIdx = match.indexOf('{');
          let endIdx = startIdx;
          for (let i = startIdx; i < match.length; i++) {
            if (match[i] === '{') braceCount++;
            if (match[i] === '}') braceCount--;
            if (braceCount === 0) {
              endIdx = i + 1;
              break;
            }
          }
          const jsonStr = match.substring(startIdx, endIdx);
          const parsed = JSON.parse(jsonStr);
          return '```plotly_chart\n' + JSON.stringify(parsed) + '\n```';
        } catch (e) {
          return match;
        }
      }
    );

    const blocks: string[] = [];
    let currentBlock = '';
    let insideCodeBlock = false;
    const lines = normalizedText.split('\n');

    for (let i = 0; i < lines.length; i++) {
      const line = lines[i];
      const isEmptyLine = line.trim() === '';

      // Track if we're inside a code block (``` markers)
      if (line.trim().startsWith('```')) {
        insideCodeBlock = !insideCodeBlock;
      }

      // Don't split inside code blocks - keep them together
      if (insideCodeBlock) {
        currentBlock += (currentBlock ? '\n' : '') + line;
      } else if (isEmptyLine && currentBlock.trim()) {
        blocks.push(currentBlock.trim());
        currentBlock = '';
      } else {
        currentBlock += (currentBlock ? '\n' : '') + line;
      }
    }
    if (currentBlock.trim()) {
      blocks.push(currentBlock.trim());
    }

    return blocks.map((para, idx) => {
      if (!para.trim()) return null;

      // Headers
      if (para.startsWith('###')) {
        const headerText = para.replace(/^###\s*/, '');
        return <h3 key={idx} className="text-base font-semibold text-white mt-4 mb-2"><InlineFormattedText text={headerText} /></h3>;
      }
      if (para.startsWith('##')) {
        const headerText = para.replace(/^##\s*/, '');
        return <h2 key={idx} className="text-lg font-semibold text-white mt-5 mb-2"><InlineFormattedText text={headerText} /></h2>;
      }
      if (para.startsWith('#')) {
        const headerText = para.replace(/^#\s*/, '');
        return <h1 key={idx} className="text-xl font-bold text-white mt-5 mb-3"><InlineFormattedText text={headerText} /></h1>;
      }

      // Code blocks - special handling for forecast_chart
      // Handle BOTH proper (```) and malformed (``) backticks
      const isForecastChartBlock = /^`{2,3}\s*forecast_chart/i.test(para);
      const hasChartTypeJson = para.includes('"chart_type"') && para.includes('"forecast');

      if (para.startsWith('```') || para.startsWith('``') || isForecastChartBlock || hasChartTypeJson) {
        // Check if it's a forecast chart - handle variations with whitespace and malformed backticks
        const isForecastChart = /^`{2,3}\s*forecast_chart/i.test(para) || hasChartTypeJson;

        if (isForecastChart) {
          // Extract JSON with improved regex that handles both ``` and `` backticks
          let chartJson = '';

          // Try triple backticks first
          let match = para.match(/^`{2,3}\s*forecast_chart\s*([\s\S]*?)`{2,3}\s*$/);
          if (match) {
            chartJson = match[1].trim();
          } else {
            // Fallback: try to find JSON object directly
            const jsonMatch = para.match(/\{[\s\S]*"chart_type"[\s\S]*\}/);
            if (jsonMatch) {
              chartJson = jsonMatch[0].trim();
            }
          }

          // Skip if empty
          if (!chartJson) {
            // Check if the paragraph IS the JSON (no backticks at all)
            if (para.trim().startsWith('{') && para.includes('"chart_type"')) {
              chartJson = para.trim();
            }
          }

          if (chartJson) {
            try {
              const chartPayload = JSON.parse(chartJson);

              // Validate it has required chart properties
              if (chartPayload && chartPayload.chart_type) {
                return (
                  <div key={idx} className="my-4 animate-fade-in">
                    <ForecastChartBlock payload={chartPayload} />
                  </div>
                );
              }
            } catch (e) {
              console.error('Chart JSON parse error:', e, 'JSON:', chartJson.substring(0, 200));
              // Show user-friendly error instead of raw JSON
              return (
                <div key={idx} className="my-3 p-4 bg-red-900/20 border border-red-500/50 rounded-xl">
                  <p className="text-red-400 text-sm">⚠️ Chart rendering failed. The data is available but couldn't be visualized.</p>
                </div>
              );
            }
          }
        }

        // Check if it's a Plotly chart - improved detection
        const isPlotlyChart = /^`{2,3}\s*plotly_chart/i.test(para) || para.includes('"type":"plotly"') || (para.includes('"data"') && para.includes('"layout"'));
        if (isPlotlyChart) {
          console.log('[CHART DEBUG] Detected plotly_chart block:', para.substring(0, 100));

          // Try multiple patterns to extract JSON - BRACE COUNTING IS MOST RELIABLE
          let chartJson = '';

          // PATTERN 1 (PRIMARY): Use brace-counting for complete JSON extraction
          // This is the most reliable method for nested JSON
          if (para.includes('{') && (para.includes('"data"') || para.includes('"type"'))) {
            const startIdx = para.indexOf('{');
            if (startIdx !== -1) {
              let braceCount = 0;
              let endIdx = para.length;
              for (let i = startIdx; i < para.length; i++) {
                if (para[i] === '{') braceCount++;
                if (para[i] === '}') braceCount--;
                if (braceCount === 0) {
                  endIdx = i + 1;
                  break;
                }
              }
              chartJson = para.substring(startIdx, endIdx);
              console.log('[CHART] Brace-counting extracted', chartJson.length, 'chars');
            }
          }

          // PATTERN 2 (FALLBACK): Regex for plotly_chart code block
          if (!chartJson) {
            const match = para.match(/`{2,3}\s*plotly_chart\s*\n?([\s\S]+?)\n?`{2,3}/);
            if (match) {
              chartJson = match[1].trim();
              console.log('[CHART] Regex extracted', chartJson.length, 'chars');
            }
          }

          console.log('[CHART DEBUG] Extracted JSON length:', chartJson.length, 'First 100 chars:', chartJson.substring(0, 100));

          if (chartJson) {
            try {
              const plotlyData = JSON.parse(chartJson);
              console.log('[CHART DEBUG] Parsed plotly data:', {
                hasData: !!plotlyData.data,
                hasLayout: !!plotlyData.layout,
                chartType: plotlyData.chart_type,
                dataLength: Array.isArray(plotlyData.data) ? plotlyData.data.length : 0
              });

              if (plotlyData && plotlyData.data && plotlyData.layout) {
                return (
                  <div key={idx} className="my-4 animate-fade-in">
                    <PlotlyChartBlock data={plotlyData.data} layout={plotlyData.layout} />
                  </div>
                );
              } else {
                console.error('[CHART DEBUG] Missing data or layout:', {
                  hasData: !!plotlyData.data,
                  hasLayout: !!plotlyData.layout,
                  keys: Object.keys(plotlyData)
                });
              }
            } catch (e) {
              console.error('Plotly chart parse error:', e, 'JSON sample:', chartJson.substring(0, 200));
              return (
                <div key={idx} className="my-3 p-4 bg-red-500/10 border border-red-500/50 rounded-xl">
                  <p className="text-red-400 text-sm">⚠️ Interactive chart rendering failed. Check console for details.</p>
                </div>
              );
            }
          }
        }

        // Regular code block — with V5 inline execution for Python
        const langMatch = para.match(/^```(\w+)/);
        const lang = langMatch ? langMatch[1].toLowerCase() : '';
        const codeContent = para.replace(/^```\w*\n?/, '').replace(/```$/, '');
        const isPython = lang === 'python' || lang === 'py' || (!lang && (codeContent.includes('import pandas') || codeContent.includes('import numpy') || codeContent.includes('print(') || codeContent.includes('df.')));
        
        return (
          <InteractiveCodeBlock key={idx} code={codeContent} language={lang || (isPython ? 'python' : 'text')} isPython={isPython} />
        );
      }

      // Images (base64 charts)
      const imageMatch = para.match(/!\[([^\]]*)\]\(([^)]+)\)/);
      if (imageMatch) {
        return <ChartImage key={idx} alt={imageMatch[1]} src={imageMatch[2]} />;
      }

      // Tables
      const tableLines = para.split('\n').filter(l => l.trim().startsWith('|') || l.includes('|'));
      if (tableLines.length >= 2) {
        const isSeparatorLine = (line: string) => /^[\s|:\-]+$/.test(line.replace(/\|/g, ''));
        const hasSeparator = tableLines.length > 1 && isSeparatorLine(tableLines[1]);

        const headers = tableLines[0].split('|').map(h => h.trim()).filter(h => h);
        const dataStartIndex = hasSeparator ? 2 : 1;
        const rows = tableLines.slice(dataStartIndex)
          .filter(row => !isSeparatorLine(row))
          .map(row => row.split('|').map(cell => cell.trim()).filter(cell => cell))
          .filter(row => row.length > 0);

        if (headers.length > 0 && rows.length > 0) {
          return (
            <div key={idx} className="my-4 overflow-x-auto rounded-xl border border-dark-border animate-fade-in">
              <table className="min-w-full">
                <thead className="bg-[var(--bg-secondary)]/50">
                  <tr>
                    {headers.map((header, i) => (
                      <th key={i} className="px-4 py-3 text-left text-sm font-semibold border-b border-[var(--border-color)]" style={{ color: 'var(--text-primary)' }}>
                        <InlineFormattedText text={header} />
                      </th>
                    ))}
                  </tr>
                </thead>
                <tbody className="divide-y divide-[var(--border-color)]">
                  {rows.map((row, i) => (
                    <tr key={i} className="hover:bg-[var(--bg-hover)]/50 transition-colors">
                      {row.map((cell, j) => (
                        <td key={j} className="px-4 py-3 text-sm" style={{ color: 'var(--text-secondary)' }}>
                          <InlineFormattedText text={cell} />
                        </td>
                      ))}
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          );
        }
      }

      // Lists
      const paraLines = para.split('\n');
      const bulletLines = paraLines.filter(line => line.trim().match(/^[-•*]\s/) || line.trim().match(/^[•●]\s?/));
      const numberedLines = paraLines.filter(line => line.trim().match(/^\d+[\.\\)]\s/));

      if (bulletLines.length > 0 && bulletLines.length >= paraLines.length * 0.4) {
        return (
          <ul key={idx} className="space-y-2 my-3">
            {paraLines.map((line, i) => {
              const cleanLine = line.trim();
              if (cleanLine.match(/^[-•*●]\s?/) || cleanLine.match(/^[•●]/)) {
                const text = cleanLine.replace(/^[-•*●]\s*/, '');
                return (
                  <li key={i} className="flex items-start gap-2 text-gray-300">
                    <span className="text-green-400 mt-0.5">•</span>
                    <span><InlineFormattedText text={text} /></span>
                  </li>
                );
              }
              return cleanLine ? <p key={i} className="text-gray-300 ml-5"><InlineFormattedText text={cleanLine} /></p> : null;
            })}
          </ul>
        );
      }

      if (numberedLines.length > 0 && numberedLines.length >= paraLines.length * 0.4) {
        return (
          <ol key={idx} className="space-y-2 my-3">
            {paraLines.map((line, i) => {
              const cleanLine = line.trim();
              const match = cleanLine.match(/^(\d+)[\.\\)]\s*(.*)$/);
              if (match) {
                return (
                  <li key={i} className="flex items-start gap-3 text-gray-300">
                    <span className="text-green-400 font-semibold min-w-[1.5rem]">{match[1]}.</span>
                    <span><InlineFormattedText text={match[2]} /></span>
                  </li>
                );
              }
              return cleanLine ? <p key={i} className="text-gray-300 ml-7"><InlineFormattedText text={cleanLine} /></p> : null;
            })}
          </ol>
        );
      }

      // Regular paragraph
      const formattedHtml = formatInlineText(para).replace(/\n/g, '<br/>');
      return (
        <p key={idx} className="mb-3 text-gray-300 leading-relaxed" dangerouslySetInnerHTML={{ __html: formattedHtml }} />
      );
    });
  };

  return <div className="space-y-1">{formatContent(content)}</div>;
});

// Animated Logo for AI Assistant - Uses actual DataVision logo with subtle animation
// Adapts to light/dark mode automatically
const AnimatedBotIcon: React.FC<{ size?: number; isDark?: boolean }> = ({ size = 28, isDark = true }) => {
  // Determine the logo to use based on theme
  const logoSrc = isDark ? '/datavision-logo-dark.jpg' : '/datavision-logo-light.jpg';
  
  return (
    <div
      className="relative flex items-center justify-center flex-shrink-0 rounded-lg overflow-hidden"
      style={{ 
        width: size, 
        height: size, 
        minWidth: size, 
        minHeight: size,
      }}
    >
      <img
        src={logoSrc}
        alt="DataVision"
        className="w-full h-full object-cover"
        style={{
          animation: 'pulse-glow 2s ease-in-out infinite',
        }}
        onError={(e) => { (e.target as HTMLImageElement).src = '/logo.svg'; }}
      />
      <style>{`
        @keyframes pulse-glow {
          0%, 100% { 
            filter: drop-shadow(0 0 2px rgba(20, 184, 166, 0.4));
            opacity: 1;
          }
          50% { 
            filter: drop-shadow(0 0 6px rgba(20, 184, 166, 0.5));
            opacity: 0.9;
          }
        }
      `}</style>
    </div>
  );
};

// Mode-specific thinking messages (Clean & Simple)
const getModeThinkingText = (modeId: string): string => {
  const thinkingTexts: Record<string, string> = {
    'analyst': 'Analyzing data...',
    'deep': 'Thinking deeply...',
    'vision': 'Analyzing image...',
    'predict': 'Running prediction...',
    'agent': 'Taking action...',
  };
  return thinkingTexts[modeId] || 'Processing...';
};

// Sleek, minimal Thinking Animation Indicator
const TypingIndicator: React.FC<{ mode?: string; isDark?: boolean }> = ({ mode = 'rag', isDark = true }) => {
  const thinkingText = getModeThinkingText(mode);

  return (
    <div className="flex items-center gap-3 py-2 px-3 rounded-xl bg-white/5 border border-white/10 w-fit backdrop-blur-sm animate-pulse">
      <AnimatedBotIcon size={22} isDark={isDark} />
      <div className="flex items-center gap-2">
        <span className="text-xs font-semibold text-[#16A34A]">{thinkingText}</span>
        <div className="flex items-center gap-1">
          <span className="w-1.5 h-1.5 rounded-full bg-[#16A34A] animate-ping" />
          <span className="w-1.5 h-1.5 rounded-full bg-[#16A34A] animate-ping delay-150" />
          <span className="w-1.5 h-1.5 rounded-full bg-[#16A34A] animate-ping delay-300" />
        </div>
      </div>
    </div>
  );
};

// ChatGPT-Style Welcome Screen with Centered Input (includes Mode & MCP controls)
interface WelcomeScreenProps {
  onSuggestionClick: (text: string) => void;
  input: string;
  setInput: (val: string) => void;
  onSend: () => void;
  isLoading: boolean;
  onFileClick: () => void;
  onPaste: (event: React.ClipboardEvent) => void;  // 📋 Added paste handler for new chat
  hasAttachment: boolean;  // 📎 Enable send button when file attached
  imagePreview: string | null;  // 🖼️ Show image preview
  onRemoveImage: () => void;  // ❌ Remove image
  currentMode: { id: string; label: string; icon: any };
  onModeClick: () => void;
  onMcpClick: () => void;
  mcpCount: { active: number; total: number };
  llm: string;
  setLlm: (val: string) => void;
}

const WelcomeScreen: React.FC<WelcomeScreenProps> = ({
  onSuggestionClick,
  input,
  setInput,
  onSend,
  isLoading,
  onFileClick,
  onPaste,  // 📋 Added paste handler
  hasAttachment,  // 📎 Track if file attached
  imagePreview,  // 🖼️ Image preview URL
  onRemoveImage,  // ❌ Remove image handler
  currentMode,
  onModeClick,
  onMcpClick,
  mcpCount,
  llm,
  setLlm
}) => {
  const suggestions = [
    { icon: TrendingUp, text: "Analyze trends in my data" },
    { icon: FileText, text: "Summarize my uploaded data" },
    { icon: Sparkles, text: "What insights can you find?" },
    { icon: Network, text: "Find patterns and correlations" },
  ];

  // Use state for logo to ensure reactivity
  const [logoSrc, setLogoSrc] = React.useState('/datavision-logo-dark.jpg');
  
  React.useEffect(() => {
    const updateLogo = () => {
      const isDarkTheme = !document.documentElement.classList.contains('light-theme');
      setLogoSrc(isDarkTheme ? '/datavision-logo-dark.jpg' : '/datavision-logo-light.jpg');
    };
    updateLogo();
    // Listen for theme changes
    const observer = new MutationObserver(updateLogo);
    observer.observe(document.documentElement, { attributes: true, attributeFilter: ['class'] });
    return () => observer.disconnect();
  }, []);

  return (
    <div className="flex flex-col items-center justify-center h-full px-4">
      {/* Logo - Theme Aware */}
      <div className="w-16 h-16 mb-4 rounded-xl overflow-hidden shadow-lg">
        <img src={logoSrc} alt="DataVision" className="w-full h-full object-cover" onError={(e) => { (e.target as HTMLImageElement).src = '/logo.svg'; }} />
      </div>

      {/* Title - ChatGPT style */}
      <h1 className="text-2xl md:text-3xl font-semibold text-white mb-8 text-center">
        How can I help you today?
      </h1>

      {/* 🖼️ Image Preview - Show attached image above input */}
      {imagePreview && (
        <div className="w-full max-w-3xl mb-4">
          <div className="relative inline-block">
            <img
              src={imagePreview}
              alt="Attached"
              className="max-h-32 rounded-xl border border-green-500/50 shadow-lg"
            />
            <button
              onClick={onRemoveImage}
              className="absolute -top-2 -right-2 w-6 h-6 bg-red-500 hover:bg-red-600 rounded-full flex items-center justify-center text-white shadow-md transition-colors"
              title="Remove image"
            >
              <X className="w-4 h-4" />
            </button>
          </div>
          <p className="text-xs text-green-400 mt-1">📷 Image ready - ask a question about it!</p>
        </div>
      )}

      {/* Centered Search Box - ChatGPT Style with Mode & MCP */}
      <div className="w-full max-w-3xl mb-10">
        <div className="relative flex items-center glass-input rounded-2xl transition-colors">
          {/* MCP Button */}
          <button
            onClick={onMcpClick}
            className="p-3 text-gray-400 hover:text-gray-200 transition-colors relative"
            title="MCP Servers"
          >
            <Database className="w-5 h-5" />
            <span className={`absolute -top-0.5 -right-0.5 w-2 h-2 rounded-full ${mcpCount.active === mcpCount.total ? 'bg-green-500' : 'bg-yellow-500'}`} />
          </button>

          {/* File Attach Button */}
          <button
            onClick={onFileClick}
            className="p-3 text-gray-400 hover:text-gray-200 transition-colors"
            title="Attach file"
          >
            <Paperclip className="w-5 h-5" />
          </button>

          {/* Input Field */}
          <input
            type="text"
            value={input}
            onChange={(e) => setInput(e.target.value)}
            onKeyDown={(e) => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); onSend(); } }}
            onPaste={onPaste}
            placeholder="Ask anything about your data..."
            className="flex-1 bg-transparent text-white placeholder-gray-500 py-4 px-2 outline-none text-base"
          />

          {/* Mode Selector Button */}
          <button
            onClick={onModeClick}
            className="flex items-center gap-1.5 px-3 py-2 bg-[var(--bg-hover)] hover:bg-[var(--bg-secondary)] rounded-lg transition-colors text-sm font-medium whitespace-nowrap mr-1"
            style={{ color: 'var(--text-secondary)' }}
          >
            {currentMode.label}
            <ChevronDown className="w-4 h-4" />
          </button>
          


          {/* Send Button */}
          <button
            onClick={onSend}
            disabled={(!input.trim() && !hasAttachment) || isLoading}
            className={`m-2 p-3 rounded-xl transition-all ${(input.trim() || hasAttachment) && !isLoading
              ? 'bg-green-500 hover:bg-green-600 text-white'
              : 'bg-[var(--bg-hover)] text-gray-400 cursor-not-allowed'
              }`}
          >
            <Send className="w-5 h-5" />
          </button>
        </div>
      </div>

      {/* Suggestion Cards - 2x2 Grid */}
      <div className="grid grid-cols-1 sm:grid-cols-2 gap-3 max-w-2xl w-full">
        {suggestions.map((suggestion, i) => (
          <button
            key={i}
            onClick={() => onSuggestionClick(suggestion.text)}
            className="flex items-center gap-3 p-4 rounded-xl border border-[var(--border-color)] bg-[var(--bg-card)]/30 hover:bg-[var(--bg-hover)] hover:border-gray-500 transition-all duration-200 text-left group"
          >
            <div className="p-2 rounded-lg bg-green-500/10 group-hover:bg-green-500/20 transition-colors">
              <suggestion.icon className="w-5 h-5 text-green-400" />
            </div>
            <span className="text-sm transition-colors group-hover:text-[var(--text-primary)]" style={{ color: 'var(--text-secondary)' }}>
              {suggestion.text}
            </span>
          </button>
        ))}
      </div>
    </div>
  );
};

const AnalystChat: React.FC = () => {
  const navigate = useNavigate();
  const location = useLocation();
  const {
    conversations,
    currentConversationId,
    createConversation,
    deleteConversation,
    selectConversation,
    addMessageToConversation,
    updateConversationMessages,
    getCurrentConversation,
    clearAllChats,
    isDark,
  } = useUserStore();
  
  const { confirm, ConfirmModal } = useConfirmModal();
  const toast = useToast();

  const [input, setInput] = useState('');
  const [isLoading, setIsLoading] = useState(false);
  const [mode, setMode] = useState<string>('analyst');
  const [llm, setLlm] = useState<string>('llama');
  const [isFullscreen, setIsFullscreen] = useState(false);
  
  // Advanced Progressive Loading States
  const [loadingMessage, setLoadingMessage] = useState("Initializing DataVision intelligence...");
  const loadingMessages = [
    "Initializing DataVision intelligence...",
    "Scanning dataset structure...",
    "Identifying patterns and correlations...",
    "Applying predictive models...",
    "Synthesizing insights...",
    "Finalizing response...",
    "Almost there..."
  ];

  useEffect(() => {
    let interval: NodeJS.Timeout;
    if (isLoading) {
      let currentIndex = 0;
      setLoadingMessage(loadingMessages[0]);
      interval = setInterval(() => {
        currentIndex = (currentIndex + 1) % loadingMessages.length;
        // Stop at the last message to avoid looping back to "Initializing..." after a long time
        if (currentIndex === loadingMessages.length - 1) {
          clearInterval(interval);
        }
        setLoadingMessage(loadingMessages[currentIndex]);
      }, 2500);
    }
    return () => clearInterval(interval);
  }, [isLoading]);

  const [isRecording, setIsRecording] = useState(false);
  const [selectedImage, setSelectedImage] = useState<File | null>(null);
  const [imagePreviewUrl, setImagePreviewUrl] = useState<string | null>(null);
  const [attachedFiles, setAttachedFiles] = useState<File[]>([]);
  const [editingMessageId, setEditingMessageId] = useState<string | null>(null);
  const [editingContent, setEditingContent] = useState('');
  const [copiedMessageId, setCopiedMessageId] = useState<string | null>(null);
  const [messageImages, setMessageImages] = useState<Record<string, string>>({});
  const [modeDropdownOpen, setModeDropdownOpen] = useState(false);
  const [animatingMessageId, setAnimatingMessageId] = useState<string | null>(null); // Track which message is animating
  const [sidebarOpen, setSidebarOpen] = useState(true);
  const [mcpDropdownOpen, setMcpDropdownOpen] = useState(false);
  const [plusMenuOpen, setPlusMenuOpen] = useState(false); // Plus menu state
  // 🏆 8 Powerful MCPs - all enabled by default
  const [enabledMcps, setEnabledMcps] = useState<Record<string, boolean>>({
    'data_analyzer': true,
    'pattern_finder': true,
    'forecaster': true,          // NEW: ML predictions
    'anomaly_detector': true,    // NEW: Outlier detection
    'chart_executor': true,      // NEW: Auto-visualization
    'report_generator': true,
    'insight_extractor': true,
    'comparison_engine': true,
  });

  // MCP execution state for Claude-style animations
  const [mcpExecutionStatus, setMcpExecutionStatus] = useState<{
    isRunning: boolean;
    currentTools: Array<{ name: string; icon: string; status: 'pending' | 'running' | 'success' }>;
    startTime: number | null;
  }>({
    isRunning: false,
    currentTools: [],
    startTime: null,
  });

  // MCP Permission Dialog state (Claude-style Allow/Deny)
  const [mcpPermissionDialog, setMcpPermissionDialog] = useState<{
    isOpen: boolean;
    pendingTools: Array<{ name: string; icon: string; description: string }>;
    pendingMessage: string;
    onAllow: (() => void) | null;
    onDeny: (() => void) | null;
  }>({
    isOpen: false,
    pendingTools: [],
    pendingMessage: '',
    onAllow: null,
    onDeny: null,
  });

  // Streaming state for ChatGPT-like word-by-word responses
  const [useStreaming, setUseStreaming] = useState(false); // Disabled - use reliable non-streaming mode
  const [streamingContent, setStreamingContent] = useState('');
  const [streamingMessageId, setStreamingMessageId] = useState<string | null>(null);
  const messagesEndRef = useRef<HTMLDivElement>(null);
  const chatContainerRef = useRef<HTMLDivElement>(null);
  const fileInputRef = useRef<HTMLInputElement>(null);
  const textareaRef = useRef<HTMLTextAreaElement>(null);
  const abortControllerRef = useRef<AbortController | null>(null);

  // Feedback state for thumbs up/down
  const [messageFeedback, setMessageFeedback] = useState<Record<string, 'up' | 'down' | null>>({});

  // Handle stop generation (ChatGPT-style stop button in input area)
  const handleStopGeneration = () => {
    if (abortControllerRef.current) {
      abortControllerRef.current.abort();
      abortControllerRef.current = null;
    }
    setIsLoading(false);
  };

  // Handle thumbs up/down feedback
  const handleFeedback = (messageId: string, type: 'up' | 'down') => {
    setMessageFeedback(prev => ({
      ...prev,
      [messageId]: prev[messageId] === type ? null : type
    }));
    // You could also send this to the backend for analytics
    console.log(`Feedback ${type} for message ${messageId}`);
  };

  // 🏆 5 POWERFUL MCPs - Competition-Winning Tools
  // Each MCP is a unique powerhouse that works autonomously
  const mcpServers = [
    {
      id: 'data_analyzer',
      name: '📊 Data Analyzer',
      icon: '📊',
      description: 'Deep data exploration • Schema analysis • Quality checks',
      power: 'Explores any dataset structure autonomously'
    },
    {
      id: 'pattern_finder',
      name: '🔎 Pattern Finder',
      icon: '🔎',
      description: 'Anomaly detection • Trends • Correlations',
      power: 'Discovers hidden patterns you never noticed'
    },
    {
      id: 'forecaster',
      name: '🔮 Forecaster',
      icon: '🔮',
      description: 'ML predictions • Confidence intervals • Trend projection',
      power: 'Predicts future with scikit-learn algorithms'
    },
    {
      id: 'anomaly_detector',
      name: '⚠️ Anomaly Detector',
      icon: '⚠️',
      description: 'Outlier detection • Z-score analysis • Risk alerts',
      power: 'Finds statistical anomalies automatically'
    },
    {
      id: 'chart_executor',
      name: '📈 Chart Generator',
      icon: '📈',
      description: 'Auto-visualization • Intent detection • Dynamic colors',
      power: 'Creates perfect charts from natural language'
    },
    {
      id: 'report_generator',
      name: '📄 Report Generator',
      icon: '📄',
      description: 'Executive summaries • Key metrics • Recommendations',
      power: 'Creates professional reports in seconds'
    },
    {
      id: 'insight_extractor',
      name: '💡 Insight Extractor',
      icon: '💡',
      description: 'Business opportunities • Pareto analysis • Growth potential',
      power: 'Mines the most valuable insights from your data'
    },
    {
      id: 'comparison_engine',
      name: '⚖️ Comparison Engine',
      icon: '⚖️',
      description: 'Category comparison • Segment analysis • Benchmarks',
      power: 'Compares data across any dimension'
    },
  ];

  // Mode definitions - 5 CORE MODES (Clean & Professional)
  // Each mode has a specific purpose
  const modes = [
    // 📊 ANALYST - Default mode, smart data analysis
    {
      id: 'analyst',
      label: '📊 Analyst',
      icon: FileText,
      description: 'Smart data analysis with charts & insights',
      fullDescription: 'Upload data and ask questions - get instant analysis with visualizations',
      features: ['Data Analysis', 'Auto Charts', 'Insights', 'Summaries'],
      badge: null,
      isAI: false,
      category: 'core',
      supportsText: true,
      supportsCharts: true,
      color: 'from-blue-500 to-cyan-500'
    },
    // 🧠 DEEP THINK - Complex reasoning
    {
      id: 'deep',
      label: '🧠 Deep Think',
      icon: Sparkles,
      description: 'Multi-step reasoning for complex questions',
      fullDescription: 'Think deeper - breaks down complex problems step by step',
      features: ['Deep Research', 'Multi-Step', 'Reasoning', 'Analysis'],
      badge: 'Pro',
      isAI: true,
      category: 'core',
      supportsText: true,
      supportsCharts: true,
      color: 'from-purple-500 to-pink-500'
    },
    // 👁️ VISION - Image analysis
    {
      id: 'vision',
      label: '👁️ Vision',
      icon: Eye,
      description: 'Analyze images, charts, documents & screenshots',
      fullDescription: 'Upload any image and ask questions about it',
      features: ['Image Analysis', 'Chart Reading', 'OCR', 'Document Scan'],
      badge: null,
      isAI: false,
      category: 'core',
      supportsText: true,
      supportsCharts: true,
      supportsImages: true,
      color: 'from-green-500 to-emerald-500'
    },
    // 📈 PREDICT - ML forecasting
    {
      id: 'predict',
      label: '📈 Predict',
      icon: TrendingUp,
      description: 'ML predictions, forecasts & trend analysis',
      fullDescription: 'Predict future trends using machine learning',
      features: ['ML Forecasts', 'Trends', 'Predictions', 'Confidence'],
      badge: 'ML',
      isAI: true,
      category: 'core',
      supportsText: true,
      supportsCharts: true,
      color: 'from-amber-500 to-orange-500'
    },
    // 🤖 AGENT - Autonomous AI
    {
      id: 'agent',
      label: '🤖 Agent',
      icon: Bot,
      description: 'Autonomous AI that takes actions on your data',
      fullDescription: 'Let AI plan and execute multi-step data tasks',
      features: ['Auto Actions', 'Multi-Step', 'Tools', 'Planning'],
      badge: 'Pro',
      isAI: true,
      category: 'core',
      supportsText: true,
      supportsCharts: true,
      color: 'from-red-500 to-rose-500'
    },
  ];

  const currentConversation = getCurrentConversation();
  const messages = currentConversation?.messages.map(m => ({
    ...m,
    timestamp: new Date(m.timestamp)
  })) || [];

  // Auto-send prefilled message from other pages (like Anomaly Monitor)
  useEffect(() => {
    if (location.state?.prefillMessage) {
      const msg = location.state.prefillMessage;
      // Clear the state so it doesn't fire again if the user refreshes the page
      navigate(location.pathname, { replace: true, state: {} });
      // Small delay to ensure state and component are fully mounted
      setTimeout(() => {
        handleSend(msg);
      }, 500);
    }
  }, [location.state, navigate]);

  useEffect(() => {
    if (!currentConversationId && conversations.length > 0) {
      selectConversation(conversations[0].id);
    }
  }, [currentConversationId, conversations]);

  useEffect(() => {
    if (currentConversation) {
      setMode(currentConversation.mode);

      // Restore images from stored imageData in messages
      const restoredImages: Record<string, string> = {};
      currentConversation.messages.forEach((msg: any) => {
        if (msg.imageData) {
          restoredImages[msg.id] = msg.imageData;
        }
      });
      if (Object.keys(restoredImages).length > 0) {
        setMessageImages(prev => ({ ...prev, ...restoredImages }));
      }
    }
  }, [currentConversation?.id]);

  // Listen for file updates from DataHub - notify user when new files are available
  useEffect(() => {
    const handleFilesUpdated = () => {
      console.log('📁 Files updated in chat context');
      // Add a system notification message to let user know data has been refreshed
      if (currentConversationId) {
        const systemMessage = {
          id: `system_${Date.now()}`,
          role: 'assistant' as const,
          content: '📁 **Data Updated!** New files have been uploaded. Your data context has been refreshed. Feel free to ask questions about your updated dataset.',
          timestamp: new Date().toISOString(),
        };
        addMessageToConversation(currentConversationId, systemMessage);
      }
    };

    window.addEventListener('filesUpdated', handleFilesUpdated);
    return () => window.removeEventListener('filesUpdated', handleFilesUpdated);
  }, [currentConversationId, addMessageToConversation]);

  // =========================================================================
  // CHATGPT-STYLE SCROLL LOGIC - OPTIMIZED TO PREVENT JITTER
  // =========================================================================

  // Track previous message count to detect actual new messages
  const prevMessageCountRef = useRef(messages.length);
  const prevLoadingRef = useRef(isLoading);
  const userScrolledUpRef = useRef(false);

  // Check if user is near the bottom of the chat (within 200px)
  const isNearBottom = (): boolean => {
    const container = chatContainerRef.current;
    if (!container) return true;
    return container.scrollHeight - container.scrollTop - container.clientHeight < 200;
  };

  // Scroll to bottom - instant for new messages, smooth for loading
  const scrollToBottom = (behavior: ScrollBehavior = 'smooth') => {
    if (messagesEndRef.current) {
      messagesEndRef.current.scrollIntoView({ behavior, block: 'end' });
    }
  };

  // Track user scroll position to avoid interrupting reading
  useEffect(() => {
    const container = chatContainerRef.current;
    if (!container) return;

    const handleScroll = () => {
      // Mark that user has scrolled up if not near bottom
      userScrolledUpRef.current = !isNearBottom();
    };

    container.addEventListener('scroll', handleScroll, { passive: true });
    return () => container.removeEventListener('scroll', handleScroll);
  }, []);

  // Auto-scroll ONLY when:
  // 1. A NEW message is added (not re-renders)
  // 2. Loading state changes to true (user sent a message)
  // 3. User hasn't scrolled up to read
  useEffect(() => {
    const messageCountChanged = messages.length !== prevMessageCountRef.current;
    const loadingStarted = isLoading && !prevLoadingRef.current;
    
    // Update refs
    prevMessageCountRef.current = messages.length;
    prevLoadingRef.current = isLoading;

    // Only scroll if there's an actual new message or user started loading
    if (messageCountChanged || loadingStarted) {
      // Reset user scrolled flag when they send a new message
      if (loadingStarted) {
        userScrolledUpRef.current = false;
      }
      
      // Don't scroll if user has scrolled up to read earlier messages
      if (!userScrolledUpRef.current) {
        // Use requestAnimationFrame for smooth scroll without jitter
        requestAnimationFrame(() => {
          scrollToBottom(loadingStarted ? 'smooth' : 'instant');
        });
      }
    }
  }, [messages.length, isLoading]);

  useEffect(() => {
    if (textareaRef.current) {
      textareaRef.current.style.height = 'auto';
      textareaRef.current.style.height = `${Math.min(textareaRef.current.scrollHeight, 200)}px`;
    }
  }, [input]);

  const { getRootProps, getInputProps, isDragActive } = useDropzone({
    onDrop: (acceptedFiles: File[]) => {
      // Separate images from other files
      const images = acceptedFiles.filter(f => f.type.startsWith('image/'));
      const otherFiles = acceptedFiles.filter(f => !f.type.startsWith('image/'));
      
      // If there's an image, set it as selected (for vision)
      if (images.length > 0) {
        const imageFile = images[0];
        setSelectedImage(imageFile);
        const reader = new FileReader();
        reader.onload = (e) => {
          setImagePreviewUrl(e.target?.result as string);
        };
        reader.readAsDataURL(imageFile);
        toast.success(`🖼️ Image "${imageFile.name}" ready for analysis!`);
      }
      
      // Add other files as attachments
      if (otherFiles.length > 0) {
        setAttachedFiles(prev => [...prev, ...otherFiles]);
        toast.success(`📎 ${otherFiles.length} file(s) attached!`);
      }
    },
    noClick: true,
    accept: {
      'application/pdf': ['.pdf'],
      'application/vnd.ms-excel': ['.xls'],
      'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': ['.xlsx'],
      'text/csv': ['.csv'],
      'application/json': ['.json'],
      'text/plain': ['.txt'],
      'image/*': ['.png', '.jpg', '.jpeg', '.gif', '.webp', '.bmp'],
      'application/vnd.ms-powerpoint': ['.ppt'],
      'application/vnd.openxmlformats-officedocument.presentationml.presentation': ['.pptx'],
      'application/msword': ['.doc'],
      'application/vnd.openxmlformats-officedocument.wordprocessingml.document': ['.docx'],
    },
  });

  const removeAttachedFile = (index: number) => {
    setAttachedFiles(prev => prev.filter((_, i) => i !== index));
  };

  const handleVoiceInput = async () => {
    if (!('webkitSpeechRecognition' in window) && !('SpeechRecognition' in window)) {
      toast.warning('Speech recognition is not supported in your browser.');
      return;
    }

    const SpeechRecognition = (window as any).SpeechRecognition || (window as any).webkitSpeechRecognition;
    const recognition = new SpeechRecognition();
    recognition.lang = 'en-US';
    recognition.continuous = false;

    recognition.onstart = () => setIsRecording(true);
    recognition.onend = () => setIsRecording(false);

    recognition.onresult = (event: any) => {
      const transcript = event.results[0][0].transcript;
      setInput(prev => prev + ' ' + transcript);
    };

    recognition.onerror = (event: any) => {
      console.error('Speech recognition error:', event.error);
      setIsRecording(false);
    };

    recognition.start();
  };

  const handleImageSelect = (event: React.ChangeEvent<HTMLInputElement>) => {
    const files = event.target.files;
    if (!files || files.length === 0) return;
    
    const fileArray = Array.from(files);
    let hasImage = false;
    const otherFiles: File[] = [];
    
    for (const file of fileArray) {
      if (file.type.startsWith('image/')) {
        // Set first image as the main image for vision
        if (!hasImage) {
          setSelectedImage(file);
          const reader = new FileReader();
          reader.onload = (e) => {
            setImagePreviewUrl(e.target?.result as string);
          };
          reader.readAsDataURL(file);
          hasImage = true;
        }
      } else {
        // Non-image files go to attachedFiles
        otherFiles.push(file);
      }
    }
    
    // Add non-image files as attachments
    if (otherFiles.length > 0) {
      setAttachedFiles(prev => [...prev, ...otherFiles]);
      toast.success(`📎 ${otherFiles.length} file(s) attached!`);
    }
    
    // Set default prompt based on what was uploaded
    if (hasImage && !input.trim()) {
      setInput('What can you see in this image?');
    } else if (otherFiles.length > 0 && !input.trim()) {
      setInput('Analyze this data');
    }
    
    // Reset file input
    event.target.value = '';
  };

  const handlePaste = async (event: React.ClipboardEvent) => {
    const items = event.clipboardData?.items;
    const files = event.clipboardData?.files;
    if (!items && !files) return;

    // Check for pasted files
    if (files && files.length > 0) {
      event.preventDefault();
      for (let i = 0; i < files.length; i++) {
        const file = files[i];
        if (file.type.startsWith('image/')) {
          // Handle image paste
          setSelectedImage(file);
          const reader = new FileReader();
          reader.onload = (e) => {
            setImagePreviewUrl(e.target?.result as string);
          };
          reader.readAsDataURL(file);
          setInput(prev => prev || 'What can you see in this image?');
        } else {
          // Handle other file types (PDF, Excel, CSV, etc.)
          const supportedTypes = [
            'application/pdf',
            'application/vnd.ms-excel',
            'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
            'text/csv',
            'application/json',
            'text/plain'
          ];
          if (supportedTypes.includes(file.type) || file.name.match(/\.(pdf|xlsx|xls|csv|json|txt)$/i)) {
            setAttachedFiles(prev => [...prev, file]);
            toast.success(`📎 File "${file.name}" attached!`);
          }
        }
      }
      return;
    }

    // Check clipboard items for images
    for (let i = 0; i < (items?.length || 0); i++) {
      const item = items![i];
      if (item.type.startsWith('image/')) {
        event.preventDefault();
        const blob = item.getAsFile();
        if (blob) {
          const file = new File([blob], `pasted_image_${Date.now()}.png`, { type: blob.type });
          setSelectedImage(file);
          const reader = new FileReader();
          reader.onload = (e) => {
            setImagePreviewUrl(e.target?.result as string);
          };
          reader.readAsDataURL(file);
          setInput(prev => prev || 'What can you see in this image?');
        }
        break;
      }
    }
  };

  // Reusable function to process user message (MCPs, API, Animation)
  const processUserMessage = async (
    messageText: string,
    convId: string,
    visionAttachments: any[] = [],
    filesToCompare?: string[]
  ) => {
    setIsLoading(true);

    try {
      // Check if we should use streaming (for RAG modes without images)
      const canStream = useStreaming && !visionAttachments.length &&
        ['rag', 'hybrid'].includes(mode);

      if (canStream) {
        // STREAMING MODE - Word by word like ChatGPT
        const assistantMsgId = (Date.now() + 1).toString();

        // Create placeholder message that will be updated
        const streamingAssistantMessage = {
          id: assistantMsgId,
          role: 'assistant' as const,
          content: '',
          timestamp: new Date().toISOString(),
          sources: [] as string[],
        };

        addMessageToConversation(convId, streamingAssistantMessage);
        setStreamingMessageId(assistantMsgId);
        setStreamingContent('');

        let fullContent = '';

        // Get model based on selected LLM
        const model = llm;

        await apiService.streamMessage(
          messageText,
          model,
          'rag',
          // onChunk - update message word by word
          (chunk: string) => {
            fullContent += chunk;
            setStreamingContent(fullContent);

            // Update the message in conversation
            const currentConv = getCurrentConversation();
            if (currentConv) {
              const updatedMessages = currentConv.messages.map(m =>
                m.id === assistantMsgId
                  ? { ...m, content: fullContent }
                  : m
              );
              updateConversationMessages(convId, updatedMessages);
            }
          },
          // onDone
          () => {
            setStreamingMessageId(null);
            setStreamingContent('');
            setIsLoading(false);
          },
          // onError
          (error: string) => {
            console.error('Streaming error:', error);
            const currentConv = getCurrentConversation();
            if (currentConv) {
              // Format error as user-friendly message
              const friendlyError = formatUserFriendlyError(error);
              const updatedMessages = currentConv.messages.map(m =>
                m.id === assistantMsgId
                  ? { ...m, content: fullContent || friendlyError }
                  : m
              );
              updateConversationMessages(convId, updatedMessages);
            }
            setStreamingMessageId(null);
            setIsLoading(false);
          }
        );
      } else {
        // NON-STREAMING MODE - Regular API call with MCP animation
        let mcpsToUse = enabledMcps;

        // Detect which MCPs might be triggered based on query (EXPANDED keyword matching)
        const queryLower = messageText.toLowerCase();
        const potentialTools: Array<{ name: string; icon: string; status: 'pending' | 'running' | 'success'; description: string }> = [];

        // Helper function for partial keyword matching
        const matchesAny = (keywords: string[]) => keywords.some(kw => queryLower.includes(kw));

        // 🏆 DETECT 5 POWERFUL MCPs based on query
        if (enabledMcps.data_analyzer && matchesAny(['analyz', 'explore', 'schema', 'structure', 'columns', 'data type', 'overview', 'describe', 'what data', 'statistics', 'stats'])) {
          potentialTools.push({ name: '🔍 Data Analyzer', icon: '🔍', status: 'pending', description: 'Deep data exploration & schema analysis' });
        }
        if (enabledMcps.pattern_finder && matchesAny(['pattern', 'anomal', 'outlier', 'trend', 'unusual', 'spike', 'drop', 'correlation', 'detect', 'discover', 'hidden'])) {
          potentialTools.push({ name: '🔎 Pattern Finder', icon: '🔎', status: 'pending', description: 'Finds patterns, anomalies & correlations' });
        }
        if (enabledMcps.report_generator && matchesAny(['report', 'summary', 'executive', 'document', 'presentation', 'findings', 'conclusion', 'recommend'])) {
          potentialTools.push({ name: '📄 Report Generator', icon: '📄', status: 'pending', description: 'Creates professional reports' });
        }
        if (enabledMcps.insight_extractor && matchesAny(['insight', 'key', 'important', 'valuable', 'business', 'opportunit', 'risk', 'growth', 'potential', 'learn'])) {
          potentialTools.push({ name: '💡 Insight Extractor', icon: '💡', status: 'pending', description: 'Mines valuable insights from data' });
        }
        if (enabledMcps.comparison_engine && matchesAny(['compare', 'versus', 'vs', 'difference', 'between', 'segment', 'category', 'breakdown', 'by', 'top', 'bottom', 'best', 'worst'])) {
          potentialTools.push({ name: '⚖️ Comparison Engine', icon: '⚖️', status: 'pending', description: 'Compares across dimensions' });
        }

        // 🚀 SPEED OPTIMIZATION: Skip MCP permission dialog for faster responses
        // MCPs are auto-allowed silently (like Claude after first authorization)
        // This removes the 300-400ms delay per tool and permission dialog wait time
        if (potentialTools.length > 0) {
          // Show quick MCP indicator (non-blocking)
          setMcpExecutionStatus({
            isRunning: true,
            currentTools: potentialTools.slice(0, 2).map((t, idx) => ({
              name: t.name,
              icon: t.icon,
              status: idx === 0 ? 'running' : 'pending'
            })),
            startTime: Date.now(),
          });
        }

        // 🧠 BUILD CONVERSATION HISTORY FOR PERSISTENT MEMORY
        // Get last 10 messages for context (like ChatGPT/Claude)
        const currentConv = getCurrentConversation();
        const recentHistory = currentConv?.messages
          .slice(-10)
          .map(m => ({
            role: m.role,
            content: m.content.substring(0, 500) // Limit content length
          })) || [];

        const response = await apiService.sendMessage(
          messageText,
          llm,
          mode,
          convId,
          filesToCompare && filesToCompare.length > 0 ? filesToCompare : undefined,
          visionAttachments.length > 0 ? visionAttachments : undefined,
          mcpsToUse,
          recentHistory // Pass conversation history for memory
        );

        // Clear MCP animation
        setMcpExecutionStatus({ isRunning: false, currentTools: [], startTime: null });

        const responseContent = response.data?.message || response.data?.answer || 'No response received';
        const responseSources = response.data?.sources || [];
        const responseSuggestions = response.data?.suggestions || [];
        const responseConfidence = response.data?.confidence;

        const assistantMessage = {
          id: (Date.now() + 1).toString(),
          role: 'assistant' as const,
          content: String(responseContent),
          timestamp: new Date().toISOString(),

          sources: Array.isArray(responseSources) ? responseSources.map(s => String(s)) : [],
          // 🏆 Competition-winning features
          suggestions: responseSuggestions,
          confidence: responseConfidence,
          mode: mode,
        };

        addMessageToConversation(convId, assistantMessage);
        setAnimatingMessageId(assistantMessage.id); // Trigger typewriter animation
        setIsLoading(false);
      }
    } catch (error: any) {
      console.error('Error processing message:', error);
      // Check for rate limit error first (added by our interceptor)
      let friendlyError: string;
      if (error.isRateLimited) {
        friendlyError = error.rateLimitMessage;
      } else if (error.serverErrorMessage) {
        friendlyError = error.serverErrorMessage;
      } else {
        // Format error as user-friendly message
        const rawError = error.response?.data?.detail || error.message || 'Unknown error';
        friendlyError = formatUserFriendlyError(rawError);
      }
      const errorMessage = {
        id: (Date.now() + 1).toString(),
        role: 'assistant' as const,
        content: friendlyError,
        timestamp: new Date().toISOString(),
      };
      addMessageToConversation(convId, errorMessage);
      setIsLoading(false);
      setMcpExecutionStatus({ isRunning: false, currentTools: [], startTime: null });
    }
  };

  const handleSend = async (eOrText?: React.MouseEvent | string) => {
    let textOverride: string | undefined;
    if (typeof eOrText === 'string') {
      textOverride = eOrText;
    }

    const textToProcess = typeof textOverride === 'string' ? textOverride : input;
    const hasContent = textToProcess.trim().length > 0 || selectedImage || attachedFiles.length > 0;
    if (!hasContent || isLoading) return;

    let convId = currentConversationId;
    if (!convId) {
      convId = createConversation(mode);
    }

    const userMessage: any = {
      id: Date.now().toString(),
      role: 'user' as const,
      content: textToProcess.trim(),
      timestamp: new Date().toISOString(),
      imageData: null,
    };

    // If image selected, read as base64 BEFORE adding to conversation
    if (selectedImage) {
      const base64Content = await new Promise<string>((resolve) => {
        const reader = new FileReader();
        reader.onload = () => resolve(reader.result as string);
        reader.readAsDataURL(selectedImage);
      });

      // Store base64 in message for persistence
      userMessage.imageData = base64Content;
      // Also set in messageImages state for immediate display
      setMessageImages(prev => ({ ...prev, [userMessage.id]: base64Content }));
    }

    addMessageToConversation(convId, userMessage);

    // Scroll to bottom immediately after sending message (ChatGPT behavior)
    setTimeout(() => scrollToBottom('smooth'), 100);

    const messageToSend = textToProcess.trim();
    const filesToCompare = attachedFiles.map(f => f.name);

    // Create vision attachments
    let visionAttachments: any[] = [];
    // Use the already-stored imageData from userMessage
    if (userMessage.imageData) {
      visionAttachments.push({
        name: 'uploaded_image',
        type: 'image/png',
        size: 0,
        content: userMessage.imageData
      });
    }

    // Upload files
    if (attachedFiles.length > 0) {
      await apiService.uploadFiles(attachedFiles);
      window.dispatchEvent(new CustomEvent('filesUpdated'));
    }

    // Reset Input if we were using the text area
    if (typeof textOverride !== 'string') {
      setInput('');
    }
    setSelectedImage(null);
    setImagePreviewUrl(null);
    setAttachedFiles([]);

    // Process Message
    await processUserMessage(messageToSend, convId, visionAttachments, filesToCompare);
  };

  const handleEditMessage = (messageId: string, content: string) => {
    setEditingMessageId(messageId);
    setEditingContent(content);
  };

  const handleCancelEdit = () => {
    setEditingMessageId(null);
    setEditingContent('');
  };

  const handleSaveAndResend = async (messageId: string) => {
    if (!editingContent.trim() || isLoading) return;

    const messageIndex = messages.findIndex(m => m.id === messageId);
    if (messageIndex === -1) return;

    let convId = currentConversationId || createConversation(mode);

    const messagesToKeep = messages.slice(0, messageIndex).map(m => ({
      ...m,
      timestamp: m.timestamp instanceof Date ? m.timestamp.toISOString() : m.timestamp
    }));

    updateConversationMessages(convId, messagesToKeep);

    const messageToSend = editingContent.trim();

    setEditingMessageId(null);
    setEditingContent('');

    const userMessage = {
      id: Date.now().toString(),
      role: 'user' as const,
      content: messageToSend,
      timestamp: new Date().toISOString(),
    };
    addMessageToConversation(convId, userMessage);

    await processUserMessage(messageToSend, convId);
  };

  const handleCopyMessage = async (messageId: string, content: string) => {
    try {
      await navigator.clipboard.writeText(content);
      setCopiedMessageId(messageId);
      setTimeout(() => setCopiedMessageId(null), 2000);
    } catch (error) {
      console.error('Failed to copy:', error);
    }
  };

  // Handle export message to PDF/PPTX/Email
  const handleExportMessage = async (content: string, format: 'pdf' | 'pptx' | 'email') => {
    try {
      const response = await fetch('/api/v1/exports/generate', {
        method: 'POST',
        headers: getAuthHeadersSync(),
        body: JSON.stringify({
          title: 'Business Analyst Report',
          content: content,
          format: format,
          workspace_id: getUserIdSync()
        })
      });

      if (!response.ok) throw new Error('Export failed');

      const data = await response.json();

      // Decode base64 and download
      const binaryString = atob(data.content_base64);
      const bytes = new Uint8Array(binaryString.length);
      for (let i = 0; i < binaryString.length; i++) {
        bytes[i] = binaryString.charCodeAt(i);
      }
      const blob = new Blob([bytes], { type: data.content_type });
      const url = URL.createObjectURL(blob);

      const a = document.createElement('a');
      a.href = url;
      a.download = data.filename;
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
      URL.revokeObjectURL(url);
    } catch (error: any) {
      console.error('Export failed:', error);
      toast.error('Export failed: ' + (error.message || 'Unknown error'));
    }
  };

  // Handle regenerate response - find the previous user message and resend it
  const handleRegenerate = async (messageId: string) => {
    const currentConv = getCurrentConversation();
    if (!currentConv) return;

    // Find the assistant message index
    const msgIndex = currentConv.messages.findIndex(m => m.id === messageId);
    if (msgIndex <= 0) return;

    // Find the previous user message
    let userMsgIndex = msgIndex - 1;
    while (userMsgIndex >= 0 && currentConv.messages[userMsgIndex].role !== 'user') {
      userMsgIndex--;
    }
    if (userMsgIndex < 0) return;

    const userMessage = currentConv.messages[userMsgIndex] as any;

    // Remove the assistant message we're regenerating
    const updatedMessages = currentConv.messages.filter((_, i) => i !== msgIndex);
    updateConversationMessages(currentConv.id, updatedMessages);

    // Prepare vision attachments if image existed
    let visionAttachments: any[] = [];
    if (userMessage.imageData) {
      visionAttachments.push({
        name: 'uploaded_image',
        type: 'image/png',
        size: 0,
        content: userMessage.imageData
      });
    }

    // Call processUserMessage
    await processUserMessage(userMessage.content, currentConv.id, visionAttachments);
  };

  const handleNewChat = () => {
    // Reset all file states for new chat to enable immediate upload
    setSelectedImage(null);
    setImagePreviewUrl(null);
    setAttachedFiles([]);
    setInput('');
    setIsLoading(false);
    setEditingMessageId(null);
    setEditingContent('');
    // Create new conversation
    createConversation(mode);
  };

  const handleDeleteConversation = async (id: string, e: React.MouseEvent) => {
    e.stopPropagation();
    const conv = conversations.find(c => c.id === id);
    const confirmed = await confirm({
      title: 'Delete Conversation',
      message: `Delete "${conv?.title || 'this conversation'}"? This cannot be undone.`,
      confirmText: 'Delete',
      cancelText: 'Keep',
      variant: 'danger',
    });
    
    if (confirmed) {
      deleteConversation(id);
      toast.deleted('Conversation Deleted');
    }
  };

  const handleSuggestionClick = (text: string) => {
    setInput(text);
    textareaRef.current?.focus();
  };

  const formatDate = (dateStr: string) => {
    const date = new Date(dateStr);
    const now = new Date();
    const diffDays = Math.floor((now.getTime() - date.getTime()) / (1000 * 60 * 60 * 24));

    if (diffDays === 0) return 'Today';
    if (diffDays === 1) return 'Yesterday';
    if (diffDays < 7) return `${diffDays} days ago`;
    return date.toLocaleDateString();
  };

  const currentMode = modes.find(m => m.id === mode) || modes[0]; // Safe fallback to analyst

  // Refs for click-outside detection
  const mcpMenuRef = useRef<HTMLDivElement>(null);
  const modeMenuRef = useRef<HTMLDivElement>(null);

  // Close dropdowns when clicking outside
  useEffect(() => {
    const handleClickOutside = (event: MouseEvent | TouchEvent) => {
      if (mcpDropdownOpen && mcpMenuRef.current && !mcpMenuRef.current.contains(event.target as Node)) {
        // Check if the click was on the toggle button - if so, let the button handle it
        const target = event.target as Element;
        if (!target.closest('button[title="MCP Servers"]')) {
          setMcpDropdownOpen(false);
        }
      }
      if (modeDropdownOpen && modeMenuRef.current && !modeMenuRef.current.contains(event.target as Node)) {
        // Check if the click was on the toggle button
        const target = event.target as Element;
        if (
          !target.closest('button[title="Analysis Modes"]') &&
          !target.closest('.mode-selector-btn') // Add class to mode buttons to be safe
        ) {
          setModeDropdownOpen(false);
        }
      }
    };

    document.addEventListener('mousedown', handleClickOutside);
    document.addEventListener('touchstart', handleClickOutside);
    return () => {
      document.removeEventListener('mousedown', handleClickOutside);
      document.removeEventListener('touchstart', handleClickOutside);
    };
  }, [mcpDropdownOpen, modeDropdownOpen]);

  return (
    <div className="flex h-screen sm:h-[100dvh] overflow-hidden bg-[var(--bg-primary)] w-full max-w-[100vw]" style={{ overflowX: 'hidden' }} {...getRootProps()}>
      <input {...getInputProps()} />

      {/* 📎 DRAG OVERLAY - Visual feedback when dragging files */}
      {isDragActive && (
        <div className="fixed inset-0 z-[100] bg-black/70 backdrop-blur-sm flex items-center justify-center">
          <div className="p-8 rounded-2xl border-2 border-dashed border-green-500 bg-green-500/10 text-center animate-pulse">
            <div className="text-6xl mb-4">📎</div>
            <h3 className="text-2xl font-bold text-white mb-2">Drop your files here</h3>
            <p className="text-gray-300">
              Supports: Images, PDF, Excel, CSV, JSON, Word, PowerPoint
            </p>
          </div>
        </div>
      )}

      {/* Mobile Sidebar Overlay - CSS transitions instead of Framer Motion for performance */}
      {sidebarOpen && (
        <div
          onClick={() => setSidebarOpen(false)}
          className="md:hidden fixed inset-0 z-40 bg-black/50 backdrop-blur-sm transition-opacity duration-200"
        />
      )}

      {/* Sidebar - Desktop Fixed / Mobile Drawer */}
      <aside className={`
        fixed md:static inset-y-0 left-0 z-50 w-[260px] bg-[var(--bg-card)] border-r border-[var(--border-color)] flex flex-col transition-transform duration-300 transform
        ${sidebarOpen ? 'translate-x-0' : '-translate-x-full md:translate-x-0 md:w-0 md:border-none md:overflow-hidden'}
      `}>
        {/* Sidebar Header */}
        <div className="p-4 border-b border-[var(--border-color)] flex items-center justify-between min-w-[256px]">
          <h2 className="text-lg font-semibold text-white">Chat History</h2>
          {/* Mobile close button */}
          <button
            onClick={() => setSidebarOpen(false)}
            className="lg:hidden p-1 hover:bg-[var(--bg-hover)] rounded-lg transition-colors"
            title="Close"
          >
            <X className="w-5 h-5 text-gray-400" />
          </button>
        </div>

        {/* New Chat Button */}
        <div className="p-3">
          <button
            onClick={handleNewChat}
            className="w-full flex items-center justify-center gap-2 py-3 px-4 btn-new-chat rounded-xl text-sm font-medium shadow-sm transition-all"
          >
            <Plus className="w-4 h-4" />
            New Chat
          </button>
        </div>

        {/* Chat List */}
        <div className="flex-1 overflow-y-auto p-2">
          <div className="flex items-center justify-between px-2 py-2 mb-2">
            <span className="text-xs font-semibold text-gray-500 uppercase tracking-wider">Recent</span>
            {conversations.length > 1 && (
              <button
                onClick={async (e) => {
                  e.preventDefault();
                  e.stopPropagation();
                  const confirmed = await confirm({
                    title: 'Clear All Chats',
                    message: 'Are you sure you want to clear all chat history? This action cannot be undone.',
                    confirmText: 'Clear All',
                    variant: 'danger',
                    icon: <Trash2 className="w-6 h-6" />
                  });
                  if (confirmed) {
                    clearAllChats();
                    toast.deleted('All chat history cleared');
                  }
                }}
                className="text-xs text-gray-500 hover:text-red-400 transition-colors"
              >
                Clear all
              </button>
            )}
          </div>

          <div className="space-y-1">
            {conversations.map((conv) => (
              <div
                key={conv.id}
                onClick={() => selectConversation(conv.id)}
                className={`group flex items-center gap-2 p-3 rounded-lg cursor-pointer chat-item ${currentConversationId === conv.id ? 'active' : ''}`}
              >
                <MessageSquare className={`w-4 h-4 flex-shrink-0 ${currentConversationId === conv.id ? 'text-green-400' : 'text-gray-500'}`} />
                <div className="flex-1 min-w-0">
                  <p className={`text-sm truncate ${currentConversationId === conv.id ? 'text-gray-100' : 'text-gray-300'}`}>
                    {conv.title}
                  </p>
                  <p className="text-xs text-gray-500">{formatDate(conv.updatedAt)}</p>
                </div>
                <button
                  onClick={(e) => {
                    e.preventDefault();
                    e.stopPropagation();
                    handleDeleteConversation(conv.id, e);
                  }}
                  className="opacity-0 group-hover:opacity-100 p-1.5 hover:bg-red-500/20 rounded-lg transition-all"
                  title="Delete"
                >
                  <Trash2 className="w-3.5 h-3.5 text-gray-400 hover:text-red-400" />
                </button>
              </div>
            ))}
          </div>
        </div>

        {/* Sidebar Footer */}
        <div className="p-3 border-t border-[var(--border-color)] space-y-1">
          <button
            onClick={() => navigate('/settings')}
            className="flex items-center gap-2 w-full p-2 rounded-lg hover:bg-[var(--bg-hover)] text-gray-400 hover:text-gray-200 transition-colors text-sm"
          >
            <Settings className="w-4 h-4" />
            Settings
          </button>
          <button
            onClick={() => navigate('/datahub')}
            className="flex items-center gap-2 w-full p-2 rounded-lg hover:bg-[var(--bg-hover)] text-gray-400 hover:text-gray-200 transition-colors text-sm"
          >
            <ArrowLeft className="w-4 h-4" />
            Back to DataHub
          </button>
        </div>
      </aside>

      {/* Main Content Area */}
      <div className="flex-1 flex flex-col relative min-w-0 bg-[var(--bg-primary)]">

        {/* Top Navigation Bar - Now visible on Desktop too */}
        <div className="h-16 border-b border-[var(--border-color)] flex items-center justify-between px-4 bg-[var(--bg-card)]/50 backdrop-blur-sm sticky top-0 z-20">
          <div className="flex items-center gap-3">
            <button
              onClick={() => setSidebarOpen(!sidebarOpen)}
              className="p-2 hover:bg-[var(--bg-hover)] rounded-lg transition-colors text-gray-400 hover:text-white"
              title={sidebarOpen ? "Close sidebar" : "Open sidebar"}
            >
              <Menu className="w-5 h-5" />
            </button>
            {/* Only show title when there are messages */}
            {messages.length > 0 && (
              <div className="flex flex-col">
                <h1 className="text-base font-semibold text-white leading-tight">Analyst Chat</h1>
                <p className="text-xs text-gray-500">
                  {currentMode.label} Mode • {Object.values(enabledMcps).filter(Boolean).length} Active Tools
                </p>
              </div>
            )}
          </div>

          {/* Top Right Actions */}
          <div className="flex items-center gap-2">
            <button
              onClick={async () => {
                if (messages.length === 0) {
                  toast.warning("No chat history to export.");
                  return;
                }
                const content = messages.map(m => `[${m.role.toUpperCase()}]\n${m.content}`).join('\n\n');
                await handleExportMessage(content, 'pdf');
              }}
              className="hidden sm:flex items-center gap-2 px-3 py-1.5 rounded-lg text-xs font-medium transition-colors bg-[var(--bg-hover)] text-gray-400 hover:text-white"
              title="Export Chat to PDF"
            >
              <FileText className="w-3 h-3" />
              Export PDF
            </button>
            <button
              onClick={() => setUseStreaming(!useStreaming)}
              className={`hidden sm:flex items-center gap-2 px-3 py-1.5 rounded-lg text-xs font-medium transition-colors ${useStreaming ? 'bg-green-500/10 text-green-400' : 'bg-[var(--bg-hover)] text-gray-500'
                }`}
              title="Toggle Streaming"
            >
              <Zap className={`w-3 h-3 ${useStreaming ? 'fill-current' : ''}`} />
              {useStreaming ? 'Fast' : 'Standard'}
            </button>
          </div>
        </div>

        {/* Messages Container - Scrollable with ChatGPT-like experience */}
        <div ref={chatContainerRef} className="flex-1 overflow-y-auto custom-scrollbar">
          <div className={`max-w-3xl mx-auto px-4 ${messages.length === 0 ? 'h-full flex flex-col justify-center py-8' : 'py-6 pb-40'}`}>
            {messages.length === 0 ? (
              <WelcomeScreen
                onSuggestionClick={handleSuggestionClick}
                input={input}
                setInput={setInput}
                onSend={handleSend}
                isLoading={isLoading}
                onFileClick={() => fileInputRef.current?.click()}
                onPaste={handlePaste}
                hasAttachment={!!(selectedImage || attachedFiles.length > 0)}
                imagePreview={imagePreviewUrl}
                onRemoveImage={() => { setSelectedImage(null); setImagePreviewUrl(null); }}
                currentMode={currentMode}
                onModeClick={() => setModeDropdownOpen(true)}
                onMcpClick={() => setMcpDropdownOpen(true)}
                mcpCount={{ active: Object.values(enabledMcps).filter(Boolean).length, total: mcpServers.length }}
                llm={llm}
                setLlm={setLlm}
              />
            ) : (
              <div className="space-y-4">
                {messages.filter(msg => msg && msg.id && msg.content).map((message) => (
                  <div
                    key={message.id}
                    className={`flex ${message.role === 'user' ? 'justify-end' : 'justify-start'} group`}
                  >
                    {message.role === 'user' ? (
                      // User Message - Right side, contained bubble
                      <div className="flex flex-col items-end max-w-[85%]">
                        {editingMessageId === message.id ? (
                          <div className="w-full">
                            <textarea
                              value={editingContent}
                              onChange={(e) => setEditingContent(e.target.value)}
                              onKeyDown={(e) => {
                                if (e.key === 'Enter' && !e.shiftKey) {
                                  e.preventDefault();
                                  if (editingContent.trim()) {
                                    handleSaveAndResend(message.id);
                                  }
                                }
                                if (e.key === 'Escape') {
                                  handleCancelEdit();
                                }
                              }}
                              className="w-full p-4 bg-[var(--bg-card)] border border-accent-primary rounded-xl resize-none focus:outline-none focus:ring-2 focus:ring-accent-primary text-gray-100"
                              rows={3}
                              autoFocus
                            />
                            <div className="flex justify-end gap-2 mt-2">
                              <button onClick={handleCancelEdit} className="px-3 py-1.5 text-sm text-gray-400 hover:text-white">
                                Cancel
                              </button>
                              <button
                                onClick={() => handleSaveAndResend(message.id)}
                                disabled={!editingContent.trim()}
                                className="px-4 py-1.5 bg-green-600 hover:bg-green-700 text-white text-sm rounded-lg disabled:opacity-50"
                              >
                                Save & Resend
                              </button>
                            </div>
                          </div>
                        ) : (
                          <>
                            <div className="px-4 py-3 chat-bubble-user rounded-2xl rounded-br-md shadow-lg">
                              <p className="whitespace-pre-wrap">{message.content}</p>
                              {messageImages[message.id] && (
                                <img src={messageImages[message.id]} alt="Uploaded" className="mt-3 max-w-full rounded-lg" />
                              )}
                            </div>
                            <div className="flex gap-1 mt-1 opacity-0 group-hover:opacity-100 transition-opacity">
                              <button onClick={() => handleCopyMessage(message.id, message.content)} className="p-1 hover:bg-[var(--bg-hover)] rounded text-gray-500 hover:text-gray-300">
                                {copiedMessageId === message.id ? <CheckCheck className="w-4 h-4 text-green-400" /> : <Copy className="w-4 h-4" />}
                              </button>
                              <button onClick={() => handleEditMessage(message.id, message.content)} className="p-1 hover:bg-[var(--bg-hover)] rounded text-gray-500 hover:text-gray-300">
                                <Pencil className="w-4 h-4" />
                              </button>
                            </div>
                          </>
                        )}
                      </div>
                    ) : (
                      // Bot Message - Left side with logo, full width response
                      <div className="flex items-start gap-3 w-full max-w-full bot-message-animate">
                        {/* DataVision Logo with animation */}
                        <div className="w-8 h-8 flex-shrink-0 mt-1 flex items-center justify-center">
                          <AnimatedBotIcon size={24} isDark={isDark} />
                        </div>
                        <div className="flex-1">
                          {/* 🎯 DIRECT ANSWER BADGE - Show key value prominently first */}
                          {(() => {
                            // Find the user message that preceded this response
                            const msgIndex = messages.findIndex(m => m.id === message.id);
                            const userMsg = msgIndex > 0 ? messages.slice(0, msgIndex).reverse().find(m => m.role === 'user') : null;
                            const directAnswer = userMsg ? extractDirectAnswer(message.content, userMsg.content) : null;
                            return directAnswer && <DirectAnswerBadge answer={directAnswer} />;
                          })()}
                          
                          <div className="prose prose-invert max-w-none">
                            <TypewriterText
                              content={message.content || 'No content'}
                              isNew={message.id === animatingMessageId}
                              onComplete={() => setAnimatingMessageId(null)}
                            />

                            {message.sources && Array.isArray(message.sources) && message.sources.length > 0 && (
                              <div className="mt-4 pt-4 border-t border-[var(--border-color)]">
                                <p className="text-xs font-semibold text-gray-500 mb-2 flex items-center gap-1">
                                  <FileText className="w-3 h-3" /> Sources
                                </p>
                                <div className="flex flex-wrap gap-2">
                                  {message.sources.map((source, i) => (
                                    <span key={i} className="px-2 py-1 bg-green-500/20 text-green-300 rounded-lg text-xs">
                                      {String(source)}
                                    </span>
                                  ))}
                                </div>
                              </div>
                            )}
                          </div>
                          <div className="flex gap-1 mt-2 opacity-0 group-hover:opacity-100 transition-opacity">
                            <button onClick={() => handleCopyMessage(message.id, message.content)} className="p-1.5 hover:bg-[var(--bg-hover)] rounded-lg text-gray-500 hover:text-gray-300 transition-colors" title="Copy">
                              {copiedMessageId === message.id ? <CheckCheck className="w-4 h-4 text-green-400" /> : <Copy className="w-4 h-4" />}
                            </button>
                            <button
                              onClick={() => handleFeedback(message.id, 'up')}
                              className={`p-1.5 hover:bg-[var(--bg-hover)] rounded-lg transition-colors ${messageFeedback[message.id] === 'up'
                                ? 'text-green-400 bg-green-400/10'
                                : 'text-gray-500 hover:text-green-400'
                                }`}
                              title="Good response"
                            >
                              <svg className="w-4 h-4" fill={messageFeedback[message.id] === 'up' ? 'currentColor' : 'none'} stroke="currentColor" viewBox="0 0 24 24">
                                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M14 10h4.764a2 2 0 011.789 2.894l-3.5 7A2 2 0 0115.263 21h-1.53a2 2 0 01-1.271-.453L11 19.5a3 3 0 01-1-2.236V13a3 3 0 011-2.236L14 8.5V10z" />
                                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M5 10h-.5a2 2 0 00-2 2v6a2 2 0 002 2h.5" />
                              </svg>
                            </button>
                            <button
                              onClick={() => handleFeedback(message.id, 'down')}
                              className={`p-1.5 hover:bg-[var(--bg-hover)] rounded-lg transition-colors ${messageFeedback[message.id] === 'down'
                                ? 'text-red-400 bg-red-400/10'
                                : 'text-gray-500 hover:text-red-400'
                                }`}
                              title="Bad response"
                            >
                              <svg className="w-4 h-4" fill={messageFeedback[message.id] === 'down' ? 'currentColor' : 'none'} stroke="currentColor" viewBox="0 0 24 24">
                                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M10 14H5.236a2 2 0 01-1.789-2.894l3.5-7A2 2 0 018.737 3h1.53a2 2 0 011.271.453L13 4.5a3 3 0 011 2.236V11a3 3 0 01-1 2.236L10 15.5V14z" />
                                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M19 14h.5a2 2 0 002-2V6a2 2 0 00-2-2h-.5" />
                              </svg>
                            </button>
                            <button
                              onClick={() => handleRegenerate(message.id)}
                              className="p-1.5 hover:bg-[var(--bg-hover)] rounded-lg text-gray-500 hover:text-green-400 transition-colors"
                              title="Regenerate response"
                            >
                              <RefreshCw className="w-4 h-4" />
                            </button>
                          </div>

                          {/* 🏆 Dynamic Follow-up Suggestions - Competition Winner Feature */}
                          {message.suggestions && message.suggestions.length > 0 && (
                            <div className="mt-4 pt-3 border-t border-[var(--border-color)]/50 animate-fadeIn">
                              <p className="text-xs text-gray-500 mb-2 flex items-center gap-1">
                                <Sparkles className="w-3 h-3 text-green-400" /> Follow-up questions
                              </p>
                              <div className="flex flex-wrap gap-2">
                                {message.suggestions.map((suggestion: string, i: number) => (
                                  <button
                                    key={i}
                                    onClick={() => {
                                      setInput(suggestion);
                                      const inputEl = document.querySelector('textarea');
                                      inputEl?.focus();
                                    }}
                                    className="px-3 py-1.5 bg-green-50 dark:bg-green-500/10 hover:bg-green-100 dark:hover:bg-green-500/20 border border-green-200 dark:border-green-500/30 rounded-full text-xs text-green-700 dark:text-green-300 transition-colors duration-200"
                                  >
                                    {suggestion}
                                  </button>
                                ))}
                              </div>
                            </div>
                          )}

                          {/* 🏆 Confidence Indicator - Shows data grounding quality */}
                          {message.confidence !== undefined && (
                            <div className="mt-3 flex items-center gap-2 text-xs">
                              <span className="text-gray-500">Data Confidence:</span>
                              <div className="flex items-center gap-1">
                                <div className={`w-2 h-2 rounded-full ${message.confidence > 0.8 ? 'bg-green-500' :
                                  message.confidence > 0.5 ? 'bg-yellow-500' : 'bg-red-500'
                                  }`} />
                                <span className={`${message.confidence > 0.8 ? 'text-green-400' :
                                  message.confidence > 0.5 ? 'text-yellow-400' : 'text-red-400'
                                  }`}>
                                  {message.confidence > 0.8 ? 'High - grounded in data' :
                                    message.confidence > 0.5 ? 'Medium' : 'Low - limited data'}
                                </span>
                              </div>
                            </div>
                          )}

                          {/* 🤖 ML Charts - Matplotlib/Seaborn Visualizations from Predict Mode */}
                          {(message as any).mlCharts && Array.isArray((message as any).mlCharts) && (message as any).mlCharts.length > 0 && (
                            <div className="mt-4 space-y-4">
                              <div className="flex items-center gap-2 text-sm text-green-400 border-t border-[var(--border-color)] pt-3">
                                <Zap className="w-4 h-4" />
                                <span>ML Visualizations • Real scikit-learn analysis</span>
                              </div>
                              {(message as any).mlCharts.map((chart: { type: string; image: string; title?: string }, i: number) => (
                                chart.image && (
                                  <div key={i} className="p-4 bg-gradient-to-br from-[var(--bg-secondary)] to-[var(--bg-primary)] rounded-xl border border-[var(--border-color)] shadow-lg">
                                    <div className="flex items-center gap-2 mb-3">
                                      <span className="text-lg">
                                        {chart.type === 'ml_forecast' ? '📈' :
                                          chart.type === 'ml_importance' ? '🔑' :
                                            chart.type === 'ml_correlation' ? '🔗' :
                                              chart.type === 'ml_distribution' ? '📊' :
                                                chart.type === 'ml_summary' ? '🤖' : '📊'}
                                      </span>
                                      <span className="text-sm font-medium text-green-400">
                                        {chart.title || 'ML Visualization'}
                                      </span>
                                      <span className="text-xs text-gray-500 ml-auto">
                                        scikit-learn + matplotlib
                                      </span>
                                    </div>
                                    <ChartImage src={chart.image} alt={chart.title || 'ML Chart'} />
                                  </div>
                                )
                              ))}
                            </div>
                          )}
                        </div>
                      </div>
                    )}
                  </div>
                ))}

                {/* MCP Permission Dialog - Fixed position to prevent layout shift */}
                {mcpPermissionDialog.isOpen && (
                  <div className="sticky bottom-4 z-30 mx-auto max-w-2xl">
                    <div className="bg-[var(--bg-card)] border border-amber-500/50 rounded-xl p-4 shadow-2xl backdrop-blur-sm">
                      <div className="flex items-center gap-2 mb-3">
                        <span className="text-lg">🔧</span>
                        <div className="w-2 h-2 bg-amber-500 rounded-full animate-pulse"></div>
                        <span className="text-sm text-amber-500 font-medium">Permission Required</span>
                      </div>
                      <p className="text-gray-300 text-sm mb-3">
                        DataVision wants to use the following tools:
                      </p>
                      <div className="space-y-2 mb-4 max-h-40 overflow-y-auto">
                        {mcpPermissionDialog.pendingTools.map((tool) => (
                          <div
                            key={tool.name}
                            className="flex items-center gap-3 px-3 py-2 bg-[var(--bg-hover)]/50 border border-[var(--border-color)] rounded-lg"
                          >
                            <span className="text-lg">{tool.icon}</span>
                            <div className="flex-1 min-w-0">
                              <span className="text-sm font-medium text-gray-200 truncate block">{tool.name}</span>
                              <p className="text-xs text-gray-500 truncate">{tool.description}</p>
                            </div>
                          </div>
                        ))}
                      </div>
                      <div className="flex gap-3 justify-end">
                        <button
                          onClick={() => mcpPermissionDialog.onDeny?.()}
                          className="px-5 py-2.5 text-sm font-medium text-gray-300 hover:text-white bg-[var(--bg-hover)] hover:bg-[var(--bg-secondary)] rounded-lg transition-colors border border-[var(--border-color)]"
                        >
                          Deny
                        </button>
                        <button
                          onClick={() => mcpPermissionDialog.onAllow?.()}
                          className="px-5 py-2.5 text-sm font-medium text-white bg-green-600 hover:bg-green-700 rounded-lg transition-colors shadow-lg"
                        >
                          Allow
                        </button>
                      </div>
                    </div>
                  </div>
                )}

                {isLoading && (
                  <div className="space-y-3">
                    {/* MCP Tool Execution Animation - Claude Style */}
                    {mcpExecutionStatus.isRunning && mcpExecutionStatus.currentTools.length > 0 && (
                      <div className="flex items-start gap-3 w-full max-w-full animate-fadeIn">
                        <div className="w-8 h-8 flex-shrink-0 mt-1 flex items-center justify-center">
                          <div className="animate-spin text-xl">⚙️</div>
                        </div>
                        <div className="flex-1 bg-[var(--bg-card)]/80 backdrop-blur-sm border border-accent-primary/30 rounded-xl p-4">
                          <div className="flex items-center gap-2 mb-3">
                            <div className="w-2 h-2 bg-accent-primary rounded-full animate-pulse"></div>
                            <span className="text-sm text-accent-primary font-medium">Running MCP Tools</span>
                          </div>
                          <div className="space-y-2">
                            {mcpExecutionStatus.currentTools.map((tool) => (
                              <div
                                key={tool.name}
                                className={`flex items-center gap-3 px-3 py-2 rounded-lg transition-all duration-300 ${tool.status === 'running'
                                  ? 'bg-accent-primary/20 border border-accent-primary/40'
                                  : tool.status === 'success'
                                    ? 'bg-green-500/20 border border-green-500/40'
                                    : 'bg-[var(--bg-hover)]/50 border border-[var(--border-color)]'
                                  }`}
                              >
                                <span className={`text-lg ${tool.status === 'running' ? 'animate-bounce' : ''}`}>
                                  {tool.status === 'success' ? '✓' : tool.icon}
                                </span>
                                <span className={`text-sm ${tool.status === 'running' ? 'text-accent-primary' :
                                  tool.status === 'success' ? 'text-green-400' : 'text-gray-400'
                                  }`}>
                                  {tool.name}
                                </span>
                                {tool.status === 'running' && (
                                  <div className="ml-auto flex items-center gap-1">
                                    <div className="w-1 h-1 bg-accent-primary rounded-full animate-ping"></div>
                                    <span className="text-xs text-accent-primary">Running...</span>
                                  </div>
                                )}
                                {tool.status === 'success' && (
                                  <span className="ml-auto text-xs text-green-400">Done</span>
                                )}
                              </div>
                            ))}
                          </div>
                        </div>
                      </div>
                    )}

                    {/* Regular Typing Indicator with mode-specific text */}
                    <TypingIndicator mode={mode} isDark={isDark} />
                  </div>
                )}
              </div>
            )}
            <div ref={messagesEndRef} />
          </div>
        </div>

        {/* ========== GLOBAL DROPDOWNS - Both appear CENTERED below search box ========== */}

        {/* Global MCP Dropdown - CSS transitions for performance */}
        {mcpDropdownOpen && (
          <div
            ref={mcpMenuRef}
            className={`fixed z-50 left-4 md:left-[calc(50%-384px)] w-80 max-w-[calc(100vw-2rem)] bg-[var(--bg-card)] border border-[var(--border-color)] rounded-xl shadow-2xl overflow-hidden transition-all duration-200 ${messages.length === 0 ? 'top-1/2 mt-16' : 'bottom-28'}`}
          >
            <div className="p-3 border-b border-[var(--border-color)] flex items-center justify-between bg-[var(--bg-secondary)]/50">
              <p className="text-xs font-semibold text-gray-400 uppercase tracking-wide">MCP Servers</p>
              <span className="text-xs text-green-400 font-medium">{Object.values(enabledMcps).filter(Boolean).length}/{mcpServers.length} active</span>
            </div>
            <div className="max-h-64 overflow-y-auto">
              {mcpServers.map((mcp) => (
                <button
                  key={mcp.id}
                  onClick={() => setEnabledMcps(prev => ({ ...prev, [mcp.id]: !prev[mcp.id] }))}
                  className="flex items-center gap-3 w-full p-3 hover:bg-[var(--bg-hover)] transition-colors"
                >
                  <span className="text-lg">{mcp.icon}</span>
                  <div className="flex-1 text-left">
                    <p className={`text-sm font-medium ${enabledMcps[mcp.id] ? 'text-gray-200' : 'text-gray-500'}`}>{mcp.name}</p>
                    <p className="text-xs text-gray-500 line-clamp-1">{mcp.description}</p>
                  </div>
                  <div className={`w-9 h-5 rounded-full transition-all duration-200 ${enabledMcps[mcp.id] ? 'bg-green-500' : 'bg-gray-700'} flex items-center`}>
                    <div className={`w-4 h-4 rounded-full bg-white shadow-sm transition-transform duration-200 ${enabledMcps[mcp.id] ? 'translate-x-4' : 'translate-x-0.5'}`} />
                  </div>
                </button>
              ))}
            </div>
          </div>
        )}

        {/* Global Mode Dropdown - CSS transitions for performance */}
        {modeDropdownOpen && (
          <div
            ref={modeMenuRef}
            className={`fixed z-50 right-4 md:right-[calc(50%-384px)] w-80 max-w-[calc(100vw-2rem)] bg-[var(--bg-card)] border border-[var(--border-color)] rounded-xl shadow-2xl overflow-hidden max-h-[60vh] overflow-y-auto transition-all duration-200 ${messages.length === 0 ? 'top-1/2 mt-16' : 'bottom-28'}`}
          >
            {/* RAG Modes */}
            <div className="p-2 border-b border-[var(--border-color)] bg-[var(--bg-secondary)]/50">
              <span className="text-xs font-semibold text-gray-400 uppercase tracking-wider px-2">📊 Data Modes</span>
            </div>
            {modes.filter(m => !m.isAI).map((m) => (
              <button
                key={m.id}
                onClick={() => { setMode(m.id); setModeDropdownOpen(false); }}
                className={`flex items-center gap-3 w-full p-3 hover:bg-[var(--bg-hover)] transition-colors ${mode === m.id ? 'bg-[var(--bg-hover)]' : ''}`}
              >
                <div className="flex-1 text-left">
                  <div className="flex items-center gap-2">
                    <p className={`text-sm font-medium ${mode === m.id ? 'text-white' : 'text-gray-200'}`}>{m.label}</p>
                    {m.badge && (
                      <span className="px-1.5 py-0.5 text-[10px] font-medium bg-green-500/20 text-green-400 rounded">
                        {m.badge}
                      </span>
                    )}
                  </div>
                  <p className="text-xs text-gray-500">{m.description}</p>
                </div>
                {mode === m.id && <Check className="w-4 h-4 text-green-400" />}
              </button>
            ))}

            {/* AI Models Divider */}
            <div className="p-2 border-t border-b border-[var(--border-color)] bg-[var(--bg-secondary)]/50">
              <span className="text-xs font-semibold text-purple-400 uppercase tracking-wider px-2">🤖 AI Models</span>
            </div>
            {modes.filter(m => m.isAI).map((m: any) => (
              <button
                key={m.id}
                onClick={() => { setMode(m.id); setModeDropdownOpen(false); }}
                className={`flex items-center gap-3 w-full p-3 hover:bg-[var(--bg-hover)] transition-colors ${mode === m.id ? 'bg-[var(--bg-hover)]' : ''}`}
              >
                {m.logo && (
                  <img
                    src={m.logo}
                    alt={m.label}
                    className="w-6 h-6 rounded object-contain bg-white/10 p-0.5"
                    onError={(e) => { e.currentTarget.style.display = 'none'; }}
                  />
                )}
                <div className="flex-1 text-left">
                  <div className="flex items-center gap-2">
                    <p className={`text-sm font-medium ${mode === m.id ? 'text-white' : 'text-gray-200'}`}>{m.label}</p>
                    {m.badge && (
                      <span className={`px-1.5 py-0.5 text-[10px] font-medium rounded ${m.badge === 'New' ? 'bg-blue-500/20 text-blue-400' : 'bg-green-500/20 text-green-400'}`}>
                        {m.badge}
                      </span>
                    )}
                  </div>
                  <p className="text-xs text-gray-500">{m.description}</p>
                </div>
                {mode === m.id && <Check className="w-4 h-4 text-green-400" />}
              </button>
            ))}
          </div>
        )}

        {/* Global Hidden File Input - Always in DOM for WelcomeScreen and bottom input */}
        <input
          ref={fileInputRef}
          type="file"
          accept="image/*,.pdf,.xlsx,.xls,.csv,.json,.txt,.doc,.docx,.ppt,.pptx"
          onChange={handleImageSelect}
          className="hidden"
          multiple
        />

        {/* Claude-style Input Bar - Only show when there are messages */}
        {/* Floating Input Area - Fixed at Bottom Center (hidden on empty state) */}
        {
          messages.length > 0 && (
            <div className="absolute inset-x-0 bottom-0 bg-gradient-to-t from-dark-bg via-dark-bg to-transparent pt-10 pb-6 px-4 z-20">
              <div className="max-w-3xl mx-auto">
                {/* Attached Files Preview */}
                {attachedFiles.length > 0 && (
                  <div className="mb-3 flex flex-wrap gap-2">
                    {attachedFiles.map((file, index) => (
                      <div key={index} className="flex items-center gap-2 px-3 py-2 bg-dark-card border border-dark-border rounded-lg text-sm">
                        <FileText className="w-4 h-4 text-green-400" />
                        <span className="text-gray-300 truncate max-w-[200px]">{file.name}</span>
                        <button
                          onClick={() => removeAttachedFile(index)} className="text-gray-500 hover:text-red-400">
                          <X className="w-4 h-4" />
                        </button>
                      </div>
                    ))}
                  </div>
                )}

                {/* Image Preview - Shows separately from attached files */}
                {selectedImage && imagePreviewUrl && (
                  <div className="mb-3 flex flex-wrap gap-2">
                    <div className="relative group inline-block">
                      {/* ChatGPT-style Image Preview Thumbnail */}
                      <div className="relative w-32 h-24 rounded-xl overflow-hidden border-2 border-indigo-500/50 shadow-lg bg-dark-card transition-all duration-200 hover:border-indigo-400">
                        <img
                          src={imagePreviewUrl}
                          alt="Preview"
                          className="w-full h-full object-cover"
                        />
                        {/* Overlay with actions */}
                        <div className="absolute inset-0 bg-black/0 group-hover:bg-black/30 transition-all duration-200 flex items-center justify-center">
                          {/* Edit/View button - top left */}
                          <button
                            className="absolute top-1 left-1 p-1 bg-black/50 hover:bg-black/70 rounded-md opacity-0 group-hover:opacity-100 transition-opacity"
                            title="View image"
                          >
                            <Pencil className="w-3 h-3 text-white" />
                          </button>
                        </div>
                        {/* Dismiss button - top right */}
                        <button
                          onClick={() => {
                            setSelectedImage(null);
                            setImagePreviewUrl(null);
                          }}
                          className="absolute top-1 right-1 p-1 bg-gray-800/80 hover:bg-red-600 rounded-md text-white transition-colors"
                          title="Remove image"
                        >
                          <X className="w-3 h-3" />
                        </button>
                      </div>
                    </div>
                  </div>
                )}

                {/* Input Bar Container - Premium ChatGPT Style */}
                <div className="glass-input w-full flex items-end gap-2 sm:gap-3 p-3 sm:p-4 rounded-2xl transition-all">

                  {/* Left side buttons - Hidden on mobile, shown on desktop */}
                  <div className="hidden sm:flex items-center gap-2">
                    {/* MCP Servers Toggle - Uses unified dropdown below */}
                    <button
                      onClick={() => setMcpDropdownOpen(!mcpDropdownOpen)}
                      className="p-2 hover:bg-dark-hover rounded-lg transition-colors text-gray-400 hover:text-gray-200 relative"
                      title="MCP Servers"
                    >
                      <Database className="w-5 h-5" />
                      <span className={`absolute -top-0.5 -right-0.5 w-2 h-2 rounded-full ${Object.values(enabledMcps).every(Boolean) ? 'bg-green-500' : 'bg-yellow-500'}`} />
                    </button>

                    {/* File Upload */}
                    <button
                      onClick={() => fileInputRef.current?.click()}
                      className="p-2 hover:bg-dark-hover rounded-lg transition-colors text-gray-400 hover:text-gray-200"
                      title="Attach File"
                    >
                      <Paperclip className="w-5 h-5" />
                    </button>
                  </div>

                  {/* Mobile: Plus button with menu */}
                  <div className="relative sm:hidden">
                    {plusMenuOpen && (
                      <>
                        <div className="fixed inset-0 z-40" onClick={() => setPlusMenuOpen(false)} />
                        <div className="absolute bottom-full mb-2 left-0 w-64 bg-dark-card border border-dark-border rounded-xl shadow-xl overflow-hidden z-50">
                          {/* Upload Files */}
                          <button
                            onClick={() => {
                              fileInputRef.current?.click();
                              setPlusMenuOpen(false);
                            }}
                            className="flex items-center gap-3 w-full p-4 hover:bg-dark-hover transition-colors text-left"
                          >
                            <div className="p-2 bg-blue-500/10 rounded-lg">
                              <Paperclip className="w-5 h-5 text-blue-400" />
                            </div>
                            <div className="flex-1">
                              <p className="text-sm font-medium text-gray-200">Add photos & files</p>
                              <p className="text-xs text-gray-500">Upload documents or images</p>
                            </div>
                          </button>

                          {/* MCPs Submenu */}
                          <button
                            onClick={() => {
                              setMcpDropdownOpen(true);
                              setPlusMenuOpen(false);
                            }}
                            className="flex items-center gap-3 w-full p-4 hover:bg-dark-hover transition-colors text-left border-t border-dark-border"
                          >
                            <div className="p-2 bg-green-500/10 rounded-lg">
                              <Database className="w-5 h-5 text-green-400" />
                            </div>
                            <div className="flex-1">
                              <p className="text-sm font-medium text-gray-200">MCP Servers</p>
                              <p className="text-xs text-gray-500">{Object.values(enabledMcps).filter(Boolean).length}/{mcpServers.length} active</p>
                            </div>
                            <ChevronDown className="w-4 h-4 text-gray-500 -rotate-90" />
                          </button>

                          {/* Modes Submenu */}
                          <button
                            onClick={() => {
                              setModeDropdownOpen(true);
                              setPlusMenuOpen(false);
                            }}
                            className="flex items-center gap-3 w-full p-4 hover:bg-dark-hover transition-colors text-left border-t border-dark-border"
                          >
                            <div className="p-2 bg-purple-500/10 rounded-lg">
                              <Sparkles className="w-5 h-5 text-purple-400" />
                            </div>
                            <div className="flex-1">
                              <p className="text-sm font-medium text-gray-200">AI Modes</p>
                              <p className="text-xs text-gray-500">Current: {currentMode.label}</p>
                            </div>
                            <ChevronDown className="w-4 h-4 text-gray-500 -rotate-90" />
                          </button>
                        </div>
                      </>
                    )}
                    <button
                      onClick={() => setPlusMenuOpen(!plusMenuOpen)}
                      className="p-3 hover:bg-dark-hover rounded-xl transition-colors text-gray-400 hover:text-gray-200"
                      title="More options"
                    >
                      <Plus className="w-6 h-6" />
                    </button>
                  </div>



                  {/* Text Input - Large and prominent */}
                  <textarea
                    ref={textareaRef}
                    value={input}
                    onChange={(e) => setInput(e.target.value)}
                    onKeyDown={(e) => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); handleSend(); } }}
                    onPaste={handlePaste}
                    placeholder="Ask anything..."
                    rows={1}
                    className="flex-1 min-w-0 bg-transparent border-none outline-none resize-none text-base text-gray-100 placeholder-gray-400 py-3 px-3 sm:py-2 sm:px-2 max-h-32 min-h-[44px]"
                    style={{ lineHeight: '1.5' }}
                  />

                  {/* Hidden file input */}

                  {/* Right side: Voice + Mode + Send */}
                  <div className="flex items-center gap-2">
                    {/* Voice Input */}
                    <button
                      onClick={handleVoiceInput}
                      className={`p-3 sm:p-2 rounded-xl sm:rounded-lg transition-colors ${isRecording ? 'bg-red-500 text-white animate-pulse' : 'hover:bg-dark-hover text-gray-400 hover:text-gray-200'}`}
                      title="Voice Input"
                    >
                      <Mic className="w-6 h-6 sm:w-5 sm:h-5" />
                    </button>

                    {/* Mode Selector - Works on mobile and desktop */}
                    <div className="flex items-center gap-1.5 ml-2">
                      <button
                        onClick={() => setModeDropdownOpen(true)}
                        className="flex items-center gap-1.5 px-3 py-2 bg-[var(--bg-secondary)] hover:bg-dark-hover rounded-lg transition-colors text-sm font-medium whitespace-nowrap"
                        style={{ color: 'var(--text-primary)' }}
                      >
                        {currentMode.label}
                        <ChevronDown className="w-4 h-4 text-gray-500" />
                      </button>
                    </div>

                    {/* Send/Stop Button - Transforms like ChatGPT */}
                    {isLoading ? (
                      <button
                        onClick={handleStopGeneration}
                        className="p-3 sm:p-2.5 bg-gray-600 hover:bg-red-600 text-white rounded-xl transition-all duration-200"
                        title="Stop generating"
                      >
                        <Square className="w-5 h-5 sm:w-4 sm:h-4 fill-current" />
                      </button>
                    ) : (
                      <button
                        onClick={handleSend}
                        disabled={!input.trim() && !selectedImage && attachedFiles.length === 0}
                        className="chat-send-btn touch-target"
                      >
                        <Send className="w-5 h-5 text-gray-900" />
                      </button>
                    )}
                  </div>
                </div>

                {/* Disclaimer */}
                <p className="text-center text-xs text-gray-500 mt-3">
                  DataVision can make mistakes. Please double-check responses.
                </p>
              </div>
            </div >
          )
        }
      </div >

      {/* Confirm Modal for Delete Operations */}
      <ConfirmModal />
    </div >
  );
};

export default AnalystChat;
