import React, { useState, useEffect } from 'react';
import SimulationCanvas from './components/SimulationCanvas';
import SimulationControls from './components/SimulationControls';
import SimulationList from './components/SimulationList';
import ConfigurationPanel from './components/ConfigurationPanel';
import { Play, Pause, Square } from 'lucide-react';

export interface Body {
  name: string;
  mass: number;
  position: [number, number, number];
  velocity: [number, number, number];
}

export interface Config {
  bodies: Body[];
  normalization?: {
    m_0: number;
    r_0: number;
    t_0: number;
  };
}

export interface SimulationInfo {
  id: string;
  is_running: boolean;
  current_step: number;
  playback_step: number;
  total_steps: number;
  recorded_steps: number;
  bodies_count: number;
  elapsed_time: number;
}

export interface BodyState {
  name: string;
  position: [number, number, number];
  velocity: [number, number, number];
  mass: number;
}

export interface SimulationUpdate {
  step: number;
  time: number;
  bodies: BodyState[];
  energy?: {
    kinetic: number;
    potential: number;
    total: number;
  };
}

function App() {
  const [simulations, setSimulations] = useState<SimulationInfo[]>([]);
  const [selectedSimulation, setSelectedSimulation] = useState<string | null>(null);
  const [currentData, setCurrentData] = useState<SimulationUpdate | null>(null);
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [isAutoPlaying, setIsAutoPlaying] = useState(true); // Auto-play timeline by default
  const [sessionId] = useState(() => {
    // Generate or retrieve session ID from localStorage
    let id = localStorage.getItem('orbital-sim-session');
    if (!id) {
      id = crypto.randomUUID();
      localStorage.setItem('orbital-sim-session', id);
    }
    return id;
  });

  // Helper function to add session header to requests
  const getHeaders = () => ({
    'Content-Type': 'application/json',
    'X-Session-ID': sessionId,
  });

  // Fetch simulations list
  const fetchSimulations = async () => {
    try {
      const response = await fetch('/api/simulations', {
        headers: { 'X-Session-ID': sessionId },
      });
      if (response.ok) {
        const data = await response.json();
        setSimulations(data);
      }
    } catch (err) {
      setError('Failed to fetch simulations');
    }
  };

  // Create new simulation
  const createSimulation = async (config: Config, stepSize: number, totalSteps: number) => {
    setIsLoading(true);
    setError(null);
    
    try {
      const response = await fetch('/api/simulations', {
        method: 'POST',
        headers: getHeaders(),
        body: JSON.stringify({
          config,
          step_size: stepSize,
          total_steps: totalSteps,
        }),
      });

      if (response.ok) {
        const newSim = await response.json();
        setSelectedSimulation(newSim.id);
        await fetchSimulations();
      } else {
        setError('Failed to create simulation');
      }
    } catch (err) {
      setError('Failed to create simulation');
    } finally {
      setIsLoading(false);
    }
  };

  // Control simulation
  const controlSimulation = async (id: string, action: string) => {
    try {
      const response = await fetch(`/api/simulations/${id}/control?action=${action}`, {
        method: 'POST',
        headers: { 'X-Session-ID': sessionId },
      });

      if (response.ok) {
        await fetchSimulations();
      }
    } catch (err) {
      setError(`Failed to ${action} simulation`);
    }
  };

  // Delete simulation
  const deleteSimulation = async (id: string) => {
    try {
      const response = await fetch(`/api/simulations/${id}`, {
        method: 'DELETE',
        headers: { 'X-Session-ID': sessionId },
      });

      if (response.ok) {
        if (selectedSimulation === id) {
          setSelectedSimulation(null);
          setCurrentData(null);
        }
        await fetchSimulations();
      }
    } catch (err) {
      setError('Failed to delete simulation');
    }
  };

  // Seek to specific simulation step
  const seekToStep = async (id: string, step: number) => {
    try {
      const response = await fetch(`/api/simulations/${id}/seek?step=${step}`, {
        method: 'POST',
        headers: { 'X-Session-ID': sessionId },
      });

      if (response.ok) {
        const data = await response.json();
        setCurrentData(data);
        await fetchSimulations(); // Update playback_step in simulation info
      } else {
        setError('Failed to seek simulation');
      }
    } catch (err) {
      setError('Failed to seek simulation');
    }
  };

  // Timeline control functions
  const handleSeek = (step: number) => {
    if (selectedSimulation) {
      seekToStep(selectedSimulation, step);
    }
  };

  const handleToggleAutoPlay = () => {
    setIsAutoPlaying(!isAutoPlaying);
  };

  const handleRestart = () => {
    if (selectedSimulation) {
      seekToStep(selectedSimulation, 0);
    }
  };

  // Poll simulation data (only when auto-playing or simulation is running)
  useEffect(() => {
    if (!selectedSimulation) return;

    const interval = setInterval(async () => {
      const selectedSim = simulations.find(s => s.id === selectedSimulation);
      
      // Only poll if auto-playing is enabled or if simulation is running
      if (!isAutoPlaying && selectedSim && !selectedSim.is_running) {
        return;
      }

      try {
        const response = await fetch(`/api/simulations/${selectedSimulation}`, {
          headers: { 'X-Session-ID': sessionId },
        });
        if (response.ok) {
          const data = await response.json();
          setCurrentData(data);
        }
      } catch (err) {
        // Silently fail for polling
      }
    }, 100); // 10 FPS updates

    return () => clearInterval(interval);
  }, [selectedSimulation, isAutoPlaying, simulations]);

  // Initial load
  useEffect(() => {
    fetchSimulations();
  }, []);

  const selectedSim = simulations.find(s => s.id === selectedSimulation);

  return (
    <div className="app">
      <header className="header">
        <div className="logo">Orbital Simulator</div>
        <div className="controls">
          {selectedSim && (
            <>
              <button
                className="button"
                onClick={() => controlSimulation(selectedSim.id, selectedSim.is_running ? 'pause' : 'start')}
                disabled={isLoading}
              >
                {selectedSim.is_running ? <Pause size={16} /> : <Play size={16} />}
                {selectedSim.is_running ? 'Pause' : 'Start'}
              </button>
              <button
                className="button secondary"
                onClick={() => controlSimulation(selectedSim.id, 'step')}
                disabled={isLoading || selectedSim.is_running}
              >
                Step
              </button>
              <button
                className="button secondary"
                onClick={() => controlSimulation(selectedSim.id, 'stop')}
                disabled={isLoading}
              >
                <Square size={16} />
                Stop
              </button>
            </>
          )}
        </div>
      </header>

      <div className="main-content">
        <div className="sidebar">
          <ConfigurationPanel
            onCreateSimulation={createSimulation}
            isLoading={isLoading}
          />
          
          <SimulationList
            simulations={simulations}
            selectedSimulation={selectedSimulation}
            currentData={currentData}
            isAutoPlaying={isAutoPlaying}
            onSelectSimulation={setSelectedSimulation}
            onDeleteSimulation={deleteSimulation}
            onControlSimulation={controlSimulation}
            onSeek={handleSeek}
            onToggleAutoPlay={handleToggleAutoPlay}
            onRestart={handleRestart}
          />

          {selectedSim && currentData && (
            <SimulationControls
              data={currentData}
            />
          )}
        </div>

        <div className="simulation-view">
          {error && (
            <div className="error">
              {error}
              <button 
                className="button secondary"
                onClick={() => setError(null)}
                style={{ marginLeft: '1rem' }}
              >
                Dismiss
              </button>
            </div>
          )}

          {currentData ? (
            <SimulationCanvas data={currentData} />
          ) : selectedSimulation ? (
            <div className="loading">Loading simulation data...</div>
          ) : (
            <div className="loading">Select or create a simulation to begin</div>
          )}
        </div>
      </div>
    </div>
  );
}

export default App;
