import { useEffect, useRef } from 'react';
import OLMapClass from 'ol/Map';
import View from 'ol/View';
import TileLayer from 'ol/layer/Tile';
import VectorLayer from 'ol/layer/Vector';
import VectorSource from 'ol/source/Vector';
import GeoJSON from 'ol/format/GeoJSON';
import OSM from 'ol/source/OSM';
import { fromLonLat } from 'ol/proj';
import { Style, Circle as CircleStyle, Fill, Stroke } from 'ol/style';
import type { FeatureLike } from 'ol/Feature';
import type { GeoJSONCollection } from '@/Pages/Map';
import 'ol/ol.css';

const COLOR: Record<string, string> = {
    'dossiers/Chantiers':       '#2d7a70',
    'dossiers/Projets':         '#5aacaa',
    'dossiers/Stations':        '#1b5c54',
    'dossiers/Autres':          '#7a9290',
    'annuaire/IR':              '#4a90d9',
    'annuaire/TP':              '#1a6fb5',
    'annuaire/Fournisseurs':    '#e8943a',
    'annuaire/Prescripteurs':   '#9b59b6',
    'annuaire/Autres':          '#7f8c8d',
    'spancs/SPANCS':            '#27ae60',
    'depanneurs/Dépanneurs':    '#e74c3c',
};

function pinStyle(feature: FeatureLike): Style {
    const key   = `${feature.get('famille')}/${feature.get('type')}`;
    const color = COLOR[key] ?? '#2d7a70';
    return new Style({
        image: new CircleStyle({
            radius: 5,
            fill:   new Fill({ color }),
            stroke: new Stroke({ color: 'rgba(255,255,255,0.6)', width: 1 }),
        }),
    });
}

interface Props {
    features?: GeoJSONCollection | null;
    onFeatureClick?: (id: number, famille: 'dossiers' | 'annuaire' | 'spancs' | 'depanneurs', type: string) => void;
}

export default function OLMap({ features, onFeatureClick }: Props) {
    const containerRef    = useRef<HTMLDivElement>(null);
    const mapRef          = useRef<OLMapClass | null>(null);
    const vectorSourceRef = useRef<VectorSource | null>(null);
    const clickCbRef      = useRef(onFeatureClick);
    clickCbRef.current = onFeatureClick;

    // Init map once
    useEffect(() => {
        if (!containerRef.current || mapRef.current) return;

        const vectorSource = new VectorSource();
        vectorSourceRef.current = vectorSource;

        const map = new OLMapClass({
            target: containerRef.current,
            layers: [
                new TileLayer({ source: new OSM() }),
                new VectorLayer({ source: vectorSource, style: pinStyle }),
            ],
            view: new View({
                center: fromLonLat([2.3522, 46.8534]),
                zoom: 6,
            }),
        });

        map.on('click', e => {
            map.forEachFeatureAtPixel(e.pixel, (feature: FeatureLike) => {
                const id      = feature.get('id') as number;
                const famille = feature.get('famille') as 'dossiers' | 'annuaire' | 'spancs' | 'depanneurs';
                const type    = feature.get('type') as string;
                clickCbRef.current?.(id, famille, type);
                return true;
            });
        });

        map.on('pointermove', e => {
            const hit = map.hasFeatureAtPixel(e.pixel);
            map.getTargetElement().style.cursor = hit ? 'pointer' : '';
        });

        mapRef.current = map;

        return () => {
            mapRef.current?.setTarget(undefined);
            mapRef.current          = null;
            vectorSourceRef.current = null;
        };
    }, []);

    // Update pins whenever features change
    useEffect(() => {
        const src = vectorSourceRef.current;
        if (!src) return;

        src.clear();
        if (features?.features?.length) {
            const olFeatures = new GeoJSON().readFeatures(features, {
                featureProjection: 'EPSG:3857',
            });
            src.addFeatures(olFeatures);
        }
    }, [features]);

    return <div ref={containerRef} className="absolute inset-0" />;
}
