import { useState, useEffect, lazy, Suspense, useRef } from 'react';
import { useNavigate } from 'react-router-dom';
import { Terminal, Settings } from 'lucide-react';
import { useOptimizationWebSocket } from '../hooks/useWebSocket';
import { useNotifications, formatOptimizationNotification } from '../hooks/useNotifications';
import { apiClient } from '../api/client';
import { useStudy } from '../context/StudyContext';
import { useClaudeTerminal } from '../context/ClaudeTerminalContext';
import { Card } from '../components/common/Card';
import { ControlPanel } from '../components/dashboard/ControlPanel';
import { NotificationSettings } from '../components/NotificationSettings';
import { ConfigEditor } from '../components/ConfigEditor';
import { ParetoPlot } from '../components/ParetoPlot';
import { ParallelCoordinatesPlot } from '../components/ParallelCoordinatesPlot';
import { ParameterImportanceChart } from '../components/ParameterImportanceChart';
import { ConvergencePlot } from '../components/ConvergencePlot';
import { StudyReportViewer } from '../components/StudyReportViewer';
import { ConsoleOutput } from '../components/ConsoleOutput';
import { ZernikeButton } from '../components/ZernikeViewer';
import { ExpandableChart } from '../components/ExpandableChart';
import { CurrentTrialPanel, OptimizerStatePanel } from '../components/tracker';
import type { Trial } from '../types';

// Lazy load Plotly components for better initial load performance
const PlotlyParallelCoordinates = lazy(() => import('../components/plotly/PlotlyParallelCoordinates').then(m => ({ default: m.PlotlyParallelCoordinates })));
const PlotlyParetoPlot = lazy(() => import('../components/plotly/PlotlyParetoPlot').then(m => ({ default: m.PlotlyParetoPlot })));
const PlotlyConvergencePlot = lazy(() => import('../components/plotly/PlotlyConvergencePlot').then(m => ({ default: m.PlotlyConvergencePlot })));
const PlotlyParameterImportance = lazy(() => import('../components/plotly/PlotlyParameterImportance').then(m => ({ default: m.PlotlyParameterImportance })));

// Loading placeholder for lazy components
const ChartLoading = () => (
  <div className="flex items-center justify-center h-64 text-dark-400">
    <div className="animate-pulse">Loading chart...</div>
  </div>
);

