"use client";

import { Box, Badge, Flex, Text } from "@chakra-ui/react";
import { MapContainer, TileLayer, Marker, Popup, useMap } from "react-leaflet";
import L, { DivIcon, LatLngBoundsLiteral } from "leaflet";
import "leaflet/dist/leaflet.css";
import "leaflet.markercluster/dist/MarkerCluster.css";
import "leaflet.markercluster/dist/MarkerCluster.Default.css";
import MarkerClusterGroup from "react-leaflet-markercluster";
import { useEffect, useMemo } from "react";

export type Company = {
    id: string;
    name: string;
    industry: "Tech" | "Retail" | "Manufacturing" | "Food" | "Healthcare";
    lat: number;
    lng: number;
    address?: string;
};

type Props = {
    companies: Company[];
    selectedId?: string | null;
    onSelect?: (id: string) => void;
    autoFit?: boolean;
};

const industryEmoji: Record<Company["industry"], string> = {
    Tech: "💻",
    Retail: "🛒",
    Manufacturing: "🏭",
    Food: "🍽️",
    Healthcare: "🏥",
};

const industryColor: Record<Company["industry"], string> = {
    Tech: "#3b82f6",
    Retail: "#f59e0b",
    Manufacturing: "#6b7280",
    Food: "#10b981",
    Healthcare: "#ef4444",
};

function makeIcon(industry: Company["industry"], highlighted: boolean): DivIcon {
    const size = highlighted ? 40 : 32;
    const color = industryColor[industry];
    const emoji = industryEmoji[industry];
    const border = highlighted ? `3px solid ${color}` : `2px solid ${color}`;
    return L.divIcon({
        className: "company-div-icon",
        html: `
      <div style="
        width:${size}px;height:${size}px;border-radius:50%;
        display:flex;align-items:center;justify-content:center;
        background:#fff;border:${border};
        box-shadow:0 2px 8px rgba(0,0,0,.15);
        font-size:${Math.round(size * 0.55)}px;
      ">${emoji}</div>
    `,
        iconSize: [size, size],
        iconAnchor: [size / 2, size / 2],
        popupAnchor: [0, -size / 2],
    });
}

function FlyTo({ lat, lng }: { lat: number; lng: number }) {
    const map = useMap();
    useEffect(() => {
        map.flyTo([lat, lng], Math.max(map.getZoom(), 13), { duration: 0.7 });
    }, [lat, lng, map]);
    return null;
}

function FitBoundsOnData({ points }: { points: { lat: number; lng: number }[] }) {
    const map = useMap();
    useEffect(() => {
        if (!points?.length) return;
        let bounds: LatLngBoundsLiteral = [
            [points[0].lat, points[0].lng],
            [points[0].lat, points[0].lng],
        ];
        for (const p of points) {
            bounds = L.latLngBounds(bounds).extend([p.lat, p.lng]) as any;
        }
        map.fitBounds(bounds, { padding: [30, 30] });
    }, [points, map]);
    return null;
}

export default function CompanyMap({ companies, selectedId, onSelect, autoFit = true }: Props) {
    const selected = useMemo(
        () => companies.find((c) => c.id === selectedId),
        [companies, selectedId]
    );

    const center = useMemo<[number, number]>(() => {
        if (!companies.length) return [46.0569, 14.5058]; // Ljubljana fallback
        const lat = companies.reduce((a, c) => a + c.lat, 0) / companies.length;
        const lng = companies.reduce((a, c) => a + c.lng, 0) / companies.length;
        return [lat, lng];
    }, [companies]);

    return (
        <Box w="100%" h="100%" borderRadius="2xl" overflow="hidden" bg="white">
            <MapContainer
                center={center}
                zoom={6}
                style={{ width: "100%", height: "100%" }}
                preferCanvas
            >
                <TileLayer
                    attribution="&copy; OpenStreetMap"
                    url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
                />

                <MarkerClusterGroup chunkedLoading>
                    {companies.map((c) => (
                        <Marker
                            key={c.id}
                            position={[c.lat, c.lng]}
                            icon={makeIcon(c.industry, c.id === selectedId)}
                            eventHandlers={{
                                click: () => onSelect?.(c.id),
                                mouseover: (e) => e.target.openPopup(),
                            }}
                        >
                            <Popup>
                                <Flex direction="column" gap={1}>
                                    <Text fontWeight="bold">{c.name}</Text>
                                    <Badge
                                        w="fit-content"
                                        colorScheme="gray"
                                        style={{ background: industryColor[c.industry], color: "#fff" }}
                                    >
                                        {c.industry}
                                    </Badge>
                                    {c.address && <Text fontSize="sm">{c.address}</Text>}
                                </Flex>
                            </Popup>
                        </Marker>
                    ))}
                </MarkerClusterGroup>

                {autoFit && companies.length > 0 && !selected && (
                    <FitBoundsOnData points={companies.map(({ lat, lng }) => ({ lat, lng }))} />
                )}
                {selected && <FlyTo lat={selected.lat} lng={selected.lng} />}
            </MapContainer>
        </Box>
    );
}
