
import React, { useState, useMemo, useEffect, useCallback, lazy, Suspense } from 'react';
import { DatasetManager } from './components/DatasetManager';
import type { Dataset, DatasetMetadata } from './types';
import * as db from './services/dbService';
import * as apiService from './services/apiService';
import { Spinner } from './components/common/Spinner';

const ComparisonTool = lazy(() => import('./components/ComparisonTool').then(module => ({ default: module.ComparisonTool })));

type View = 'manager' | 'comparison';

const App: React.FC = () => {
  const [datasets, setDatasets] = useState<DatasetMetadata[]>([]);
  const [selectedDatasetId, setSelectedDatasetId] = useState<string | null>(null);
  const [activeDataset, setActiveDataset] = useState<Dataset | null>(null);
  const [view, setView] = useState<View>('manager');
  const [isLoading, setIsLoading] = useState(true);
  const [isNavigating, setIsNavigating] = useState(false);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    const loadInitialData = async () => {
      try {
        const localMeta = await db.getAllDatasetMetadata();
        let sharedMeta: DatasetMetadata[] = [];
        try {
            sharedMeta = await apiService.getSharedDatasetMetadata();
        } catch (e) {
            console.error("Could not load shared datasets, continuing with local.", e);
            setError("Could not load cloud datasets. The backend service may be unavailable. Local datasets are still accessible.");
        }
        
        const allMeta = [...sharedMeta, ...localMeta];

        setDatasets(allMeta);

        if (allMeta.length > 0) {
            // Select the most recent dataset by default
            const sortedMeta = [...allMeta].sort((a, b) => new Date(b.uploadDate).getTime() - new Date(a.uploadDate).getTime());
            setSelectedDatasetId(sortedMeta[0].id);
        }
      } catch (error) {
        console.error("Failed to load initial data", error);
        setError("A critical error occurred while loading local datasets.");
      } finally {
        setIsLoading(false);
      }
    };
    loadInitialData();
  }, []);

  const addDataset = async (newDataset: Dataset) => {
    await db.addDataset(newDataset);
    const localMeta = await db.getAllDatasetMetadata();
    const sharedMeta = datasets.filter(d => d.isShared); // Keep existing shared meta
    setDatasets([...sharedMeta, ...localMeta]);
    setSelectedDatasetId(newDataset.id);
  };

  const deleteDataset = async (id: string) => {
    await db.deleteDataset(id);
    setDatasets(prevDatasets => {
      const newDatasets = prevDatasets.filter(d => d.id !== id);
      if (selectedDatasetId === id) {
        const sortedMeta = [...newDatasets].sort((a, b) => new Date(b.uploadDate).getTime() - new Date(a.uploadDate).getTime());
        setSelectedDatasetId(sortedMeta.length > 0 ? sortedMeta[0].id : null);
      }
      return newDatasets;
    });
  };

  const renameDataset = async (id: string, newName: string) => {
    await db.renameDataset(id, newName);
    setDatasets(prev => prev.map(d => d.id === id ? { ...d, name: newName } : d));
  };
  
  const processedDatasets = useMemo(() => {
    return datasets.filter(d => d.processingState === 'processed');
  }, [datasets]);

  const getFullDataset = async (id: string): Promise<Dataset | null> => {
    const meta = datasets.find(d => d.id === id);
    if (!meta) return null;

    if (meta.isShared) {
      return apiService.getSharedDataset(id);
    } else {
      return db.getDataset(id);
    }
  };

  const handleOpenComparisonTool = useCallback(async () => {
    if (!selectedDatasetId) return;
    const selectedMeta = datasets.find(d => d.id === selectedDatasetId);
    if (!selectedMeta || selectedMeta.processingState !== 'processed') return;

    setView('comparison');
    setActiveDataset(null);
    setIsNavigating(true);

    try {
        const fullDataset = await getFullDataset(selectedDatasetId);
        if (!fullDataset) {
            throw new Error(`Failed to load dataset ${selectedDatasetId}.`);
        }

        // *** NEW LOGIC ***
        // If it's a local dataset, ensure it's in the backend's cache before proceeding.
        if (!fullDataset.isShared) {
            console.log("Local dataset selected. Ensuring it's cached on the backend...");
            await apiService.ensureDatasetInCache(fullDataset);
            console.log("Backend cache confirmed.");
        }

        setActiveDataset(fullDataset);

    } catch (error) {
        console.error("Error preparing comparison tool:", error);
        alert(`Error: Could not load the selected dataset. ${error instanceof Error ? error.message : ''}`);
        setView('manager'); // Go back on error
    } finally {
        setIsNavigating(false);
    }
  }, [selectedDatasetId, datasets]);

  const handleDatasetChange = useCallback(async (newId: string) => {
      setSelectedDatasetId(newId);
      
      setActiveDataset(null);
      setIsNavigating(true);

      try {
        const fullDataset = await getFullDataset(newId);
        if (!fullDataset) {
            throw new Error(`Failed to load dataset ${newId}.`);
        }

        // Also ensure cache is hydrated when switching datasets inside the tool
        if (!fullDataset.isShared) {
            await apiService.ensureDatasetInCache(fullDataset);
        }
        
        setActiveDataset(fullDataset);

      } catch (error) {
            console.error(`Error switching dataset to ${newId}:`, error);
            setActiveDataset(null);
      } finally {
          setIsNavigating(false);
      }
  }, []);


  const mainContent = () => {
    if (isLoading) {
        return <div className="flex justify-center items-center h-64"><Spinner /><span>Loading Datasets...</span></div>;
    }
    
    const errorBanner = error ? (
        <div className="bg-red-800/50 border border-red-600 text-red-200 px-4 py-3 rounded-lg mb-4" role="alert">
          <p>
            <strong className="font-bold">Cloud Connection Error:</strong> {error}
          </p>
        </div>
    ) : null;

    if (view === 'manager') {
      return (
        <DatasetManager
          datasets={datasets}
          selectedDatasetId={selectedDatasetId}
          onSelectDataset={setSelectedDatasetId}
          onAddDataset={addDataset}
          onDeleteDataset={deleteDataset}
          onRenameDataset={renameDataset}
          onOpenComparisonTool={handleOpenComparisonTool}
          onGetFullDataset={getFullDataset}
          errorBanner={errorBanner}
        />
      );
    }
    
    if (view === 'comparison') {
        const fallbackUI = <div className="flex justify-center items-center h-64"><Spinner /><span>Loading Comparison Tool...</span></div>;
        if (isNavigating || !activeDataset) {
            return fallbackUI;
        }
        return (
            <Suspense fallback={fallbackUI}>
                <ComparisonTool
                    key={activeDataset.id}
                    dataset={activeDataset}
                    allDatasets={processedDatasets}
                    onDatasetChange={handleDatasetChange}
                    onBack={() => { setView('manager'); setActiveDataset(null); }}
                />
            </Suspense>
        );
    }
    return null;
  };

  return (
    <div className="min-h-screen bg-gray-900 text-gray-200 font-sans">
      <header className="bg-gray-800/50 backdrop-blur-sm border-b border-gray-700 sticky top-0 z-20">
        <div className="container mx-auto px-4 sm:px-6 lg:px-8 py-4 flex items-center justify-between">
          <h1 className="text-2xl font-bold text-cyan-400">
            Cross-Modal Object Comparison Tool
          </h1>
        </div>
      </header>
      <main className="container mx-auto px-4 sm:px-6 lg:px-8 py-8">
        {mainContent()}
      </main>
    </div>
  );
};

export default App;
