// src/components/MapaBsAs.tsx
import { useState, useMemo } from 'react';
import { ComposableMap, Geographies, Geography } from 'react-simple-maps';
import { Tooltip } from 'react-tooltip';
import { useQuery } from '@tanstack/react-query';
import axios from 'axios';
import type { Feature, Geometry } from 'geojson';
import { geoCentroid } from 'd3-geo'; // Para calcular el centro de cada partido
import { useSpring, animated } from 'react-spring'; // Para animar el zoom

//import geoUrl from '/partidos-bsas.topojson';
import './MapaBsAs.css';

// --- Interfaces y Tipos ---
interface ResultadoMapa {
  partidoId: string;
  agrupacionGanadoraId: string;
  porcentajeGanador: number; // Nueva propiedad desde el backend
}

interface Agrupacion {
  id: string;
  nombre: string;
}

interface PartidoProperties {
  id: number;
  departamento: string;
  cabecera: string; // Asegúrate de que coincida con tu topojson
  provincia: string;
}

type PartidoGeography = Feature<Geometry, PartidoProperties> & { rsmKey: string };

const PALETA_COLORES: { [key: string]: [number, number, number] } = {
  'default': [214, 214, 218] // RGB para el color por defecto
};

const INITIAL_PROJECTION = {
  center: [-59.8, -37.0] as [number, number],
  scale: 5400,
};

