import { useAuth } from "@/_core/hooks/useAuth";
import { DirectionsMenu } from "@/components/DirectionsMenu";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Badge } from "@/components/ui/badge";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Slider } from "@/components/ui/slider";
import { buildMaterialReturnFinalPdfViewerHref } from "@/lib/materialReturnFinalPdf";
import { buildRoutePrefetchHandlers } from "@/lib/routePrefetch";
import { trpc } from "@/lib/trpc";
import { useViewportFlags } from "@/hooks/useMobile";
import { cn } from "@/lib/utils";
import { associationCommuneOptions, getAssociationCommuneLabel, type AssociationCommuneFilter } from "@shared/associationCommunes";
import { associationThematicOptions, getAssociationThematicLabel, getAssociationThematicLabels, type AssociationThematic } from "@shared/associationThematics";
import { ArrowLeft, Building2, ChevronDown, Filter, Loader2, MapPinned, PackageCheck, Search } from "lucide-react";
import { Suspense, lazy, useEffect, useMemo, useState } from "react";
import { Link } from "wouter";
import { toast } from "sonner";

const AssociationPublicMap = lazy(() => import("@/components/AssociationPublicMap.lazy"));

function MapPanelLoader() {
  return (
    <div className="flex min-h-[620px] items-center justify-center rounded-lg border bg-background">
      <Loader2 className="h-6 w-6 animate-spin text-primary" />
    </div>
  );
}

function getModeMeta(mode: "annuaire" | "densite" | "logistique") {
  if (mode === "densite") {
    return {
      title: "Densité d’implantation",
      description: "Lecture territoriale des zones où la présence associative est la plus forte.",
      accentClassName: "border-amber-200 bg-amber-50 text-amber-800",
    };
  }
  if (mode === "logistique") {
    return {
      title: "Flux logistique",
      description: "Pilotage des missions matérielles, usages à venir et points de vigilance.",
      accentClassName: "border-rose-200 bg-rose-50 text-rose-800",
    };
  }
  return {
    title: "Annuaire géographique",
    description: "Lecture simple du tissu associatif, commune par commune, avec accès direct aux fiches.",
    accentClassName: "border-emerald-200 bg-emerald-50 text-emerald-800",
  };
}

type LogisticsMapEvent = {
  requestId: number;
  title: string;
  associationName: string;
  commune: string;
  manifestationStart: string;
  manifestationEnd: string;
  pickupDate: string;
  restitutionDate: string;
  useStartDate: string;
  useEndDate: string;
  requestedItems: Array<{
    key: string;
    label: string;
    quantity: number;
    granted: boolean;
    requested: boolean;
    extra: string;
  }>;
  boardState: string;
  boardStateLabel: string;
  logisticServiceLabel: string;
  issueFlag: boolean;
  finalPdfUrl: string | null;
  uploadLink: string | null;
};

function haversineDistanceKm(a: { latitude: number; longitude: number }, b: { latitude: number; longitude: number }) {
  const toRad = (value: number) => (value * Math.PI) / 180;
  const earthRadiusKm = 6371;
  const deltaLat = toRad(b.latitude - a.latitude);
  const deltaLng = toRad(b.longitude - a.longitude);
  const lat1 = toRad(a.latitude);
  const lat2 = toRad(b.latitude);

  const hav =
    Math.sin(deltaLat / 2) ** 2 +
    Math.cos(lat1) * Math.cos(lat2) * Math.sin(deltaLng / 2) ** 2;

  return 2 * earthRadiusKm * Math.asin(Math.sqrt(hav));
}

function handleInteractiveCardKeyDown(event: React.KeyboardEvent<HTMLElement>, onActivate: () => void) {
  if (event.key !== "Enter" && event.key !== " ") {
    return;
  }
  event.preventDefault();
  onActivate();
}

