import { useState, useEffect } from 'react';
import axios from 'axios';
import './App.css';
import 'react-leaflet-cluster/dist/assets/MarkerCluster.css';
import 'react-leaflet-cluster/dist/assets/MarkerCluster.Default.css';
import FileUpload from './components/FileUpload';
import FilterPanel from './components/FilterPanel';
import MapDisplay from './components/MapDisplay';
import ErrorBoundary from './components/ErrorBoundary';
import PlzSelector from './components/PlzSelector';

// Define types for our state
export interface FilterOptions {
  [key: string]: string[];
}

export interface TooltipColumn {
  id: string;
  name: string;
  visible: boolean;
}

export interface HeatmapPoint {
  plz: string;
  lat: number;
  lon: number;
  count: number;
  attributes_summary?: Record<string, string[]>;
}

export type MapMode = 'points' | 'heatmap';

function App() {
  const [filters, setFilters] = useState<FilterOptions>({});
  const [heatmapData, setHeatmapData] = useState<HeatmapPoint[]>([]);
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [radiusMultiplier, setRadiusMultiplier] = useState(1);
  const [viewMode, setViewMode] = useState<MapMode>('points');
  
  const [plzColumnNeeded, setPlzColumnNeeded] = useState(false);
  const [availableColumns, setAvailableColumns] = useState<string[]>([]);
  const [tooltipColumns, setTooltipColumns] = useState<TooltipColumn[]>([]);


  const handleUploadSuccess = (response: any) => {
    setError(null);
    if (response.plz_column_needed) {
      setAvailableColumns(response.columns);
      setPlzColumnNeeded(true);
      setFilters({});
      setHeatmapData([]);
      setTooltipColumns([]);
    } else {
      setPlzColumnNeeded(false);
      const newFilters = response.filters;
      setFilters(newFilters);
      // Initialize tooltip columns based on filters
      setTooltipColumns(Object.keys(newFilters).map(name => ({ id: name, name, visible: true })));
      setHeatmapData([]); // Clear previous heatmap data
      // Automatically fetch data with no filters on successful upload
      // Pass initial tooltip config
      handleFilterChange({}, Object.keys(newFilters).map(name => ({ id: name, name, visible: true })));
    }
  };

  const handlePlzColumnSubmit = async (selectedColumn: string) => {
    setIsLoading(true);
    setError(null);
    try {
      const response = await axios.post('/heatmap/api/set-plz-column', {
        plz_column: selectedColumn,
      });
      handleUploadSuccess(response.data); // Re-use the success handler
    } catch (error: any) {
        if (axios.isAxiosError(error) && error.response) {
            setError(`Failed to set PLZ column: ${error.response.data.detail || error.message}`);
        }
        else {
            setError(`Failed to set PLZ column: ${error.message}`);
        }
    }
    finally {
        setIsLoading(false);
    }
  };

  const handleFilterChange = async (selectedFilters: FilterOptions, currentTooltipConfig: TooltipColumn[]) => {
    setIsLoading(true);
    setError(null);
    try {
      const response = await axios.post('/heatmap/api/heatmap', {
        filters: selectedFilters,
        tooltip_config: currentTooltipConfig, // Pass tooltip config to backend
      });
      setHeatmapData(response.data);
    } catch (error: any) {
        if (axios.isAxiosError(error) && error.response) {
            setError(`Failed to fetch heatmap data: ${error.response.data.detail || error.message}`);
        }
        else {
            setError(`Failed to fetch heatmap data: ${error.message}`);
        }
      setHeatmapData([]); // Clear data on error
    }
    finally {
      setIsLoading(false);
    }
  };
  
  // Need to re-fetch data when tooltip config changes. 
  // Optimization: In a real app, we might debounce this or add an "Apply" button for sorting.
  // For now, let's keep it manual via the "Apply Filters" button in the FilterPanel to avoid excessive API calls while dragging.
  // The FilterPanel calls onFilterChange when "Apply" is clicked, passing both filters and the current tooltipColumns.

  return (
    <ErrorBoundary>
        <div className="App">
        <header className="App-header">
            <h1>German PLZ Heatmap Tool</h1>
        </header>
        <main className="App-main">
            <div className="control-panel">
              <FileUpload
                  onUploadSuccess={handleUploadSuccess}
                  setIsLoading={setIsLoading}
                  setError={setError}
              />
              {plzColumnNeeded ? (
                <PlzSelector
                  columns={availableColumns}
                  onSubmit={handlePlzColumnSubmit}
                  isLoading={isLoading}
                />
              ) : (
                <>
                  <FilterPanel
                      filters={filters}
                      tooltipColumns={tooltipColumns}
                      setTooltipColumns={setTooltipColumns}
                      onFilterChange={(selectedFilters) => handleFilterChange(selectedFilters, tooltipColumns)}
                      isLoading={isLoading}
                  />
                  <div className="map-controls" style={{ marginTop: '20px', paddingTop: '20px', borderTop: '1px solid #555' }}>
                    <h3>Map Settings</h3>
                    <div className="toggle-switch" style={{ marginBottom: '15px' }}>
                      <label>
                        <input type="radio" value="points" checked={viewMode === 'points'} onChange={() => setViewMode('points')} />
                        Points
                      </label>
                      <label>
                        <input type="radio" value="heatmap" checked={viewMode === 'heatmap'} onChange={() => setViewMode('heatmap')} />
                        Heatmap
                      </label>
                    </div>
                    <label htmlFor="radius-slider">Marker Size: {radiusMultiplier.toFixed(1)}x</label>
                    <input
                      type="range"
                      id="radius-slider"
                      min="0.1"
                      max="5"
                      step="0.1"
                      value={radiusMultiplier}
                      onChange={(e) => setRadiusMultiplier(parseFloat(e.target.value))}
                      style={{ width: '100%' }}
                      disabled={viewMode === 'heatmap'}
                    />
                  </div>
                </>
              )}
            </div>
            <div className="map-container">
            {isLoading ? (
                <p>Loading map data...</p>
            ) : error ? (
                <p className="error">{error}</p>
            ) : (
                <MapDisplay
                heatmapData={heatmapData}
                radiusMultiplier={radiusMultiplier}
                viewMode={viewMode}
                tooltipColumns={tooltipColumns}
                />
            )}
            </div>
        </main>
        </div>
    </ErrorBoundary>
  );
}

export default App;
