import { useState, useEffect} from 'react';
// import Waterfall from './components/Waterfall.js';
import SankeyDiagram from './components/Sankey.js';
import Heatmap from './components/Heatmap.js';
import AssessmentItems from './components/itemList.js';
import { getThemes, getJudges, getModelFamilies, getProviders, getReclassificationData, getAssessmentItems, getModels } from './utils/apiUtils.js';
import { modelSort } from './utils/chartUtils.js';
import type { Theme, Judges, Model, ModelFamily, Provider, SelectedJudge, TransitionMatrix, AssessmentItem } from './types';
import FilterBar from './components/Filterbar';

function App() {

  const [themes, setThemes] = useState<Theme[]>([]);
  const [judges, setJudges] = useState<Judges[]>([]);
  const [models, setModels] = useState<Model[]>([]);
  const [modelFamilies, setModelFamilies] = useState<ModelFamily[]>([]);
  const [providers, setProviders] = useState<Provider[]>([]);
  const [matrix, setMatrix] = useState<TransitionMatrix | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [isLoading, setIsLoading] = useState(false);
  const [loadingItems, setLoadingItems] = useState(false);

  const [selectedTheme, setSelectedTheme] = useState<string>('');
  const [selectedModel, setSelectedModel] = useState<string>('');
  const [selectedModelFamily, setSelectedModelFamily] = useState<string>('');
  const [selectedProvider, setSelectedProvider] = useState<string>('');
  const [selectedJudge1, setSelectedJudge1] = useState<SelectedJudge | null >(null);
  const [selectedJudge2, setSelectedJudge2] = useState<SelectedJudge | null >(null);
  const [selectedCategory, setSelectedCategory] = useState<string[] | null>(null);
  const [selectedItems, setSelectedItems] = useState<AssessmentItem[]>([]);

  const getFirstClassification = (judge: Judges): string => {
    return Object.keys(judge.classifications).filter(key => judge.classifications[key] > 0)[0] || '';
  };

  // Fetch initial data when the component mounts
  useEffect(() => {
    const loadFilters = async () => {
      try {
        const [themesData, judgesData, modelsData, modelFamiliesData, providersData] = await Promise.all([
          getThemes(),
          getJudges(),
          getModels(),
          getModelFamilies(),
          getProviders(),
        ]);
        setThemes(themesData);
        setJudges(judgesData.sort(modelSort));
        setModels(modelsData);
        setModelFamilies(modelFamiliesData);
        setProviders(providersData);

        // Set default selections
        if (judgesData.length >= 2) {
          setSelectedJudge1({
            name: judgesData[0].name,
            classification: getFirstClassification(judgesData[0]),
          });
          setSelectedJudge2({
            name: judgesData[1].name,
            classification: getFirstClassification(judgesData[1]),
          });
        }

      } catch (err) {
        setError('Failed to load filter data. Is the backend server running?');
        console.error(err);
      }
    };
    loadFilters();
  }, []); 

  // Data fetching logic
  useEffect(() => {
    if (!selectedJudge1 || !selectedJudge2) return;

    const fetchData = async () => {
      setIsLoading(true);
      setError(null);
      setMatrix(null);
      try {
        const result = await getReclassificationData(
          selectedJudge1.name,
          selectedJudge1.classification,
          selectedJudge2.name,
          selectedJudge2.classification,
          selectedTheme,
          selectedModel,
          selectedModelFamily,
          selectedProvider
        );
        setMatrix(result);
        setSelectedItems([]); 
        setSelectedCategory(null); 
      } catch (err) {
        setError(err instanceof Error ? err.message : 'An unknown error occurred.');
      } finally {
        setIsLoading(false);
      }
    };

    fetchData();
  }, [selectedTheme, selectedJudge1, selectedJudge2, selectedModel, selectedModelFamily, selectedProvider]);

  const handleJudge1NameChange = (newName: string) => {
    const newJudge = judges.find(j => j.name === newName);
    if (newJudge) {
      // When judge changes, reset classification to the first available one
      setSelectedJudge1({
        name: newName,
        classification: getFirstClassification(newJudge),
      });
    }
  };

  const handleJudge1ClassificationChange = (newClassification: string) => {
    if (selectedJudge1) {
      setSelectedJudge1({ ...selectedJudge1, classification: newClassification });
    }
  };
  
  const handleJudge2NameChange = (newName: string) => {
    const newJudge = judges.find(j => j.name === newName);
    if (newJudge) {
      setSelectedJudge2({
        name: newName,
        classification: getFirstClassification(newJudge),
      });
    }
  };
  
  const handleJudge2ClassificationChange = (newClassification: string) => {
    if (selectedJudge2) {
      setSelectedJudge2({ ...selectedJudge2, classification: newClassification });
    }
  };

  // Handle cell click to fetch assessment items
  const handleCellClick = async (fromCategory: string, toCategory: string) => {
    if (selectedJudge1 && selectedJudge2 && fromCategory && toCategory) {
      setLoadingItems(true);
      try {
        const items = await getAssessmentItems(
          selectedJudge1.name,
          selectedJudge1.classification,
          fromCategory, 
          selectedJudge2.name, 
          selectedJudge2.classification,
          toCategory, 
          selectedTheme,
          selectedModel,
          selectedModelFamily,
          selectedProvider
        )
        setSelectedItems(items);
        setSelectedCategory([fromCategory, toCategory]);
      } catch (err) {
        setError(err instanceof Error ? err.message : 'An unknown error occurred.');
      } finally {
        setLoadingItems(false);
      };
    }

    return;
  };

  return (
      <div className="app">
      <header className="app-header">
        <div className="header-content">
          <div className="logo-section">
            <svg width="40" height="40" viewBox="0 0 40 40" className="logo">
              <circle cx="20" cy="20" r="18" fill="#10b981" />
              <path d="M12 20l6 6 10-12" stroke="white" strokeWidth="3" fill="none" strokeLinecap="round" strokeLinejoin="round"/>
            </svg>
            <h1 className="app-title">LLM Assessment Explorer</h1>
          </div>
        </div>
      </header>

      <main className="main-content">
          <FilterBar
            themes={themes}
            judges={judges}
            models={models}
            modelFamilies={modelFamilies}
            providers={providers}
            selectedTheme={selectedTheme}
            onThemeChange={setSelectedTheme}
            selectedModel={selectedModel}
            onModelChange={setSelectedModel}
            selectedModelFamily={selectedModelFamily}
            onModelFamilyChange={setSelectedModelFamily}
            selectedProvider={selectedProvider}
            onProviderChange={setSelectedProvider}
            selectedJudge1={selectedJudge1}
            selectedJudge2={selectedJudge2}
            onJudge1NameChange={handleJudge1NameChange}
            onJudge1ClassificationChange={handleJudge1ClassificationChange}
            onJudge2NameChange={handleJudge2NameChange}
            onJudge2ClassificationChange={handleJudge2ClassificationChange}
          />

          {isLoading && (
            <div className="loading-indicator">
              <div className="loading-spinner"></div>
              <p>Loading data...</p>
            </div>
          )}

         {!isLoading && matrix && (
          <div className="charts-container">
            <SankeyDiagram
              matrix={matrix}
              judge1={selectedJudge1!.name}
              judge2={selectedJudge2!.name}
              onCellClick={handleCellClick}
            />
            
            <Heatmap
              matrix={matrix}
              judge1={selectedJudge1!.name}
              judge2={selectedJudge2!.name}
              onCellClick={handleCellClick}
            />
          </div>
        )}

        {!loadingItems && selectedItems.length > 0 && (
          <AssessmentItems
            judge1={selectedJudge1!.name}
            judge2={selectedJudge2!.name}
            items={selectedItems}
            selectedCategory={selectedCategory}
          />
        )}
        {loadingItems && (
            <div className="loading-indicator">
              <div className="loading-spinner"></div>
              <p>Loading data...</p>
            </div>
          )}
      </main>
    </div>
  );
}

export default App;