export default function Dashboard() {
  const navigate = useNavigate();
  const { selectedStudy, refreshStudies, isInitialized } = useStudy();
  const selectedStudyId = selectedStudy?.id || null;

  // All hooks must be declared before any conditional returns
  const [allTrials, setAllTrials] = useState<Trial[]>([]);
  const [displayedTrials, setDisplayedTrials] = useState<Trial[]>([]);
  const [bestValue, setBestValue] = useState<number>(Infinity);
  const [prunedCount, setPrunedCount] = useState<number>(0);
  const [alerts, setAlerts] = useState<Array<{ id: number; type: 'success' | 'warning'; message: string }>>([]);
  const [alertIdCounter, setAlertIdCounter] = useState(0);
  const [expandedTrials, setExpandedTrials] = useState<Set<number>>(new Set());
  const [sortBy, setSortBy] = useState<'performance' | 'chronological'>('performance');
  const [trialsPage, setTrialsPage] = useState(0);
  const trialsPerPage = 50; // Limit trials per page for performance
  const [showOnlyFEA, setShowOnlyFEA] = useState(false); // Filter to show only trials with OP2 results
  const [zernikeAvailableTrials, setZernikeAvailableTrials] = useState<Set<number>>(new Set()); // Trials with OP2 files

  // Parameter Space axis selection (reserved for future use)
  const [_paramXIndex, _setParamXIndex] = useState(0);
  const [_paramYIndex, _setParamYIndex] = useState(1);

  // Protocol 13: New state for metadata and Pareto front
  const [studyMetadata, setStudyMetadata] = useState<any>(null);
  const [paretoFront, setParetoFront] = useState<any[]>([]);
  const [allTrialsRaw, setAllTrialsRaw] = useState<any[]>([]); // All trials for parallel coordinates

  // Chart library toggle: 'recharts' (faster) or 'plotly' (more interactive but slower)
  const [chartLibrary, setChartLibrary] = useState<'plotly' | 'recharts'>('recharts');

  // Process status for tracker panels
  const [isRunning, setIsRunning] = useState(false);
  const [lastTrialTime, _setLastTrialTime] = useState<number | undefined>(undefined);

  // Config editor modal
  const [showConfigEditor, setShowConfigEditor] = useState(false);

  // Claude terminal from global context
  const { isOpen: claudeTerminalOpen, setIsOpen: setClaudeTerminalOpen, isConnected: claudeConnected } = useClaudeTerminal();

  // Desktop notifications
  const { showNotification } = useNotifications();
  const previousBestRef = useRef<number>(Infinity);

  // Redirect to home if no study selected (but only after initialization completes)
  useEffect(() => {
    if (isInitialized && !selectedStudy) {
      navigate('/');
    }
  }, [selectedStudy, navigate, isInitialized]);

  const showAlert = (type: 'success' | 'warning', message: string) => {
    const id = alertIdCounter;
    setAlertIdCounter(prev => prev + 1);
    setAlerts(prev => [...prev, { id, type, message }]);
    setTimeout(() => {
      setAlerts(prev => prev.filter(a => a.id !== id));
    }, 5000);
  };

  // WebSocket connection
  const { connectionStatus: _connectionStatus } = useOptimizationWebSocket({
    studyId: selectedStudyId,
    onMessage: (msg) => {
      if (msg.type === 'trial_completed') {
        const trial = msg.data as Trial;
        // Avoid duplicates by checking if trial already exists
        setAllTrials(prev => {
          const exists = prev.some(t => t.trial_number === trial.trial_number);
          if (exists) return prev;
          return [...prev, trial];
        });
        if (trial.objective !== null && trial.objective !== undefined && trial.objective < bestValue) {
          const improvement = previousBestRef.current !== Infinity
            ? ((previousBestRef.current - trial.objective) / Math.abs(previousBestRef.current)) * 100
            : 0;

          setBestValue(trial.objective);
          previousBestRef.current = trial.objective;
          showAlert('success', `New best: ${trial.objective.toFixed(4)} (Trial #${trial.trial_number})`);

          // Desktop notification for new best
          showNotification(formatOptimizationNotification({
            type: 'new_best',
            studyName: selectedStudy?.name || selectedStudyId || 'Study',
            message: `Best value: ${trial.objective.toExponential(4)}`,
            value: trial.objective,
            improvement
          }));
        }
      } else if (msg.type === 'trial_pruned') {
        setPrunedCount(prev => prev + 1);
        showAlert('warning', `Trial pruned: ${msg.data.pruning_cause}`);
      }
    }
  });

  // Load initial trial history when study changes
  // PERFORMANCE: Use limit to avoid loading thousands of trials at once
  const MAX_TRIALS_LOAD = 300;

  useEffect(() => {
    if (selectedStudyId) {
      setAllTrials([]);
      setBestValue(Infinity);
      setPrunedCount(0);
      setExpandedTrials(new Set());

      // Single history fetch with limit - used for both trial list and charts
      // This replaces the duplicate fetch calls
      fetch(`/api/optimization/studies/${selectedStudyId}/history?limit=${MAX_TRIALS_LOAD}`)
        .then(res => res.json())
        .then(data => {
          // Set trials for the trial list
          const validTrials = data.trials.filter((t: any) => t.objective !== null && t.objective !== undefined);
          setAllTrials(validTrials);
          if (validTrials.length > 0) {
            const minObj = Math.min(...validTrials.map((t: any) => t.objective));
            setBestValue(minObj);
          }

          // Transform for charts (parallel coordinates, etc.)
          const trialsData = data.trials.map((t: any) => {
            let values: number[] = [];
            if (t.objectives && Array.isArray(t.objectives)) {
              values = t.objectives;
            } else if (t.objective !== null && t.objective !== undefined) {
              values = [t.objective];
            }
            return {
              trial_number: t.trial_number,
              values,
              params: t.design_variables || {},
              user_attrs: t.user_attrs || {},
              constraint_satisfied: t.constraint_satisfied !== false,
              source: t.source || t.user_attrs?.source || 'FEA'
            };
          });
          setAllTrialsRaw(trialsData);
        })
        .catch(console.error);

      apiClient.getStudyPruning(selectedStudyId)
        .then(data => {
          setPrunedCount(data.count ?? data.pruned_trials?.length ?? 0);
        })
        .catch(console.error);

      // Fetch metadata (small payload)
      fetch(`/api/optimization/studies/${selectedStudyId}/metadata`)
        .then(res => res.json())
        .then(data => setStudyMetadata(data))
        .catch(err => console.error('Failed to load metadata:', err));

      // Fetch Pareto front (usually small)
      fetch(`/api/optimization/studies/${selectedStudyId}/pareto-front`)
        .then(res => res.json())
        .then(paretoData => {
          if (paretoData.is_multi_objective && paretoData.pareto_front) {
            setParetoFront(paretoData.pareto_front);
          } else {
            setParetoFront([]);
          }
        })
        .catch(err => console.error('Failed to load Pareto front:', err));

      // Check process status
      apiClient.getProcessStatus(selectedStudyId)
        .then(data => {
          setIsRunning(data.is_running);
        })
        .catch(err => console.error('Failed to load process status:', err));

      // Fetch available Zernike trials (for mirror/zernike studies)
      if (selectedStudyId.includes('mirror') || selectedStudyId.includes('zernike')) {
        fetch(`/api/optimization/studies/${selectedStudyId}/zernike-available`)
          .then(res => res.json())
          .then(data => {
            setZernikeAvailableTrials(new Set(data.available_trials || []));
          })
          .catch(err => console.error('Failed to load Zernike available trials:', err));
      } else {
        setZernikeAvailableTrials(new Set());
      }
    }
  }, [selectedStudyId]);

  // Poll process status periodically
  useEffect(() => {
    if (!selectedStudyId) return;

    const pollStatus = setInterval(() => {
      apiClient.getProcessStatus(selectedStudyId)
        .then(data => {
          setIsRunning(data.is_running);
        })
        .catch(() => {});
    }, 5000);

    return () => clearInterval(pollStatus);
  }, [selectedStudyId]);

  // Sort and filter trials based on selected options
  useEffect(() => {
    let filtered = [...allTrials];

    // Filter to trials with OP2 results (for Zernike analysis)
    if (showOnlyFEA && zernikeAvailableTrials.size > 0) {
      filtered = filtered.filter(t => zernikeAvailableTrials.has(t.trial_number));
    }

    // Sort
    if (sortBy === 'performance') {
      // Sort by objective (best first)
      filtered.sort((a, b) => {
        const aObj = a.objective ?? Infinity;
        const bObj = b.objective ?? Infinity;
        return aObj - bObj;
      });
    } else {
      // Chronological (newest first)
      filtered.sort((a, b) => b.trial_number - a.trial_number);
    }
    setDisplayedTrials(filtered);
    setTrialsPage(0); // Reset pagination when filter changes
  }, [allTrials, sortBy, showOnlyFEA, zernikeAvailableTrials]);

  // Auto-refresh polling for trial history
  // PERFORMANCE: Use limit and longer interval for large studies
  useEffect(() => {
    if (!selectedStudyId) return;

    const refreshInterval = setInterval(() => {
      // Only fetch latest trials, not the entire history
      fetch(`/api/optimization/studies/${selectedStudyId}/history?limit=${MAX_TRIALS_LOAD}`)
        .then(res => res.json())
        .then(data => {
          const validTrials = data.trials.filter((t: any) => t.objective !== null && t.objective !== undefined);
          setAllTrials(validTrials);
          if (validTrials.length > 0) {
            const minObj = Math.min(...validTrials.map((t: any) => t.objective));
            setBestValue(minObj);
          }
          // Also update chart data
          const trialsData = data.trials.map((t: any) => {
            let values: number[] = [];
            if (t.objectives && Array.isArray(t.objectives)) {
              values = t.objectives;
            } else if (t.objective !== null && t.objective !== undefined) {
              values = [t.objective];
            }
            return {
              trial_number: t.trial_number,
              values,
              params: t.design_variables || {},
              user_attrs: t.user_attrs || {},
              constraint_satisfied: t.constraint_satisfied !== false,
              source: t.source || t.user_attrs?.source || 'FEA'
            };
          });
          setAllTrialsRaw(trialsData);
        })
        .catch(err => console.error('Auto-refresh failed:', err));
    }, 15000); // Poll every 15 seconds for performance

    return () => clearInterval(refreshInterval);
  }, [selectedStudyId]);

  // Show loading state while initializing (restoring study from localStorage)
  if (!isInitialized) {
    return (
      <div className="flex items-center justify-center min-h-screen">
        <div className="text-center">
          <div className="animate-spin w-8 h-8 border-2 border-primary-500 border-t-transparent rounded-full mx-auto mb-4"></div>
          <p className="text-dark-400">Loading study...</p>
        </div>
      </div>
    );
  }

  // Note: Chart data sampling is handled by individual chart components

  // Calculate average objective
  const validObjectives = allTrials.filter(t => t.objective !== null && t.objective !== undefined).map(t => t.objective);
  const avgObjective = validObjectives.length > 0
    ? validObjectives.reduce((sum, obj) => sum + obj, 0) / validObjectives.length
    : 0;

  // Get parameter names
  const paramNames = allTrials.length > 0 && allTrials[0].design_variables
    ? Object.keys(allTrials[0].design_variables)
    : [];

  // Toggle trial expansion
  const toggleTrialExpansion = (trialNumber: number) => {
    setExpandedTrials(prev => {
      const newSet = new Set(prev);
      if (newSet.has(trialNumber)) {
        newSet.delete(trialNumber);
      } else {
        newSet.add(trialNumber);
      }
      return newSet;
    });
  };

  // Export functions
  const exportJSON = () => {
    if (allTrials.length === 0) return;
    const data = JSON.stringify(allTrials, null, 2);
    const blob = new Blob([data], { type: 'application/json' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `${selectedStudyId}_trials.json`;
    a.click();
    URL.revokeObjectURL(url);
    showAlert('success', 'JSON exported successfully!');
  };

  const exportCSV = () => {
    if (allTrials.length === 0) return;
    const headers = ['trial_number', 'objective', ...paramNames].join(',');
    const rows = allTrials.map(t => [
      t.trial_number,
      t.objective,
      ...paramNames.map(k => t.design_variables?.[k] ?? '')
    ].join(','));
    const csv = [headers, ...rows].join('\n');
    const blob = new Blob([csv], { type: 'text/csv' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `${selectedStudyId}_trials.csv`;
    a.click();
    URL.revokeObjectURL(url);
    showAlert('success', 'CSV exported successfully!');
  };

  return (
    <div className="w-full">
      {/* Alerts */}
      <div className="fixed top-4 right-4 z-50 space-y-2">
        {alerts.map(alert => (
          <div
            key={alert.id}
            className={`px-4 py-3 rounded-lg shadow-lg transition-all duration-300 ${
              alert.type === 'success'
                ? 'bg-green-900 border-l-4 border-green-400 text-green-100'
                : 'bg-yellow-900 border-l-4 border-yellow-400 text-yellow-100'
            }`}
          >
            {alert.message}
          </div>
        ))}
      </div>

      {/* Header */}
      <header className="mb-8 flex items-center justify-between border-b border-dark-600 pb-4">
        <div>
          <h1 className="text-3xl font-bold text-primary-400">Live Dashboard</h1>
          <p className="text-dark-300 mt-1">Real-time optimization monitoring</p>
        </div>
        <div className="flex gap-2">
          {/* Config Editor Button */}
          {selectedStudyId && (
            <button
              onClick={() => setShowConfigEditor(true)}
              className="flex items-center gap-1.5 px-2 py-1 rounded text-xs bg-dark-700 text-dark-400 hover:bg-dark-600 hover:text-white transition-colors"
              title="Edit study configuration"
            >
              <Settings className="w-4 h-4" />
              <span className="hidden sm:inline">Config</span>
            </button>
          )}

          {/* Notification Toggle */}
          <NotificationSettings compact />

          {/* Claude Code Terminal Toggle Button */}
          <button
            onClick={() => setClaudeTerminalOpen(!claudeTerminalOpen)}
            className={`flex items-center gap-2 px-4 py-2 rounded-lg transition-colors ${
              claudeTerminalOpen
                ? 'bg-primary-600 text-white'
                : claudeConnected
                  ? 'bg-green-700 text-white border border-green-600'
                  : 'bg-dark-700 text-dark-200 hover:bg-dark-600 hover:text-white border border-dark-600'
            }`}
            title={claudeConnected ? 'Claude Terminal (Connected)' : 'Open Claude Code terminal'}
          >
            <Terminal className="w-4 h-4" />
            <span className="hidden sm:inline">Claude Code</span>
            {claudeConnected && !claudeTerminalOpen && (
              <span className="w-2 h-2 bg-green-400 rounded-full animate-pulse" />
            )}
          </button>
          {selectedStudyId && (
            <StudyReportViewer studyId={selectedStudyId} />
          )}
          <button
            onClick={async () => {
              if (!selectedStudyId) return;
              try {
                // Launch Optuna dashboard via API, then open the returned URL
                const result = await apiClient.launchOptunaDashboard(selectedStudyId);
                window.open(result.url || 'http://localhost:8081', '_blank');
              } catch (err) {
                // If launch fails (maybe already running), try opening directly
                console.warn('Failed to launch dashboard:', err);
                window.open('http://localhost:8081', '_blank');
              }
            }}
            className="btn-secondary"
            title="Launch Optuna Dashboard for this study"
            disabled={!selectedStudyId}
          >
            Optuna Dashboard
          </button>
          <button onClick={exportJSON} className="btn-secondary" disabled={allTrials.length === 0}>
            Export JSON
          </button>
          <button onClick={exportCSV} className="btn-secondary" disabled={allTrials.length === 0}>
            Export CSV
          </button>
          {/* Chart library toggle */}
          <div className="flex rounded-lg overflow-hidden border border-dark-500 ml-2">
            <button
              onClick={() => setChartLibrary('plotly')}
              className={`px-3 py-1.5 text-sm transition-colors ${
                chartLibrary === 'plotly'
                  ? 'bg-primary-500 text-white'
                  : 'bg-dark-600 text-dark-200 hover:bg-dark-500'
              }`}
              title="Interactive Plotly charts with zoom, pan, and export"
            >
              Plotly
            </button>
            <button
              onClick={() => setChartLibrary('recharts')}
              className={`px-3 py-1.5 text-sm transition-colors ${
                chartLibrary === 'recharts'
                  ? 'bg-primary-500 text-white'
                  : 'bg-dark-600 text-dark-200 hover:bg-dark-500'
              }`}
              title="Simple Recharts visualization"
            >
              Simple
            </button>
          </div>
        </div>
      </header>

      {/* Control Panel - Full Width on Top */}
      <div className="mb-6">
        <ControlPanel onStatusChange={refreshStudies} horizontal />
      </div>

      {/* Tracker Panels - Current Trial and Optimizer State */}
      <div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6">
        <CurrentTrialPanel
          studyId={selectedStudyId}
          totalTrials={selectedStudy?.progress.total || 100}
          completedTrials={allTrials.length}
          isRunning={isRunning}
          lastTrialTime={lastTrialTime}
        />
        <OptimizerStatePanel
          sampler={studyMetadata?.sampler}
          nTrials={selectedStudy?.progress.total || 100}
          completedTrials={allTrials.length}
          feaTrials={allTrialsRaw.filter(t => t.source === 'FEA').length}
          nnTrials={allTrialsRaw.filter(t => t.source === 'NN').length}
          objectives={studyMetadata?.objectives || []}
          isMultiObjective={(studyMetadata?.objectives?.length || 0) > 1}
          paretoSize={paretoFront.length}
        />
      </div>

      {/* Main Layout: Charts (Claude Terminal is now global/floating) */}
      <div className="grid gap-4 grid-cols-1">
        {/* Main Content - Charts stacked vertically */}
        <main>
          {/* Study Name Header + Metrics in one row */}
          <div className="mb-4 pb-3 border-b border-dark-600 flex items-center justify-between">
            <div>
              {selectedStudyId && (
                <>
                  <h2 className="text-xl font-semibold text-primary-300">
                    {selectedStudyId}
                  </h2>
                  {studyMetadata?.description && (
                    <p className="text-sm text-dark-400 mt-1">{studyMetadata.description}</p>
                  )}
                </>
              )}
            </div>
            {/* Compact Metrics */}
            <div className="flex gap-3">
              <div className="text-center px-3">
                <div className="text-2xl font-bold text-white">{allTrials.length}</div>
                <div className="text-xs text-dark-400">Trials</div>
              </div>
              <div className="text-center px-3 border-l border-dark-600">
                <div className="text-2xl font-bold text-green-400">
                  {bestValue === Infinity ? '-' : bestValue.toFixed(4)}
                </div>
                <div className="text-xs text-dark-400">Best</div>
              </div>
              <div className="text-center px-3 border-l border-dark-600">
                <div className="text-2xl font-bold text-blue-400">
                  {avgObjective > 0 ? avgObjective.toFixed(4) : '-'}
                </div>
                <div className="text-xs text-dark-400">Avg</div>
              </div>
              <div className="text-center px-3 border-l border-dark-600">
                <div className={`text-2xl font-bold ${prunedCount > 0 ? 'text-red-400' : 'text-green-400'}`}>
                  {prunedCount}
                </div>
                <div className="text-xs text-dark-400">Pruned</div>
              </div>
            </div>
          </div>

          {/* Pareto Front - Full Width */}
          {selectedStudyId && paretoFront.length > 0 && studyMetadata && studyMetadata.objectives && (
            <div className="mb-4">
              <ExpandableChart
                title="Pareto Front"
                subtitle={`${paretoFront.length} Pareto-optimal solutions | ${studyMetadata.sampler || 'NSGA-II'} | ${studyMetadata.objectives?.length || 2} objectives`}
              >
                {chartLibrary === 'plotly' ? (
                  <Suspense fallback={<ChartLoading />}>
                    <PlotlyParetoPlot
                      trials={allTrialsRaw}
                      paretoFront={paretoFront}
                      objectives={studyMetadata.objectives}
                      height={300}
                    />
                  </Suspense>
                ) : (
                  <ParetoPlot
                    paretoData={paretoFront}
                    objectives={studyMetadata.objectives}
                    allTrials={allTrialsRaw}
                  />
                )}
              </ExpandableChart>
            </div>
          )}

          {/* Parallel Coordinates - Full Width */}
          {allTrialsRaw.length > 0 && studyMetadata && studyMetadata.objectives && studyMetadata.design_variables && (
            <div className="mb-4">
              <ExpandableChart
                title="Parallel Coordinates"
                subtitle={`${allTrialsRaw.length} trials - Design Variables → Objectives`}
              >
                {chartLibrary === 'plotly' ? (
                  <Suspense fallback={<ChartLoading />}>
                    <PlotlyParallelCoordinates
                      trials={allTrialsRaw}
                      objectives={studyMetadata.objectives}
                      designVariables={studyMetadata.design_variables}
                      paretoFront={paretoFront}
                      height={350}
                    />
                  </Suspense>
                ) : (
                  <ParallelCoordinatesPlot
                    paretoData={allTrialsRaw}
                    objectives={studyMetadata.objectives}
                    designVariables={studyMetadata.design_variables}
                    paretoFront={paretoFront}
                  />
                )}
              </ExpandableChart>
            </div>
          )}

          {/* Convergence Plot - Full Width */}
          {allTrialsRaw.length > 0 && (
            <div className="mb-4">
              <ExpandableChart
                title="Convergence"
                subtitle={`Best ${studyMetadata?.objectives?.[0]?.name || 'Objective'} over ${allTrialsRaw.length} trials`}
              >
                {chartLibrary === 'plotly' ? (
                  <Suspense fallback={<ChartLoading />}>
                    <PlotlyConvergencePlot
                      trials={allTrialsRaw}
                      objectiveIndex={0}
                      objectiveName={studyMetadata?.objectives?.[0]?.name || 'Objective'}
                      direction="minimize"
                      height={280}
                    />
                  </Suspense>
                ) : (
                  <ConvergencePlot
                    trials={allTrialsRaw}
                    objectiveIndex={0}
                    objectiveName={studyMetadata?.objectives?.[0]?.name || 'Objective'}
                    direction="minimize"
                  />
                )}
              </ExpandableChart>
            </div>
          )}

          {/* Parameter Importance - Full Width */}
          {allTrialsRaw.length > 0 && (studyMetadata?.design_variables?.length > 0 || (allTrialsRaw[0]?.params && Object.keys(allTrialsRaw[0].params).length > 0)) && (
            <div className="mb-4">
              <ExpandableChart
                title="Parameter Importance"
                subtitle={`Correlation with ${studyMetadata?.objectives?.[0]?.name || 'Objective'}`}
              >
                {chartLibrary === 'plotly' ? (
                  <Suspense fallback={<ChartLoading />}>
                    <PlotlyParameterImportance
                      trials={allTrialsRaw}
                      designVariables={
                        studyMetadata?.design_variables?.length > 0
                          ? studyMetadata.design_variables
                          : Object.keys(allTrialsRaw[0]?.params || {}).map(name => ({ name }))
                      }
                      objectiveIndex={0}
                      objectiveName={studyMetadata?.objectives?.[0]?.name || 'Objective'}
                      height={280}
                    />
                  </Suspense>
                ) : (
                  <ParameterImportanceChart
                    trials={allTrialsRaw}
                    designVariables={
                      studyMetadata?.design_variables?.length > 0
                        ? studyMetadata.design_variables
                        : Object.keys(allTrialsRaw[0]?.params || {}).map(name => ({ name }))
                    }
                    objectiveIndex={0}
                    objectiveName={studyMetadata?.objectives?.[0]?.name || 'Objective'}
                  />
                )}
              </ExpandableChart>
            </div>
          )}

          {/* Trial History with Sort Controls and Pagination */}
          <Card
            title={
              <div className="flex items-center justify-between w-full">
                <span>Trial History ({displayedTrials.length}{showOnlyFEA ? ' with OP2' : ''} trials{showOnlyFEA && allTrials.length !== displayedTrials.length ? ` of ${allTrials.length}` : ''})</span>
                <div className="flex gap-2 items-center">
                  {/* OP2/Zernike toggle - only show for mirror/zernike studies */}
                  {selectedStudyId && (selectedStudyId.includes('mirror') || selectedStudyId.includes('zernike')) && zernikeAvailableTrials.size > 0 && (
                    <button
                      onClick={() => setShowOnlyFEA(!showOnlyFEA)}
                      className={`px-3 py-1 rounded text-sm ${
                        showOnlyFEA
                          ? 'bg-green-600 text-white'
                          : 'bg-dark-500 text-dark-200 hover:bg-dark-400'
                      }`}
                      title={`Show only ${zernikeAvailableTrials.size} trials with OP2 results (for Zernike analysis)`}
                    >
                      OP2 Only ({zernikeAvailableTrials.size})
                    </button>
                  )}
                  <button
                    onClick={() => setSortBy('performance')}
                    className={`px-3 py-1 rounded text-sm ${
                      sortBy === 'performance'
                        ? 'bg-primary-500 text-white'
                        : 'bg-dark-500 text-dark-200 hover:bg-dark-400'
                    }`}
                  >
                    Best First
                  </button>
                  <button
                    onClick={() => setSortBy('chronological')}
                    className={`px-3 py-1 rounded text-sm ${
                      sortBy === 'chronological'
                        ? 'bg-primary-500 text-white'
                        : 'bg-dark-500 text-dark-200 hover:bg-dark-400'
                    }`}
                  >
                    Newest First
                  </button>
                  {/* Pagination controls */}
                  {displayedTrials.length > trialsPerPage && (
                    <div className="flex items-center gap-1 ml-2 border-l border-dark-500 pl-2">
                      <button
                        onClick={() => setTrialsPage(Math.max(0, trialsPage - 1))}
                        disabled={trialsPage === 0}
                        className="px-2 py-1 text-sm bg-dark-500 rounded disabled:opacity-50 hover:bg-dark-400"
                      >
                        ‹
                      </button>
                      <span className="text-xs text-dark-300 px-2">
                        {trialsPage + 1}/{Math.ceil(displayedTrials.length / trialsPerPage)}
                      </span>
                      <button
                        onClick={() => setTrialsPage(Math.min(Math.ceil(displayedTrials.length / trialsPerPage) - 1, trialsPage + 1))}
                        disabled={trialsPage >= Math.ceil(displayedTrials.length / trialsPerPage) - 1}
                        className="px-2 py-1 text-sm bg-dark-500 rounded disabled:opacity-50 hover:bg-dark-400"
                      >
                        ›
                      </button>
                    </div>
                  )}
                </div>
              </div>
            }
          >
            <div className="space-y-2 max-h-[600px] overflow-y-auto">
              {displayedTrials.length > 0 ? (
                displayedTrials.slice(trialsPage * trialsPerPage, (trialsPage + 1) * trialsPerPage).map((trial, idx) => {
                  const isExpanded = expandedTrials.has(trial.trial_number);
                  const isBest = trial.objective === bestValue;

                  return (
                    <div
                      key={`trial-${trial.trial_number}-${idx}`}
                      className={`rounded-lg transition-all duration-200 cursor-pointer ${
                        isBest
                          ? 'bg-green-900 border-l-4 border-green-400'
                          : 'bg-dark-500 hover:bg-dark-400'
                      }`}
                      onClick={() => toggleTrialExpansion(trial.trial_number)}
                    >
                      {/* Collapsed View */}
                      <div className="p-3">
                        <div className="flex justify-between items-center">
                          <span className="font-semibold text-primary-400">
                            Trial #{trial.trial_number}
                            {isBest && <span className="ml-2 text-xs bg-green-700 text-green-100 px-2 py-1 rounded">BEST</span>}
                          </span>
                          <div className="flex items-center gap-3">
                            <span className={`font-mono text-lg ${
                              isBest ? 'text-green-400 font-bold' : 'text-dark-100'
                            }`}>
                              {trial.objective !== null && trial.objective !== undefined
                                ? trial.objective.toFixed(4)
                                : 'N/A'}
                            </span>
                            {/* Zernike viewer button - only show for mirror/Zernike studies */}
                            {selectedStudyId && (selectedStudyId.includes('mirror') || selectedStudyId.includes('zernike')) && (
                              <ZernikeButton
                                studyId={selectedStudyId}
                                trialNumber={trial.trial_number}
                                compact
                              />
                            )}
                            <span className="text-dark-400 text-sm">
                              {isExpanded ? '▼' : '▶'}
                            </span>
                          </div>
                        </div>

                        {/* Quick Preview - Show ALL metrics */}
                        {!isExpanded && trial.results && Object.keys(trial.results).length > 0 && (
                          <div className="text-xs text-primary-300 flex flex-wrap gap-3 mt-2">
                            {Object.entries(trial.results).slice(0, 6).map(([key, val]) => {
                              // Format value based on type
                              const formatValue = (v: unknown): string => {
                                if (typeof v === 'number') {
                                  // Use fewer decimals for quick preview
                                  return Math.abs(v) < 0.01 ? v.toExponential(2) : v.toFixed(2);
                                }
                                if (Array.isArray(v)) return `[${v.length}]`;
                                return String(v);
                              };
                              // Format key: snake_case to Title Case, abbreviate long names
                              const formatKey = (k: string): string => {
                                const short = k.replace(/_/g, ' ')
                                  .replace(/rel /g, 'Δ')
                                  .replace(/filtered rms/g, 'fRMS')
                                  .replace(/global rms/g, 'gRMS')
                                  .replace(/ vs /g, '/')
                                  .replace(/mfg /g, '')
                                  .replace(/optician workload/g, 'work');
                                return short.length > 15 ? short.slice(0, 12) + '...' : short;
                              };
                              return (
                                <span key={key} title={`${key}: ${val}`}>
                                  {formatKey(key)}: {formatValue(val)}
                                </span>
                              );
                            })}
                            {Object.keys(trial.results).length > 6 && (
                              <span className="text-dark-400">+{Object.keys(trial.results).length - 6} more</span>
                            )}
                          </div>
                        )}
                      </div>

                      {/* Expanded View */}
                      {isExpanded && (
                        <div className="px-3 pb-3 space-y-3">
                          {/* Design Variables */}
                          {trial.design_variables && Object.keys(trial.design_variables).length > 0 && (
                            <div className="border-t border-dark-400 pt-3">
                              <h4 className="text-sm font-semibold text-dark-200 mb-2">Design Variables</h4>
                              <div className="grid grid-cols-2 gap-2 text-xs">
                                {Object.entries(trial.design_variables).map(([key, val]) => (
                                  <div key={key} className="flex justify-between bg-dark-600 px-2 py-1 rounded">
                                    <span className="text-dark-300">{key}:</span>
                                    <span className="text-dark-100 font-mono">{val.toFixed(4)}</span>
                                  </div>
                                ))}
                              </div>
                            </div>
                          )}

                          {/* Results */}
                          {trial.results && Object.keys(trial.results).length > 0 && (
                            <div className="border-t border-dark-400 pt-3">
                              <h4 className="text-sm font-semibold text-dark-200 mb-2">Extracted Results</h4>
                              <div className="grid grid-cols-2 gap-2 text-xs">
                                {Object.entries(trial.results).map(([key, val]) => (
                                  <div key={key} className="flex justify-between bg-dark-600 px-2 py-1 rounded">
                                    <span className="text-dark-300">{key}:</span>
                                    <span className="text-primary-300 font-mono">
                                      {typeof val === 'number' ? val.toFixed(4) : String(val)}
                                    </span>
                                  </div>
                                ))}
                              </div>
                            </div>
                          )}

                          {/* All User Attributes */}
                          {trial.user_attrs && Object.keys(trial.user_attrs).length > 0 && (
                            <div className="border-t border-dark-400 pt-3">
                              <h4 className="text-sm font-semibold text-dark-200 mb-2">All Attributes</h4>
                              <div className="max-h-48 overflow-y-auto">
                                <pre className="text-xs text-dark-300 bg-dark-700 p-2 rounded">
                                  {JSON.stringify(trial.user_attrs, null, 2)}
                                </pre>
                              </div>
                            </div>
                          )}

                          {/* Timestamps */}
                          {trial.start_time && trial.end_time && (
                            <div className="border-t border-dark-400 pt-3 text-xs text-dark-400">
                              <div className="flex justify-between">
                                <span>Duration:</span>
                                <span>
                                  {((new Date(trial.end_time).getTime() - new Date(trial.start_time).getTime()) / 1000).toFixed(1)}s
                                </span>
                              </div>
                            </div>
                          )}

                          {/* Zernike Analysis Button - Full size in expanded view */}
                          {selectedStudyId && (selectedStudyId.includes('mirror') || selectedStudyId.includes('zernike')) && (
                            <div className="border-t border-dark-400 pt-3 mt-3">
                              <ZernikeButton
                                studyId={selectedStudyId}
                                trialNumber={trial.trial_number}
                              />
                            </div>
                          )}
                        </div>
                      )}
                    </div>
                  );
                })
              ) : (
                <div className="text-center py-8 text-dark-300">
                  No trials yet. Waiting for optimization to start...
                </div>
              )}
            </div>
          </Card>

          {/* Console Output - at the bottom */}
          <div className="mt-4">
            <ConsoleOutput
              studyId={selectedStudyId}
              refreshInterval={2000}
              maxLines={150}
            />
          </div>
        </main>
      </div>

      {/* Config Editor Modal */}
      {showConfigEditor && selectedStudyId && (
        <ConfigEditor
          studyId={selectedStudyId}
          onClose={() => setShowConfigEditor(false)}
          onSaved={() => refreshStudies()}
        />
      )}
    </div>
  );
}
