// src/features/legislativas/provinciales/MapaBsAsSecciones.tsx
import { useState, useMemo, useCallback, useEffect } from 'react';
import { ComposableMap, Geographies, Geography, ZoomableGroup } from 'react-simple-maps';
import { Tooltip } from 'react-tooltip';
import { useQuery } from '@tanstack/react-query';
import axios from 'axios';
import { geoCentroid } from 'd3-geo';
import { getDetalleSeccion, API_BASE_URL, assetBaseUrl } from '../../../apiService';
import { type ResultadoDetalleSeccion } from '../../../apiService';
import './MapaBsAs.css';

// --- Interfaces y Tipos ---
type PointTuple = [number, number];
interface ResultadoMapaSeccion {
  seccionId: string;
  seccionNombre: string;
  agrupacionGanadoraId: string | null;
  colorGanador: string | null;
}
interface Agrupacion { id: string; nombre: string; }
interface Categoria { id: number; nombre: string; }
type SeccionGeography = {
  rsmKey: string;
  properties: { seccion: string; fna: string; };
};

// --- Constantes ---
const DEFAULT_MAP_COLOR = '#E0E0E0';
const CATEGORIAS: Categoria[] = [{ id: 5, nombre: 'Senadores' }, { id: 6, nombre: 'Diputados' }];
const SECCION_ID_TO_ROMAN: Record<string, string> = { '1': 'I', '2': 'II', '3': 'III', '4': 'IV', '5': 'V', '6': 'VI', '7': 'VII', '8': 'VIII' };
const ROMAN_TO_SECCION_ID: Record<string, string> = { 'I': '1', 'II': '2', 'III': '3', 'IV': '4', 'V': '5', 'VI': '6', 'VII': '7', 'VIII': '8' };
const NOMBRES_SECCIONES: Record<string, string> = {
    'I': 'Sección Primera', 'II': 'Sección Segunda', 'III': 'Sección Tercera', 'IV': 'Sección Cuarta',
    'V': 'Sección Quinta', 'VI': 'Sección Sexta', 'VII': 'Sección Séptima', 'VIII': 'Sección Capital'
};
const MIN_ZOOM = 1;
const MAX_ZOOM = 5;
const TRANSLATE_EXTENT: [[number, number], [number, number]] = [[-100, -1000], [1100, 800]];
const INITIAL_POSITION = { center: [-60.5, -37.2] as PointTuple, zoom: MIN_ZOOM };


// --- Componente de Detalle ---
const DetalleSeccion = ({ seccion, categoriaId, onReset }: { seccion: SeccionGeography | null, categoriaId: number, onReset: () => void }) => {
    const seccionId = seccion ? ROMAN_TO_SECCION_ID[seccion.properties.seccion] : null;

    const { data: resultadosDetalle, isLoading, error } = useQuery<ResultadoDetalleSeccion[]>({
        queryKey: ['detalleSeccion', seccionId, categoriaId],
        queryFn: () => getDetalleSeccion(1,seccionId!, categoriaId),
        enabled: !!seccionId,
    });

    if (!seccion) {
        return (
        <div className="detalle-placeholder">
            <h3>Resultados por Sección</h3>
            <p>Haga clic en una sección del mapa para ver los resultados detallados.</p>
        </div>
        );
    }
    
    if (isLoading) return (<div className="detalle-loading"><div className="spinner"></div><p>Cargando resultados de la sección...</p></div>);
    if (error) return <div className="detalle-error">Error al cargar los datos de la sección.</div>;

    const nombreSeccionLegible = NOMBRES_SECCIONES[seccion.properties.seccion] || "Sección Desconocida";

    return (
        <div className="detalle-content">
        <button className="reset-button-panel" onClick={onReset}>← VOLVER</button>
        <h3>{nombreSeccionLegible}</h3>
        <ul className="resultados-lista">
            {resultadosDetalle?.map((r) => (
            <li key={r.id}>
                <div className="resultado-info">
                <span className="partido-nombre">{r.nombre}</span>
                <span className="partido-votos">{r.votos.toLocaleString('es-AR')} ({r.porcentaje.toFixed(2)}%)</span>
                </div>
                <div className="progress-bar">
                <div className="progress-fill" style={{ width: `${r.porcentaje}%`, backgroundColor: r.color || DEFAULT_MAP_COLOR }}></div>
                </div>
            </li>
            ))}
        </ul>
        </div>
    );
};

// --- Componente de Controles del Mapa ---
const ControlesMapa = ({ onReset }: { onReset: () => void }) => (
  <div className="map-controls">
    <button onClick={onReset}>← VOLVER</button>
  </div>
);