const MapaBsAs = () => {
  const [selectedPartido, setSelectedPartido] = useState<PartidoGeography | null>(null);
  const [projectionConfig, setProjectionConfig] = useState(INITIAL_PROJECTION);

  // --- Carga de Datos ---
  const { data: resultadosData, isLoading: isLoadingResultados } = useQuery<ResultadoMapa[]>({
    queryKey: ['mapaResultados'],
    queryFn: async () => {
      const { data } = await axios.get('http://localhost:5217/api/Resultados/mapa');
      return data;
    },
  });

  const { data: geoData, isLoading: isLoadingGeo } = useQuery({
    queryKey: ['mapaGeoData'],
    queryFn: async () => {
      const { data } = await axios.get('/partidos-bsas.topojson'); 
      return data;
    },
  });

  const { data: agrupacionesData, isLoading: isLoadingAgrupaciones } = useQuery<Agrupacion[]>({
    queryKey: ['catalogoAgrupaciones'],
    queryFn: async () => {
      const { data } = await axios.get('http://localhost:5217/api/Catalogos/agrupaciones');
      return data;
    },
  });

  const { nombresAgrupaciones, coloresPartidos } = useMemo(() => {
    if (!agrupacionesData) return { nombresAgrupaciones: {}, coloresPartidos: {} };

    const nombres = agrupacionesData.reduce((acc, agrupacion) => {
      acc[agrupacion.id] = agrupacion.nombre;
      return acc;
    }, {} as { [key: string]: string });

    const colores = agrupacionesData.reduce((acc, agrupacion, index) => {
      const baseColor = [255, 87, 51, 51, 255, 87, 51, 87, 255, 255, 51, 161, 161, 51, 255, 255, 195, 0, 199, 0, 57, 144, 12, 63, 88, 24, 69];
      acc[agrupacion.nombre] = [baseColor[index*3], baseColor[index*3+1], baseColor[index*3+2]];
      return acc;
    }, {} as { [key: string]: [number, number, number] });
    
    colores['default'] = [214, 214, 218];
    return { nombresAgrupaciones: nombres, coloresPartidos: colores };
  }, [agrupacionesData]);

  const animatedProps = useSpring({
    to: { scale: projectionConfig.scale, cx: projectionConfig.center[0], cy: projectionConfig.center[1] },
    config: { tension: 170, friction: 26 },
  });

  if (isLoadingResultados || isLoadingGeo || isLoadingAgrupaciones) {
    return <div>Cargando datos del mapa...</div>;
  }

  const getPartyStyle = (partidoIdGeo: string) => {
    const resultado = resultadosData?.find(r => r.partidoId === partidoIdGeo);
    if (!resultado) {
      return { fill: `rgb(${PALETA_COLORES.default.join(',')})` };
    }
    const nombreAgrupacion = nombresAgrupaciones[resultado.agrupacionGanadoraId] || 'Otro';
    const baseColor = coloresPartidos[nombreAgrupacion] || PALETA_COLORES.default;
    
    // Calcula la opacidad basada en el porcentaje. 0.4 (débil) a 1.0 (fuerte)
    const opacity = 0.4 + (resultado.porcentajeGanador / 100) * 0.6;
    
    return { fill: `rgba(${baseColor.join(',')}, ${opacity})` };
  };

  const handleGeographyClick = (geo: PartidoGeography) => {
    const centroid = geoCentroid(geo);
    setSelectedPartido(geo);
    setProjectionConfig({
      center: centroid,
      scale: 18000, // Zoom más cercano
    });
  };

  const handleReset = () => {
    setSelectedPartido(null);
    setProjectionConfig(INITIAL_PROJECTION);
  };
  
  return (
    <div className="mapa-wrapper">
      <div className="mapa-container">
        <animated.div style={{
          width: '100%',
          height: '100%',
          transform: animatedProps.scale.to(s => `scale(${s / INITIAL_PROJECTION.scale})`),
        }}>
          <ComposableMap
            projection="geoMercator"
            projectionConfig={{
              scale: animatedProps.scale,
              center: [animatedProps.cx, animatedProps.cy],
            }}
            className="rsm-svg"
          >
            <Geographies geography={geoData}>
              {({ geographies }: { geographies: PartidoGeography[] }) =>
                geographies.map((geo) => {
                  const partidoId = String(geo.properties.id);
                  const partidoNombre = geo.properties.departamento;
                  const resultado = resultadosData?.find(r => r.partidoId === partidoId);
                  const agrupacionNombre = resultado ? (nombresAgrupaciones[resultado.agrupacionGanadoraId] || 'Desconocido') : 'Sin datos';

                  return (
                    <Geography
                      key={geo.rsmKey}
                      geography={geo}
                      data-tooltip-id="partido-tooltip"
                      data-tooltip-content={`${partidoNombre}: ${agrupacionNombre}`}
                      fill={getPartyStyle(partidoId).fill}
                      stroke="#FFF"
                      className="rsm-geography"
                      style={{
                        default: { outline: 'none' },
                        hover: { outline: 'none', stroke: '#FF5722', strokeWidth: 2, fill: getPartyStyle(partidoId).fill },
                        pressed: { outline: 'none' },
                      }}
                      onClick={() => handleGeographyClick(geo)}
                    />
                  );
                })
              }
            </Geographies>
          </ComposableMap>
        </animated.div>
        <Tooltip id="partido-tooltip" />
      </div>

      <div className="info-panel">
        <button onClick={handleReset}>Resetear Vista</button>
        {selectedPartido ? (
          <div>
            <h3>{selectedPartido.properties.departamento}</h3>
            <p><strong>Cabecera:</strong> {selectedPartido.properties.cabecera}</p>
            <p><strong>ID:</strong> {selectedPartido.properties.id}</p>
            {/* Aquí mostrarías más datos del partido seleccionado */}
          </div>
        ) : (
          <div>
            <h3>Provincia de Buenos Aires</h3>
            <p>Selecciona un partido para ver más detalles.</p>
          </div>
        )}
        <Legend colores={coloresPartidos} />
      </div>
    </div>
  );
};


// Componente de Leyenda separado
const Legend = ({ colores }: { colores: { [key: string]: [number, number, number] } }) => {
    return (
        <div className="legend">
            <h4>Leyenda</h4>
            {Object.entries(colores).map(([nombre, color]) => {
                if (nombre === 'default') return null;
                return (
                    <div key={nombre} className="legend-item">
                        <div className="legend-color-box" style={{ backgroundColor: `rgb(${color.join(',')})` }} />
                        <span>{nombre}</span>
                    </div>
                );
            })}
        </div>
    );
};

export default MapaBsAs;