export default function AssociationMapPublic() {
  const { isAuthenticated, user } = useAuth();
  const { isMobile, isTablet } = useViewportFlags();
  const isAdmin = user?.role === "admin" || user?.role === "super_admin";
  const [search, setSearch] = useState("");
  const [communeFilter, setCommuneFilter] = useState<AssociationCommuneFilter>("all");
  const [thematiqueFilter, setThematiqueFilter] = useState<AssociationThematic | "all">("all");
  const [mapMode, setMapMode] = useState<"annuaire" | "densite" | "logistique">("annuaire");
  const [selectedAssociationId, setSelectedAssociationId] = useState<number | null>(null);
  const [selectedLogisticsRequestId, setSelectedLogisticsRequestId] = useState<number | null>(null);
  const [radiusEnabled, setRadiusEnabled] = useState(false);
  const [radiusKm, setRadiusKm] = useState(5);
  const [userPosition, setUserPosition] = useState<{ latitude: number; longitude: number } | null>(null);
  const [geolocating, setGeolocating] = useState(false);
  const [logisticsFilter, setLogisticsFilter] = useState<"actifs" | "avenir" | "tous">("actifs");
  const [mobilePanel, setMobilePanel] = useState<"map" | "list">("map");
  const [showMobileFilters, setShowMobileFilters] = useState(false);

  const { data, isLoading } = trpc.associationDirectory.listMap.useQuery({
    search: search || undefined,
    commune: communeFilter,
    thematique: thematiqueFilter,
    registrationStatus: "all",
    limit: 500,
  });

  const materialCalendarQuery = trpc.request.getMaterialCalendar.useQuery(undefined, {
    enabled: isAdmin,
  });
  const { data: associationMapSettings } = trpc.settings.getAssociationMap.useQuery();

  useEffect(() => {
    if (mapMode === "logistique" && !isAdmin) {
      setMapMode("annuaire");
    }
  }, [isAdmin, mapMode]);

  const requestUserLocation = () => {
    if (!navigator.geolocation) {
      toast.error("La géolocalisation n'est pas disponible sur cet appareil.");
      return;
    }

    setGeolocating(true);
    navigator.geolocation.getCurrentPosition(
      (position) => {
        setUserPosition({
          latitude: position.coords.latitude,
          longitude: position.coords.longitude,
        });
        setRadiusEnabled(true);
        setGeolocating(false);
      },
      () => {
        toast.error("Impossible de récupérer la position. La carte reste utilisable sans ce filtre.");
        setGeolocating(false);
      },
      {
        enableHighAccuracy: true,
        timeout: 5000,
      }
    );
  };

  const radiusFilteredAssociations = useMemo(() => {
    const entries = data?.data || [];
    if (!radiusEnabled || !userPosition) return entries;

    return entries.filter((entry) => {
      if (entry.latitude === null || entry.longitude === null) return false;
      return haversineDistanceKm(userPosition, {
        latitude: entry.latitude,
        longitude: entry.longitude,
      }) <= radiusKm;
    });
  }, [data?.data, radiusEnabled, radiusKm, userPosition]);

  const logisticsEvents = useMemo<LogisticsMapEvent[]>(() => {
    if (!isAdmin) return [];

    const allEvents: LogisticsMapEvent[] = (materialCalendarQuery.data?.events || []).flatMap((event) => {
      if (typeof event.requestId !== "number") {
        return [];
      }

      return [{
          requestId: event.requestId,
          title: event.title,
          associationName: event.associationName,
          commune: event.commune,
          manifestationStart: event.manifestationStart,
          manifestationEnd: event.manifestationEnd,
          pickupDate: event.pickupDate,
          restitutionDate: event.restitutionDate,
          useStartDate: event.useStartDate,
          useEndDate: event.useEndDate,
          requestedItems: event.requestedItems,
          boardState: event.boardState,
          boardStateLabel: event.boardStateLabel,
          logisticServiceLabel: event.logisticServiceLabel,
          issueFlag: event.issueFlag,
          finalPdfUrl: event.finalPdfUrl,
          uploadLink: event.uploadLink,
        }];
      });
    const today = new Date().toISOString().slice(0, 10);

    return allEvents.filter((event) => {
      if (communeFilter !== "all" && event.commune?.toLowerCase() !== communeFilter.toLowerCase()) {
        return false;
      }

      if (search) {
        const haystack = `${event.associationName} ${event.title} ${event.commune} ${event.requestedItems.map((item: any) => item.label).join(" ")}`.toLowerCase();
        if (!haystack.includes(search.toLowerCase())) {
          return false;
        }
      }

      if (logisticsFilter === "tous") return true;
      const start = String(event.useStartDate || "").slice(0, 10);
      const end = String(event.useEndDate || start).slice(0, 10);
      const active = start && end && start <= today && today <= end;
      if (logisticsFilter === "actifs") return active;
      if (logisticsFilter === "avenir") return start > today;
      return true;
    });
  }, [communeFilter, isAdmin, logisticsFilter, materialCalendarQuery.data?.events, search]);

  const selectedAssociation = useMemo(
    () => radiusFilteredAssociations.find((item) => item.id === selectedAssociationId) || null,
    [radiusFilteredAssociations, selectedAssociationId]
  );

  const selectedLogistics = useMemo(
    () => logisticsEvents.find((event) => event.requestId === selectedLogisticsRequestId) || null,
    [logisticsEvents, selectedLogisticsRequestId]
  );

  const logisticsDirectionsByRequestId = useMemo(() => {
    const associationLookup = new Map<string, { latitude: number; longitude: number }>();
    (data?.data || []).forEach((entry) => {
      if (entry.latitude === null || entry.longitude === null) return;
      const baseKey = entry.nomAssociation.trim().toLowerCase();
      associationLookup.set(baseKey, { latitude: entry.latitude, longitude: entry.longitude });
      if (entry.ville) {
        associationLookup.set(`${baseKey}::${entry.ville.trim().toLowerCase()}`, {
          latitude: entry.latitude,
          longitude: entry.longitude,
        });
      }
    });

    const directionsByRequestId = new Map<number, { latitude?: number | null; longitude?: number | null; destinationLabel: string }>();
    logisticsEvents.forEach((event) => {
      const associationNameKey = event.associationName.trim().toLowerCase();
      const communeKey = event.commune?.trim().toLowerCase();
      const matchedCoordinates = (communeKey && associationLookup.get(`${associationNameKey}::${communeKey}`))
        || associationLookup.get(associationNameKey);
      directionsByRequestId.set(event.requestId, {
        latitude: matchedCoordinates?.latitude,
        longitude: matchedCoordinates?.longitude,
        destinationLabel: [event.associationName, event.commune || "Guyane"].filter(Boolean).join(", "),
      });
    });

    return directionsByRequestId;
  }, [data?.data, logisticsEvents]);

  const densitySummary = useMemo(() => {
    const grouped = new Map<string, number>();
    radiusFilteredAssociations.forEach((entry) => {
      const key = entry.ville || "Commune non renseignée";
      grouped.set(key, (grouped.get(key) || 0) + 1);
    });
    return Array.from(grouped.entries())
      .map(([ville, count]) => ({ ville, count }))
      .sort((a, b) => b.count - a.count);
  }, [radiusFilteredAssociations]);

  const backHref = isAuthenticated ? "/dashboard/associations" : "/associations";
  const visibleCount = mapMode === "logistique" ? logisticsEvents.length : radiusFilteredAssociations.length;
  const modeMeta = getModeMeta(mapMode);
  const publicNavItems = [
    { href: "/associations", label: "Annuaire", active: false },
    { href: "/associations/carte", label: "Carte publique", active: true },
  ];
  const activateAssociation = (id: number) => {
    setSelectedAssociationId(id);
    setSelectedLogisticsRequestId(null);
  };
  const activateLogistics = (requestId: number | null) => {
    setSelectedLogisticsRequestId(requestId);
    setSelectedAssociationId(null);
  };
  const resultsPanelContent = (
    <>
      {(isLoading || (mapMode === "logistique" && materialCalendarQuery.isLoading)) ? (
        <p className="text-sm text-muted-foreground">Chargement de la carte...</p>
      ) : mapMode === "annuaire" ? (
        radiusFilteredAssociations.length > 0 ? (
          radiusFilteredAssociations.map((entry) => (
            <div
              key={entry.id}
              role="button"
              tabIndex={0}
              onClick={() => activateAssociation(entry.id)}
              onKeyDown={(event) => handleInteractiveCardKeyDown(event, () => activateAssociation(entry.id))}
              className={`w-full rounded-xl border p-3 text-left transition-colors sm:rounded-2xl sm:p-4 ${selectedAssociation?.id === entry.id ? "border-primary bg-primary/5 shadow-sm" : "border-slate-200 hover:bg-muted/40"}`}
            >
              <div className="flex items-start justify-between gap-3">
                <div>
                  <p className="line-clamp-2 text-sm font-medium sm:text-base">{entry.nomAssociation}</p>
                  <p className="text-sm text-muted-foreground">{entry.ville || "Commune non renseignée"}</p>
                  {entry.thematiques?.length ? (
                    <p className="line-clamp-2 text-xs text-primary sm:text-sm">{getAssociationThematicLabels(entry.thematiques).join(" • ")}</p>
                  ) : null}
                </div>
                <Badge variant="outline">{entry.registered ? "Inscrite" : "Référencée"}</Badge>
              </div>
              {entry.objetAssociation ? (
                <p className="mt-2 line-clamp-2 text-sm text-muted-foreground sm:line-clamp-3">{entry.objetAssociation}</p>
              ) : null}
              <div className="mt-3">
                <div className="flex flex-col gap-2 sm:flex-row sm:flex-wrap">
                  <Link href={entry.publicUrl} {...buildRoutePrefetchHandlers(entry.publicUrl)}>
                    <Button asChild type="button" size="sm" variant="outline" className="min-h-10 w-full sm:w-auto">
                      <span>
                        <Building2 className="mr-2 h-4 w-4" />
                        Voir la fiche
                      </span>
                    </Button>
                  </Link>
                  <DirectionsMenu
                    latitude={entry.latitude}
                    longitude={entry.longitude}
                    destinationLabel={[entry.nomAssociation, entry.ville || "Guyane"].filter(Boolean).join(", ")}
                    label="Ouvrir avec"
                    usageContext="public"
                    className="min-h-10 w-full sm:w-auto"
                  />
                </div>
              </div>
            </div>
          ))
        ) : (
          <div className="rounded-2xl border border-dashed p-4 text-sm text-muted-foreground">
            Aucune association géolocalisée ne correspond à cette recherche.
          </div>
        )
      ) : mapMode === "densite" ? (
        densitySummary.length > 0 ? (
          densitySummary.map((entry) => (
            <div key={entry.ville} className="rounded-2xl border border-slate-200 p-4">
              <div className="flex items-center justify-between gap-3">
                <p className="font-medium">{entry.ville}</p>
                <Badge>{entry.count} association(s)</Badge>
              </div>
            </div>
          ))
        ) : (
          <div className="rounded-lg border border-dashed p-4 text-sm text-muted-foreground">
            Aucune commune ne remonte dans ce filtre.
          </div>
        )
      ) : logisticsEvents.length > 0 ? (
        logisticsEvents.map((event) => (
          <div
            key={event.requestId}
            role="button"
            tabIndex={0}
            onClick={() => activateLogistics(event.requestId ?? null)}
            onKeyDown={(keyboardEvent) => handleInteractiveCardKeyDown(keyboardEvent, () => activateLogistics(event.requestId ?? null))}
            className={`w-full rounded-xl border p-3 text-left transition-colors sm:rounded-2xl sm:p-4 ${selectedLogistics?.requestId === event.requestId ? "border-primary bg-primary/5 shadow-sm" : "border-slate-200 hover:bg-muted/40"}`}
          >
            <div className="flex items-start justify-between gap-3">
              <div>
                <p className="line-clamp-2 text-sm font-medium sm:text-base">{event.associationName}</p>
                <p className="text-sm text-muted-foreground">{event.commune || "Commune non renseignée"}</p>
                <p className="text-sm text-primary">{event.boardStateLabel}</p>
              </div>
              <Badge variant="outline">{formatDateLabel(event.useStartDate, event.useEndDate)}</Badge>
            </div>
            <p className="mt-2 text-sm text-muted-foreground line-clamp-2">
              {event.requestedItems.map((item) => `${item.label} x${item.quantity}`).join(" • ") || "Matériel non renseigné"}
            </p>
            <div className="mt-3 flex flex-col gap-2 sm:flex-row sm:flex-wrap">
              {logisticsDirectionsByRequestId.get(event.requestId) ? (
                <DirectionsMenu
                  latitude={logisticsDirectionsByRequestId.get(event.requestId)?.latitude}
                  longitude={logisticsDirectionsByRequestId.get(event.requestId)?.longitude}
                  destinationLabel={logisticsDirectionsByRequestId.get(event.requestId)?.destinationLabel}
                  label="Ouvrir avec"
                  usageContext="public"
                  className="min-h-10 w-full sm:w-auto"
                />
              ) : null}
              <Link href={`/dashboard/requests/${event.requestId}`} {...buildRoutePrefetchHandlers(`/dashboard/requests/${event.requestId}`)}>
                <Button asChild type="button" size="sm" variant="outline" className="min-h-10 w-full sm:w-auto">
                  <span>Ouvrir le dossier</span>
                </Button>
              </Link>
              {event.finalPdfUrl ? (
                <a
                  href={buildMaterialReturnFinalPdfViewerHref({
                    url: event.finalPdfUrl,
                    returnTo: "/associations/carte",
                    title: "Consulter le PDF final de restitution",
                    downloadName: `fiche-finale-restitution-${event.requestId}.pdf`,
                  })}
                >
                  <Button asChild type="button" size="sm" variant="outline" className="min-h-10 w-full sm:w-auto">
                    <span>PDF final</span>
                  </Button>
                </a>
              ) : null}
            </div>
          </div>
        ))
      ) : (
        <div className="rounded-2xl border border-dashed p-4 text-sm text-muted-foreground">
          Aucune mission logistique ne correspond à cette lecture.
        </div>
      )}
    </>
  );

  return (
    <div className="portal-immersive-page min-h-screen overflow-x-hidden">
      <header className="border-b border-border bg-white">
        <div className="container py-3 sm:py-4">
          <div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between sm:gap-4">
            <div className="flex items-start gap-3 sm:items-center sm:gap-4">
              <Link href={backHref} {...buildRoutePrefetchHandlers(backHref)}>
                <Button variant="ghost" size="icon">
                  <ArrowLeft className="h-5 w-5" />
                </Button>
              </Link>
              <div className="min-w-0">
                <h1 className="text-lg font-bold sm:text-xl">Carte des associations</h1>
                <p className="max-w-2xl text-sm leading-6 text-muted-foreground">
                  Découvre les associations des Savanes, leur densité territoriale et, côté administration, la circulation du matériel CCDS.
                </p>
              </div>
            </div>
            <div className="grid w-full gap-2 self-start sm:flex sm:w-auto sm:items-center sm:gap-3 sm:self-auto">
              <Badge variant="outline" className="bg-primary/5 text-primary border-primary/20">
                {visibleCount} {mapMode === "logistique" ? "mission(s)" : "association(s)"}
              </Badge>
              {isAuthenticated ? (
                <Link href="/dashboard/associations" {...buildRoutePrefetchHandlers("/dashboard/associations")}>
                  <Button variant="outline" className="min-h-10 w-full whitespace-normal sm:w-auto">Annuaire portail</Button>
                </Link>
              ) : null}
            </div>
          </div>
        </div>
      </header>

      <main className="container space-y-4 py-4 sm:space-y-6 sm:py-8">
        <div className="flex gap-2 overflow-x-auto pb-1 sm:hidden">
          {publicNavItems.map((item) => (
            <Link key={item.href} href={item.href} {...buildRoutePrefetchHandlers(item.href)}>
              <Button
                type="button"
                variant={item.active ? "default" : "outline"}
                size="sm"
                className="min-h-10 shrink-0 rounded-full px-4"
              >
                {item.label}
              </Button>
            </Link>
          ))}
        </div>

        <section className="rounded-2xl border border-slate-200 bg-white/96 shadow-[0_18px_44px_rgba(15,23,42,0.06)]">
          <div className="grid gap-0 xl:grid-cols-[1.2fr_0.8fr]">
            <div className="space-y-4 p-4 sm:p-5 lg:p-6">
              <div className="space-y-2 sm:space-y-3">
                <Badge variant="outline" className={modeMeta.accentClassName}>
                  {modeMeta.title}
                </Badge>
                <div className="space-y-2">
                  <h2 className="text-lg font-semibold tracking-tight sm:text-[1.55rem]">Cartographie interactive & implantation territoriale</h2>
                  <p className="max-w-3xl text-sm leading-6 text-muted-foreground">
                    Passe de l'annuaire géographique à la densité d'implantation, puis au pilotage logistique si tu es administrateur.
                  </p>
                </div>
              </div>

              <div className="grid grid-cols-1 gap-3 sm:grid-cols-3">
                <div className="rounded-2xl border border-slate-200 bg-slate-50 px-4 py-3">
                  <p className="text-xs uppercase tracking-wide text-muted-foreground">Éléments visibles</p>
                  <p className="mt-2 text-2xl font-semibold text-slate-900 sm:text-3xl">{visibleCount}</p>
                </div>
                <div className="rounded-2xl border border-slate-200 bg-slate-50 px-4 py-3">
                  <p className="text-xs uppercase tracking-wide text-muted-foreground">Mode actif</p>
                  <p className="mt-2 break-words text-base font-semibold text-slate-900">{modeMeta.title}</p>
                </div>
                <div className="rounded-2xl border border-slate-200 bg-slate-50 px-4 py-3">
                  <p className="text-xs uppercase tracking-wide text-muted-foreground">Lecture</p>
                  <p className="mt-2 text-sm font-medium leading-6 text-slate-700 line-clamp-3">{modeMeta.description}</p>
                </div>
              </div>

              <div className="grid gap-2 sm:flex sm:flex-wrap sm:overflow-visible">
                <Button
                  variant={mapMode === "annuaire" ? "default" : "outline"}
                  onClick={() => setMapMode("annuaire")}
                  className="min-h-10 justify-start whitespace-normal text-left sm:shrink-0"
                >
                  Annuaire géographique
                </Button>
                <Button
                  variant={mapMode === "densite" ? "default" : "outline"}
                  onClick={() => setMapMode("densite")}
                  className="min-h-10 justify-start whitespace-normal text-left sm:shrink-0"
                >
                  Densité d'implantation
                </Button>
                {isAdmin ? (
                  <Button
                    variant={mapMode === "logistique" ? "default" : "outline"}
                    onClick={() => setMapMode("logistique")}
                    className="min-h-10 justify-start whitespace-normal text-left sm:shrink-0"
                  >
                    <PackageCheck className="mr-2 h-4 w-4" />
                    Flux logistique événementiel
                  </Button>
                ) : null}
              </div>
            </div>

            {!isMobile ? (
            <div className="border-t border-slate-200 bg-slate-50/90 p-5 lg:p-8 xl:border-l xl:border-t-0">
              <div className="rounded-2xl border border-slate-200 bg-white p-5 shadow-sm">
                <p className="text-sm font-semibold text-slate-900">Repères de lecture</p>
                <div className="mt-4 space-y-3 text-sm text-slate-600">
                  <div className="flex items-start gap-3">
                    <span className="mt-1 h-2.5 w-2.5 rounded-full bg-emerald-500" />
                    <p>Les points et zones répondent aux filtres actifs sans masquer les fiches utiles.</p>
                  </div>
                  <div className="flex items-start gap-3">
                    <span className="mt-1 h-2.5 w-2.5 rounded-full bg-blue-500" />
                    <p>Le panneau latéral reste synchronisé avec la carte pour ouvrir la bonne lecture au bon endroit.</p>
                  </div>
                  <div className="flex items-start gap-3">
                    <span className="mt-1 h-2.5 w-2.5 rounded-full bg-amber-500" />
                    <p>Le filtre par rayon aide à isoler l’offre locale autour d’une position réelle, sans brouiller l’écran.</p>
                  </div>
                </div>
              </div>
            </div>
            ) : null}
          </div>
        </section>

        {!isMobile ? (
        <Card className="border-slate-200 shadow-sm">
          <CardContent className="space-y-5 p-4 sm:p-6">
            <div className="flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between">
              <div className="relative w-full lg:w-[320px]">
                <Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
                <Input
                  placeholder={mapMode === "logistique" ? "Rechercher une mission ou du matériel..." : "Rechercher une association..."}
                  value={search}
                  onChange={(e) => setSearch(e.target.value)}
                  className="min-h-11 pl-9"
                />
              </div>
              <div className="w-full lg:w-[280px]">
                <Select value={thematiqueFilter} onValueChange={(value) => setThematiqueFilter(value as AssociationThematic | "all")}>
                  <SelectTrigger disabled={mapMode === "logistique"} className="min-h-11">
                    <SelectValue placeholder="Filtrer par catégorie" />
                  </SelectTrigger>
                  <SelectContent>
                    <SelectItem value="all">Toutes les thématiques</SelectItem>
                    {associationThematicOptions.map((option) => (
                      <SelectItem key={option.value} value={option.value}>
                        {option.label}
                      </SelectItem>
                    ))}
                  </SelectContent>
                </Select>
              </div>
              <div className="flex gap-2 overflow-x-auto pb-1 sm:flex-wrap sm:overflow-visible">
                {associationCommuneOptions.map((option) => (
                  <Button
                    key={option.value}
                    size="sm"
                    type="button"
                    variant={communeFilter === option.value ? "default" : "outline"}
                    className="min-h-10 shrink-0 rounded-full"
                    onClick={() => setCommuneFilter(option.value)}
                  >
                    {option.label}
                  </Button>
                ))}
              </div>
            </div>

            <div className="grid gap-4 xl:grid-cols-[1fr_0.8fr]">
              <div className="space-y-3 rounded-2xl border border-slate-200 bg-slate-50 p-4">
                <div className="flex flex-wrap items-center justify-between gap-3">
                  <div>
                    <p className="text-sm font-medium">Filtre par rayon d'action</p>
                    <p className="text-xs text-muted-foreground">
                      Affiche uniquement les associations autour de ta position pour repérer l'offre locale sur le territoire.
                    </p>
                  </div>
                  <div className="flex gap-2">
                    <Button variant="outline" onClick={requestUserLocation} disabled={geolocating} className="min-h-10">
                      {geolocating ? <Loader2 className="mr-2 h-4 w-4 animate-spin" /> : null}
                      {userPosition ? "Actualiser ma position" : "Utiliser ma position"}
                    </Button>
                    {radiusEnabled ? (
                      <Button variant="ghost" onClick={() => setRadiusEnabled(false)} className="min-h-10">
                        Désactiver
                      </Button>
                    ) : null}
                  </div>
                </div>
                <div className="space-y-2">
                  <div className="flex items-center justify-between text-sm">
                    <span>Rayon actif</span>
                    <span className="font-medium">{radiusKm} km</span>
                  </div>
                  <Slider
                    value={[radiusKm]}
                    min={1}
                    max={25}
                    step={1}
                    onValueChange={(value) => setRadiusKm(value[0] || 5)}
                    disabled={!userPosition}
                  />
                </div>
              </div>

              {mapMode === "logistique" ? (
                <div className="rounded-2xl border border-slate-200 bg-slate-50 p-4">
                  <p className="text-sm font-medium">Vue logistique</p>
                  <p className="text-xs text-muted-foreground mb-3">
                    Les missions terrain peuvent être affichées en cours, à venir ou dans une vue complète.
                  </p>
                  <div className="flex flex-wrap gap-2">
                    {([
                      ["actifs", "Actifs aujourd'hui"],
                      ["avenir", "À venir"],
                      ["tous", "Tous les flux"],
                    ] as const).map(([value, label]) => (
                      <Button
                        key={value}
                        variant={logisticsFilter === value ? "default" : "outline"}
                        size="sm"
                        onClick={() => setLogisticsFilter(value)}
                        className="min-h-10"
                      >
                        {label}
                      </Button>
                    ))}
                  </div>
                </div>
              ) : (
                <div className="rounded-2xl border border-slate-200 bg-slate-50 p-4">
                  <p className="text-sm font-medium">Lecture territoriale</p>
                  <p className="text-xs text-muted-foreground">
                    {mapMode === "annuaire"
                      ? "La carte regroupe automatiquement les marqueurs quand le nombre d'associations devient dense, puis les détaille au zoom."
                      : "La couche densité montre les zones de concentration associatives pour aider à repérer les secteurs isolés ou saturés."}
                  </p>
                </div>
              )}
            </div>

            <p className="text-sm text-muted-foreground">
              {visibleCount} élément(s) visible(s)
              {communeFilter !== "all" ? ` • ${getAssociationCommuneLabel(communeFilter)}` : ""}
              {thematiqueFilter !== "all" && mapMode !== "logistique" ? ` • ${getAssociationThematicLabel(thematiqueFilter)}` : ""}
              {radiusEnabled && userPosition ? ` • dans un rayon de ${radiusKm} km autour de toi` : ""}
            </p>
          </CardContent>
        </Card>
        ) : null}

        {isMobile ? (
          <div className="space-y-4">
            <div className="flex gap-2 rounded-2xl border border-slate-200 bg-white p-2 shadow-sm">
              <Button
                type="button"
                variant={mobilePanel === "map" ? "default" : "ghost"}
                className="min-h-10 flex-1"
                onClick={() => setMobilePanel("map")}
              >
                Carte
              </Button>
              <Button
                type="button"
                variant={mobilePanel === "list" ? "default" : "ghost"}
                className="min-h-10 flex-1"
                onClick={() => setMobilePanel("list")}
              >
                Liste
              </Button>
            </div>

            {mobilePanel === "map" ? (
              <Suspense fallback={<MapPanelLoader />}>
                <AssociationPublicMap
                  associations={radiusFilteredAssociations}
                  mode={mapMode}
                  selectedAssociationId={selectedAssociationId}
                  onSelectAssociation={(id) => {
                    setSelectedAssociationId(id);
                    setSelectedLogisticsRequestId(null);
                  }}
                  logisticsEvents={logisticsEvents}
                  selectedLogisticsRequestId={selectedLogisticsRequestId}
                  onSelectLogistics={(requestId) => {
                    setSelectedLogisticsRequestId(requestId);
                    setSelectedAssociationId(null);
                  }}
                  radiusCenter={radiusEnabled ? userPosition : null}
                  radiusKm={radiusEnabled ? radiusKm : 0}
                  styleUrl={associationMapSettings?.publicStyleUrl || associationMapSettings?.styleUrl}
                  heightClassName="h-[44dvh] min-h-[320px] max-h-[460px]"
                />
              </Suspense>
            ) : null}

              <Card className="border-slate-200 bg-white/96 shadow-sm">
                <CardContent className="space-y-4 p-4">
                <div className="flex gap-2">
                  <Button
                    type="button"
                    variant={showMobileFilters ? "default" : "outline"}
                    className="min-h-10 flex-1"
                    onClick={() => setShowMobileFilters((prev) => !prev)}
                  >
                    <Filter className="mr-2 h-4 w-4" />
                    Filtres
                    <ChevronDown className={cn("ml-2 h-4 w-4 transition-transform", showMobileFilters && "rotate-180")} />
                  </Button>
                </div>

                <p className="text-sm text-muted-foreground">
                  {visibleCount} élément(s) visible(s)
                  {communeFilter !== "all" ? ` • ${getAssociationCommuneLabel(communeFilter)}` : ""}
                  {thematiqueFilter !== "all" && mapMode !== "logistique" ? ` • ${getAssociationThematicLabel(thematiqueFilter)}` : ""}
                  {radiusEnabled && userPosition ? ` • rayon ${radiusKm} km` : ""}
                </p>

                {showMobileFilters ? (
                  <>
                    <div className="relative w-full">
                      <Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
                      <Input
                        placeholder={mapMode === "logistique" ? "Rechercher une mission ou du matériel..." : "Rechercher une association..."}
                        value={search}
                        onChange={(e) => setSearch(e.target.value)}
                        className="min-h-11 pl-9"
                      />
                    </div>

                    <Select value={thematiqueFilter} onValueChange={(value) => setThematiqueFilter(value as AssociationThematic | "all")}>
                      <SelectTrigger disabled={mapMode === "logistique"} className="min-h-11">
                        <SelectValue placeholder="Filtrer par catégorie" />
                      </SelectTrigger>
                      <SelectContent>
                        <SelectItem value="all">Toutes les thématiques</SelectItem>
                        {associationThematicOptions.map((option) => (
                          <SelectItem key={option.value} value={option.value}>
                            {option.label}
                          </SelectItem>
                        ))}
                      </SelectContent>
                    </Select>

                    <div className="flex gap-2 overflow-x-auto pb-1">
                      {associationCommuneOptions.map((option) => (
                        <Button
                          key={option.value}
                          size="sm"
                          type="button"
                          variant={communeFilter === option.value ? "default" : "outline"}
                          className="min-h-10 shrink-0 rounded-full"
                          onClick={() => setCommuneFilter(option.value)}
                        >
                          {option.label}
                        </Button>
                      ))}
                    </div>

                    <div className="rounded-2xl border border-slate-200 bg-slate-50 p-4">
                      <div className="flex flex-col gap-3">
                        <div>
                          <p className="text-sm font-medium">Filtre par rayon d'action</p>
                          <p className="text-xs text-muted-foreground">
                            Isole les structures proches de ta position quand tu en as besoin.
                          </p>
                        </div>
                        <div className="flex flex-col gap-2">
                          <Button variant="outline" onClick={requestUserLocation} disabled={geolocating} className="min-h-10 w-full">
                            {geolocating ? <Loader2 className="mr-2 h-4 w-4 animate-spin" /> : null}
                            {userPosition ? "Actualiser ma position" : "Utiliser ma position"}
                          </Button>
                          {radiusEnabled ? (
                            <Button variant="ghost" onClick={() => setRadiusEnabled(false)} className="min-h-10 w-full">
                              Désactiver
                            </Button>
                          ) : null}
                        </div>
                        <div className="space-y-2">
                          <div className="flex items-center justify-between text-sm">
                            <span>Rayon actif</span>
                            <span className="font-medium">{radiusKm} km</span>
                          </div>
                          <Slider
                            value={[radiusKm]}
                            min={1}
                            max={25}
                            step={1}
                            onValueChange={(value) => setRadiusKm(value[0] || 5)}
                            disabled={!userPosition}
                          />
                        </div>
                      </div>
                    </div>

                    {mapMode === "logistique" ? (
                      <div className="rounded-2xl border border-slate-200 bg-slate-50 p-4">
                        <p className="text-sm font-medium">Vue logistique</p>
                        <p className="mb-3 text-xs text-muted-foreground">
                          Affiche les missions en cours, à venir ou l’ensemble des flux.
                        </p>
                        <div className="flex flex-wrap gap-2">
                          {([
                            ["actifs", "Actifs aujourd'hui"],
                            ["avenir", "À venir"],
                            ["tous", "Tous les flux"],
                          ] as const).map(([value, label]) => (
                            <Button
                              key={value}
                              variant={logisticsFilter === value ? "default" : "outline"}
                              size="sm"
                              onClick={() => setLogisticsFilter(value)}
                              className="min-h-10"
                            >
                              {label}
                            </Button>
                          ))}
                        </div>
                      </div>
                    ) : null}
                  </>
                ) : null}
              </CardContent>
            </Card>

            {mobilePanel === "list" ? (
              <Card className="border-slate-200 shadow-sm">
                <CardHeader>
                  <CardTitle className="text-lg">
                    {mapMode === "annuaire"
                      ? "Associations géolocalisées"
                      : mapMode === "densite"
                        ? "Lecture par commune"
                        : "Missions logistiques"}
                  </CardTitle>
                  <CardDescription>
                    {mapMode === "annuaire"
                      ? "Touchez une fiche pour la relier à la carte ou ouvrir son détail."
                      : mapMode === "densite"
                        ? "Les communes les plus présentes remontent ici pour lecture rapide."
                        : "Les missions matérielles se relisent ici sans surcharger la carte."}
                  </CardDescription>
                </CardHeader>
                <CardContent className="space-y-3">
                  {resultsPanelContent}
                </CardContent>
              </Card>
            ) : null}
          </div>
        ) : (
          <div className="grid gap-6 xl:grid-cols-[minmax(0,1.7fr)_420px]">
            <Suspense fallback={<MapPanelLoader />}>
              <AssociationPublicMap
                associations={radiusFilteredAssociations}
                mode={mapMode}
                selectedAssociationId={selectedAssociationId}
                onSelectAssociation={(id) => {
                  setSelectedAssociationId(id);
                  setSelectedLogisticsRequestId(null);
                }}
                logisticsEvents={logisticsEvents}
                selectedLogisticsRequestId={selectedLogisticsRequestId}
                onSelectLogistics={(requestId) => {
                  setSelectedLogisticsRequestId(requestId);
                  setSelectedAssociationId(null);
                }}
                radiusCenter={radiusEnabled ? userPosition : null}
                radiusKm={radiusEnabled ? radiusKm : 0}
                styleUrl={associationMapSettings?.publicStyleUrl || associationMapSettings?.styleUrl}
              />
            </Suspense>

              <Card className="min-h-[620px] border-slate-200 bg-white/96 shadow-sm">
              <CardHeader>
                <CardTitle>
                  {mapMode === "annuaire"
                    ? "Associations géolocalisées"
                    : mapMode === "densite"
                      ? "Lecture par commune"
                      : "Missions logistiques"}
                </CardTitle>
                <CardDescription>
                  {mapMode === "annuaire"
                    ? "Clique sur une fiche ou un point de la carte pour centrer l'association."
                    : mapMode === "densite"
                      ? "Les zones les plus denses remontent ici pour guider l'analyse territoriale."
                      : "Les prêts de matériel en cours ou à venir deviennent des objets de pilotage cartographique."}
                </CardDescription>
              </CardHeader>
              <CardContent className="space-y-3 max-h-[560px] overflow-auto pr-1">
                {resultsPanelContent}
              </CardContent>
            </Card>
          </div>
        )}
      </main>
    </div>
  );
}

function formatDateLabel(start?: string | null, end?: string | null) {
  if (!start) return "-";
  const startLabel = new Date(start).toLocaleDateString("fr-FR", {
    day: "2-digit",
    month: "2-digit",
  });
  const endLabel = new Date(end || start).toLocaleDateString("fr-FR", {
    day: "2-digit",
    month: "2-digit",
  });
  if (startLabel === endLabel) return startLabel;
  return `${startLabel} -> ${endLabel}`;
}