// --- Componente Principal ---
const MapaBsAsSecciones = () => {
  const [position, setPosition] = useState(INITIAL_POSITION);
  const [selectedCategoriaId, setSelectedCategoriaId] = useState<number>(6);
  const [clickedSeccion, setClickedSeccion] = useState<SeccionGeography | null>(null);
  const [tooltipContent, setTooltipContent] = useState('');
  const [isPanning, setIsPanning] = useState(false);

    const { data: geoData, isLoading: isLoadingGeo } = useQuery<any>({
        queryKey: ['mapaGeoDataSecciones'],
        queryFn: async () => (await axios.get(`${assetBaseUrl}/secciones-electorales-pba.topojson`)).data,
    });

    const { data: resultadosData, isLoading: isLoadingResultados } = useQuery<ResultadoMapaSeccion[]>({
        queryKey: ['mapaResultadosPorSeccion', selectedCategoriaId],
        queryFn: async () => (await axios.get(`${API_BASE_URL}/Resultados/mapa-por-seccion?categoriaId=${selectedCategoriaId}`)).data,
    });

    const { data: agrupacionesData, isLoading: isLoadingAgrupaciones } = useQuery<Agrupacion[]>({
        queryKey: ['catalogoAgrupaciones'],
        queryFn: async () => (await axios.get(`${API_BASE_URL}/Catalogos/agrupaciones`)).data,
    });

    const { nombresAgrupaciones, resultadosPorSeccionRomana } = useMemo<{
        nombresAgrupaciones: Map<string, string>;
        resultadosPorSeccionRomana: Map<string, ResultadoMapaSeccion>;
    }>((
    ) => {
        const nombresMap = new Map<string, string>();
        const resultadosMap = new Map<string, ResultadoMapaSeccion>();

        if (agrupacionesData) {
        agrupacionesData.forEach(a => nombresMap.set(a.id, a.nombre));
        }
        if (resultadosData) {
        resultadosData.forEach(r => {
            const roman = SECCION_ID_TO_ROMAN[r.seccionId];
            if (roman) resultadosMap.set(roman, r);
        });
        }
        return { nombresAgrupaciones: nombresMap, resultadosPorSeccionRomana: resultadosMap };
    }, [agrupacionesData, resultadosData]);

  const isLoading = isLoadingGeo || isLoadingResultados || isLoadingAgrupaciones;

    const handleReset = useCallback(() => {
        setClickedSeccion(null);
        setPosition(INITIAL_POSITION);
    }, []);

    const handleGeographyClick = useCallback((geo: SeccionGeography) => {
        if (clickedSeccion?.rsmKey === geo.rsmKey) {
        handleReset();
        } else {
        const centroid = geoCentroid(geo as any) as PointTuple;
        setPosition({ center: centroid, zoom: 2 });
        setClickedSeccion(geo);
        }
    }, [clickedSeccion, handleReset]);

    const handleMoveEnd = (newPosition: { coordinates: PointTuple; zoom: number }) => {
        if (newPosition.zoom <= MIN_ZOOM) {
        if (position.zoom > MIN_ZOOM || clickedSeccion !== null) {
            handleReset();
        }
        return;
        }
        if (newPosition.zoom < position.zoom && clickedSeccion !== null) {
        setClickedSeccion(null);
        }
        setPosition({ center: newPosition.coordinates, zoom: newPosition.zoom });
    };

    useEffect(() => {
        const handleKeyDown = (e: KeyboardEvent) => e.key === 'Escape' && handleReset();
        window.addEventListener('keydown', handleKeyDown);
        return () => window.removeEventListener('keydown', handleKeyDown);
    }, [handleReset]);

    const getSectionFillColor = (seccionRomana: string) => {
        return resultadosPorSeccionRomana.get(seccionRomana)?.colorGanador || DEFAULT_MAP_COLOR;
    };

    const handleZoomIn = () => {
        if (position.zoom < MAX_ZOOM) {
        setPosition(p => ({ ...p, zoom: Math.min(p.zoom * 1.5, MAX_ZOOM) }));
        }
    };


  return (
    <div className="mapa-wrapper">
      <div className="mapa-container">
        {isLoading ? <div className="spinner"></div> : (
          <ComposableMap
            key={selectedCategoriaId}
            projection="geoMercator"
            projectionConfig={{ scale: 4400, center: [-60.5, -37.2] }}
            className="rsm-svg"
            data-tooltip-id="seccion-tooltip"
          >
            <ZoomableGroup
              center={position.center}
              zoom={position.zoom}
              onMoveEnd={(newPosition: { coordinates: PointTuple; zoom: number }) => {
                setIsPanning(false);
                handleMoveEnd(newPosition);
              }}
              minZoom={MIN_ZOOM}
              maxZoom={MAX_ZOOM}
              translateExtent={TRANSLATE_EXTENT}
              className={isPanning ? 'panning' : ''}
              onMoveStart={() => setIsPanning(true)}
              filterZoomEvent={(e: WheelEvent) => {
                if (e.deltaY > 0) {
                  handleReset();
                } else if (e.deltaY < 0) {
                  handleZoomIn();
                }
                return true;
              }}
            >
              {geoData && (
                <Geographies geography={geoData}>
                  {({ geographies }: { geographies: SeccionGeography[] }) =>
                    geographies.map((geo) => {
                      const seccionRomana = geo.properties.seccion;
                      const resultado = resultadosPorSeccionRomana.get(seccionRomana);
                      const nombreGanador = resultado?.agrupacionGanadoraId ? nombresAgrupaciones.get(resultado.agrupacionGanadoraId) : 'Sin datos';
                      const isSelected = clickedSeccion?.rsmKey === geo.rsmKey;
                      const isFaded = clickedSeccion && !isSelected;
                      const isClickable = !!resultado;

                      return (
                        <Geography
                          key={geo.rsmKey + (isSelected ? '-selected' : '')}
                          geography={geo as any}
                          data-tooltip-id="seccion-tooltip"
                          onClick={isClickable ? () => handleGeographyClick(geo) : undefined}
                          onMouseEnter={() => {
                            if (isClickable) {
                              const nombreSeccionLegible = NOMBRES_SECCIONES[geo.properties.seccion] || "Sección Desconocida";
                              setTooltipContent(`${nombreSeccionLegible}: ${nombreGanador}`);
                            }
                          }}
                          onMouseLeave={() => setTooltipContent("")}
                          className={`rsm-geography ${isSelected ? 'selected' : ''} ${isFaded ? 'faded' : ''} ${!isClickable ? 'no-results' : ''}`}
                          fill={getSectionFillColor(seccionRomana)}
                        />
                      );
                    })
                  }
                </Geographies>
              )}
            </ZoomableGroup>
          </ComposableMap>
        )}
        {clickedSeccion && <ControlesMapa onReset={handleReset} />}
        <Tooltip id="seccion-tooltip" content={tooltipContent} />
      </div>
      <div className="info-panel">
        <div className="mapa-categoria-selector">
          <select
            className="mapa-categoria-combobox"
            value={selectedCategoriaId}
            onChange={(e) => {
              setSelectedCategoriaId(Number(e.target.value));
              handleReset();
            }}
          >
            {CATEGORIAS.map(cat => (
              <option key={cat.id} value={cat.id}>
                {cat.nombre}
              </option>
            ))}
          </select>
        </div>
        <DetalleSeccion seccion={clickedSeccion} categoriaId={selectedCategoriaId} onReset={handleReset} />
        <LegendSecciones resultados={resultadosPorSeccionRomana} nombresAgrupaciones={nombresAgrupaciones} />
      </div>
    </div>
  );
};

// --- Sub-componente para la Leyenda (sin cambios) ---
const LegendSecciones = ({ resultados, nombresAgrupaciones }: { resultados: Map<string, ResultadoMapaSeccion>, nombresAgrupaciones: Map<string, string> }) => {
    const legendItems = useMemo(() => {
        const ganadoresUnicos = new Map<string, { nombre: string; color: string }>();
        resultados.forEach(resultado => {
        if (resultado.agrupacionGanadoraId && resultado.colorGanador && !ganadoresUnicos.has(resultado.agrupacionGanadoraId)) {
            ganadoresUnicos.set(resultado.agrupacionGanadoraId, {
            nombre: nombresAgrupaciones.get(resultado.agrupacionGanadoraId) || 'Desconocido',
            color: resultado.colorGanador
            });
        }
        });
        return Array.from(ganadoresUnicos.values());
    }, [resultados, nombresAgrupaciones]);

    return (
        <div className="legend">
        <h4>Leyenda de Ganadores</h4>
        {legendItems.map(item => (
            <div key={item.nombre} className="legend-item">
            <div className="legend-color-box" style={{ backgroundColor: item.color }} />
            <span>{item.nombre}</span>
            </div>
        ))}
        </div>
    );
};

export default MapaBsAsSecciones;