"use client";

import { useEffect, useMemo, useRef, useState } from "react";
import FullCalendar from "@fullcalendar/react";
import dayGridPlugin from "@fullcalendar/daygrid";
import timeGridPlugin from "@fullcalendar/timegrid";
import listPlugin from "@fullcalendar/list";
import interactionPlugin from "@fullcalendar/interaction";
import deLocale from "@fullcalendar/core/locales/de";
import { useSession } from "next-auth/react";
import EventForm from "./EventForm";

type EventItem = {
  id: string;
  title: string;
  description?: string | null;
  location?: string | null;
  locationPlaceId?: string | null;
  locationLat?: number | null;
  locationLng?: number | null;
  startAt: string;
  endAt?: string | null;
  status: string;
  category?: { id: string; name: string } | null;
};

type ViewItem = {
  id: string;
  token: string;
  items: { eventId: string }[];
  categories: { categoryId: string; category?: { name: string } }[];
  exclusions: { eventId: string }[];
};

export default function CalendarBoard() {
  const { data } = useSession();
  const [events, setEvents] = useState<EventItem[]>([]);
  const [view, setView] = useState<ViewItem | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [loading, setLoading] = useState(false);
  const [query, setQuery] = useState("");
  const [categoryFilter, setCategoryFilter] = useState("ALL");
  const [sortKey, setSortKey] = useState("startAt");
  const [sortDir, setSortDir] = useState<"asc" | "desc">("asc");
  const [detailsEvent, setDetailsEvent] = useState<EventItem | null>(null);
  const [placesKey, setPlacesKey] = useState("");
  const [placesProvider, setPlacesProvider] = useState<"google" | "osm">("osm");
  const [formOpen, setFormOpen] = useState(false);
  const [prefillStartAt, setPrefillStartAt] = useState<string | null>(null);
  const [viewOrder, setViewOrder] = useState<Array<"calendar" | "list">>([
    "calendar",
    "list"
  ]);
  const [collapsed, setCollapsed] = useState<{ calendar: boolean; list: boolean }>({
    calendar: false,
    list: false
  });
  const [activeRange, setActiveRange] = useState<{
    start: Date;
    end: Date;
    viewType: string;
  } | null>(null);
  const [initialView, setInitialView] = useState("dayGridMonth");
  const [dragSource, setDragSource] = useState<"calendar" | "list" | null>(null);
  const [dragOver, setDragOver] = useState<"calendar" | "list" | null>(null);
  const calendarRef = useRef<HTMLDivElement | null>(null);
  const listRef = useRef<HTMLDivElement | null>(null);

  const fetchEvents = async () => {
    setLoading(true);
    setError(null);
    try {
      const [eventsResponse, viewResponse] = await Promise.all([
        fetch("/api/events"),
        fetch("/api/views/default")
      ]);
      if (!eventsResponse.ok) {
        throw new Error("Events konnten nicht geladen werden.");
      }
      const payload = await eventsResponse.json();
      setEvents(payload);
      if (viewResponse.ok) {
        setView(await viewResponse.json());
      }
    } catch (err) {
      setError((err as Error).message);
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    if (data?.user) {
      fetchEvents();
    }
  }, [data?.user]);

  useEffect(() => {
    const loadKey = async () => {
      try {
        const response = await fetch("/api/settings/google-places");
        if (!response.ok) return;
        const payload = await response.json();
        setPlacesKey(payload.apiKey || "");
        setPlacesProvider(payload.provider === "google" ? "google" : "osm");
      } catch {
        // ignore
      }
    };

    if (data?.user) {
      loadKey();
    }
  }, [data?.user]);

  useEffect(() => {
    const handler = () => {
      fetchEvents();
    };
    window.addEventListener("views-updated", handler);
    return () => window.removeEventListener("views-updated", handler);
  }, []);

  useEffect(() => {
    try {
      const stored = window.localStorage.getItem("calendarLastView");
      if (stored) {
        setInitialView(stored);
      }
    } catch {
      // ignore
    }
  }, []);

  useEffect(() => {
    try {
      const stored = window.localStorage.getItem("listSort");
      if (!stored) return;
      const parsed = JSON.parse(stored);
      if (
        parsed &&
        typeof parsed === "object" &&
        typeof parsed.key === "string" &&
        (parsed.dir === "asc" || parsed.dir === "desc")
      ) {
        setSortKey(parsed.key);
        setSortDir(parsed.dir);
      }
    } catch {
      // ignore
    }
  }, []);

  useEffect(() => {
    try {
      const stored = window.localStorage.getItem("calendarViewOrder");
      if (!stored) return;
      const parsed = JSON.parse(stored);
      if (
        Array.isArray(parsed) &&
        parsed.length === 2 &&
        parsed.includes("calendar") &&
        parsed.includes("list")
      ) {
        setViewOrder(parsed);
      }
    } catch {
      // ignore
    }
  }, []);

  useEffect(() => {
    try {
      const stored = window.localStorage.getItem("calendarViewCollapsed");
      if (!stored) return;
      const parsed = JSON.parse(stored);
      if (
        parsed &&
        typeof parsed === "object" &&
        typeof parsed.calendar === "boolean" &&
        typeof parsed.list === "boolean"
      ) {
        setCollapsed({ calendar: parsed.calendar, list: parsed.list });
      }
    } catch {
      // ignore
    }
  }, []);

  const persistOrder = (nextOrder: Array<"calendar" | "list">) => {
    setViewOrder(nextOrder);
    try {
      window.localStorage.setItem("calendarViewOrder", JSON.stringify(nextOrder));
    } catch {
      // ignore
    }
  };

  const toggleCollapse = (section: "calendar" | "list") => {
    const next = { ...collapsed, [section]: !collapsed[section] };
    setCollapsed(next);
    try {
      window.localStorage.setItem("calendarViewCollapsed", JSON.stringify(next));
    } catch {
      // ignore
    }
  };

  const swapOrder = (source: "calendar" | "list", target: "calendar" | "list") => {
    if (source === target) return;
    const next = viewOrder.map((item) => (item === source ? target : source)) as Array<
      "calendar" | "list"
    >;
    persistOrder(next);
  };

  const onDragStart = (
    event: React.DragEvent<HTMLDivElement>,
    section: "calendar" | "list"
  ) => {
    event.dataTransfer.setData("text/plain", section);
    event.dataTransfer.effectAllowed = "move";
    setDragSource(section);
    setDragOver(section);
    const node = section === "calendar" ? calendarRef.current : listRef.current;
    if (node) {
      event.dataTransfer.setDragImage(node, 20, 20);
    }
  };

  const onDragEnter = (target: "calendar" | "list") => {
    setDragOver(target);
  };

  const onDragEnd = () => {
    setDragSource(null);
    setDragOver(null);
  };

  const onDrop = (event: React.DragEvent<HTMLDivElement>, target: "calendar" | "list") => {
    event.preventDefault();
    const source = event.dataTransfer.getData("text/plain") as
      | "calendar"
      | "list";
    if (source) {
      swapOrder(source, target);
    }
    setDragSource(null);
    setDragOver(null);
  };

  const openFormForDate = (date: Date | null) => {
    if (date) {
      const prefill = new Date(date);
      prefill.setHours(12, 0, 0, 0);
      setPrefillStartAt(prefill.toISOString());
    } else {
      setPrefillStartAt(null);
    }
    setFormOpen(true);
  };

  const calendarEvents = useMemo(
    () =>
      events.map((event) => ({
        id: event.id,
        title: event.title,
        start: event.startAt,
        end: event.endAt || undefined,
        extendedProps: {
          status: event.status,
          location: event.location,
          description: event.description,
          category: event.category?.name
        }
      })),
    [events]
  );

  const selectedEventIds = useMemo(() => {
    if (!view) return new Set<string>();
    const ids = new Set(view.items.map((item) => item.eventId));
    const excluded = new Set(view.exclusions.map((item) => item.eventId));
    const subscribedCategoryIds = new Set(
      view.categories.map((item) => item.categoryId)
    );
    events.forEach((event) => {
      if (event.category?.id && subscribedCategoryIds.has(event.category.id)) {
        ids.add(event.id);
      }
    });
    excluded.forEach((eventId) => ids.delete(eventId));
    return ids;
  }, [view, events]);

  const subscribedCategoryIds = useMemo(() => {
    return new Set(view?.categories.map((item) => item.categoryId) || []);
  }, [view]);

  const toggleEvent = async (eventId: string) => {
    if (!view) return;
    const isSelected = selectedEventIds.has(eventId);
    await fetch(`/api/views/${view.id}/items`, {
      method: isSelected ? "DELETE" : "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ eventId })
    });
    await fetchEvents();
    window.dispatchEvent(new Event("views-updated"));
  };


  const filteredEvents = useMemo(() => {
    const normalizedQuery = query.trim().toLowerCase();
    const filtered = events.filter((event) => {
      const categoryName = event.category?.name || "Ohne Kategorie";
      if (categoryFilter !== "ALL" && categoryName !== categoryFilter) {
        return false;
      }
      if (!normalizedQuery) return true;
      return (
        event.title.toLowerCase().includes(normalizedQuery) ||
        (event.description || "").toLowerCase().includes(normalizedQuery) ||
        (event.location || "").toLowerCase().includes(normalizedQuery) ||
        categoryName.toLowerCase().includes(normalizedQuery)
      );
    });

    const sorted = [...filtered].sort((a, b) => {
      const dir = sortDir === "asc" ? 1 : -1;
      if (sortKey === "title") {
        return a.title.localeCompare(b.title) * dir;
      }
      if (sortKey === "category") {
        const aCat = a.category?.name || "Ohne Kategorie";
        const bCat = b.category?.name || "Ohne Kategorie";
        return aCat.localeCompare(bCat) * dir;
      }
      if (sortKey === "location") {
        const aLoc = a.location || "";
        const bLoc = b.location || "";
        return aLoc.localeCompare(bLoc) * dir;
      }
      if (sortKey === "status") {
        return a.status.localeCompare(b.status) * dir;
      }
      const aDate = new Date(a.startAt).getTime();
      const bDate = new Date(b.startAt).getTime();
      return (aDate - bDate) * dir;
    });

    return sorted;
  }, [events, query, categoryFilter, sortKey, sortDir]);

  const categoryOptions = useMemo(() => {
    const list = events
      .map((event) => event.category?.name || "Ohne Kategorie")
      .filter(Boolean);
    return Array.from(new Set(list)).sort();
  }, [events]);

  const displayedEvents = useMemo(() => {
    if (!activeRange) {
      return filteredEvents;
    }
    return filteredEvents.filter((event) => {
      const start = new Date(event.startAt);
      return start >= activeRange.start && start < activeRange.end;
    });
  }, [filteredEvents, activeRange]);

  const toggleSort = (nextKey: string) => {
    let nextDir: "asc" | "desc" = "asc";
    if (sortKey === nextKey) {
      nextDir = sortDir === "asc" ? "desc" : "asc";
      setSortDir(nextDir);
    } else {
      setSortKey(nextKey);
      setSortDir("asc");
    }
    try {
      const key = sortKey === nextKey ? sortKey : nextKey;
      window.localStorage.setItem(
        "listSort",
        JSON.stringify({ key, dir: nextDir })
      );
    } catch {
      // ignore
    }
  };

  if (!data?.user) {
    return (
      <div className="card-muted text-center">
        <p className="text-slate-700">
          Bitte anmelden, um die Vereinskalender zu sehen.
        </p>
      </div>
    );
  }

  return (
    <section className="space-y-4 fade-up">
      <div className="flex items-center justify-between">
        <div>
          <p className="text-xs uppercase tracking-[0.2em] text-slate-500">Kalender</p>
          <h2 className="text-2xl font-semibold">Termine im Blick</h2>
        </div>
        <div className="flex items-center gap-2">
          <button
            type="button"
            className="btn-accent"
            onClick={() => openFormForDate(null)}
          >
            Neuer Termin
          </button>
          <button
            type="button"
            onClick={fetchEvents}
            className="btn-ghost"
          >
            Aktualisieren
          </button>
        </div>
      </div>
      <EventForm
        variant="inline"
        showTrigger={false}
        open={formOpen}
        onOpenChange={(open) => {
          setFormOpen(open);
          if (!open) {
            setPrefillStartAt(null);
          }
        }}
        prefillStartAt={prefillStartAt}
      />
      {error && <p className="text-sm text-red-600">{error}</p>}
      {loading && <p className="text-sm text-slate-500">Lade Termine...</p>}
      {viewOrder.map((section) => {
        if (section === "calendar") {
          return (
            <div
              key="calendar"
              ref={calendarRef}
              className={`card drag-card ${
                dragSource === "calendar" ? "dragging" : ""
              } ${
                dragOver === "calendar" && dragSource && dragSource !== "calendar"
                  ? "drag-target"
                  : ""
              } ${
                dragSource === "list" && dragOver === "calendar" ? "shift-down" : ""
              }`}
              onDragOver={(event) => event.preventDefault()}
              onDragEnter={() => onDragEnter("calendar")}
              onDrop={(event) => onDrop(event, "calendar")}
            >
              <div className="mb-3 flex items-center justify-between">
                <h3 className="text-sm font-semibold text-slate-700">Kalender</h3>
                <div className="flex items-center gap-2">
                  <button
                    type="button"
                    className="rounded-full border border-slate-200 px-2 py-1 text-xs text-slate-600"
                    onClick={() => toggleCollapse("calendar")}
                    aria-label={collapsed.calendar ? "Kalender aufklappen" : "Kalender zuklappen"}
                    title={collapsed.calendar ? "Aufklappen" : "Zuklappen"}
                  >
                    {collapsed.calendar ? <IconChevronDown /> : <IconChevronUp />}
                  </button>
                  <div
                    className="drag-handle"
                    draggable
                    onDragStart={(event) => onDragStart(event, "calendar")}
                    onDragEnd={onDragEnd}
                    title="Zum Tauschen ziehen"
                    aria-label="Kalender verschieben"
                  >
                    <IconGrip />
                  </div>
                </div>
              </div>
              {!collapsed.calendar && (
                <FullCalendar
                  plugins={[dayGridPlugin, timeGridPlugin, listPlugin, interactionPlugin]}
                locale={deLocale}
                initialView={initialView}
                firstDay={1}
                headerToolbar={{
                  left: "prev,next today",
                  center: "title",
                  right: "dayGridMonth,timeGridWeek,dayGridYear,listWeek"
                  }}
                  views={{
                    dayGridMonth: { buttonText: "Monat" },
                    timeGridWeek: { buttonText: "Woche" },
                    dayGridYear: { buttonText: "Jahr" },
                    listWeek: { buttonText: "Übersicht" }
                  }}
                  buttonText={{ today: "Heute" }}
                  events={calendarEvents}
                  dayCellContent={(arg) => {
                    if (arg.view.type !== "dayGridMonth") {
                      return arg.dayNumberText;
                    }
                    return (
                      <div className="flex items-center justify-between">
                        <span>{arg.dayNumberText}</span>
                        <button
                          type="button"
                          className="rounded-full border border-slate-200 bg-white/80 px-2 py-0.5 text-xs text-slate-600 hover:bg-slate-100"
                          aria-label={`Termin am ${arg.date.toLocaleDateString("de-DE")} anlegen`}
                          onClick={(event) => {
                            event.preventDefault();
                            event.stopPropagation();
                            openFormForDate(arg.date);
                          }}
                        >
                          +
                        </button>
                      </div>
                    );
                  }}
                  eventClick={(info) => {
                    const match = events.find((event) => event.id === info.event.id);
                    if (match) {
                      setDetailsEvent(match);
                    }
                  }}
                eventContent={(arg) => {
                  const status = arg.event.extendedProps.status as string;
                  const isSelected = selectedEventIds.has(arg.event.id);
                  return (
                      <div className="event-shell">
                        <div>
                          <div className="text-sm font-medium">{arg.event.title}</div>
                          <div className="text-xs text-slate-600">
                            {arg.event.extendedProps.category || "Ohne Kategorie"}
                          </div>
                          <div className="mt-1 flex items-center gap-1">
                            <StatusIcon status={status} />
                          </div>
                        </div>
                        <ViewToggleButton
                          isSelected={isSelected}
                          onClick={(event) => {
                            event.preventDefault();
                            event.stopPropagation();
                            toggleEvent(arg.event.id);
                          }}
                          size="sm"
                        />
                      </div>
                    );
                  }}
                  height="auto"
                  datesSet={(arg) => {
                    setActiveRange({
                      start: arg.start,
                      end: arg.end,
                      viewType: arg.view.type
                    });
                    try {
                      window.localStorage.setItem("calendarLastView", arg.view.type);
                    } catch {
                      // ignore
                    }
                  }}
                />
              )}
            </div>
          );
        }

        return (
          <div
            key="list"
            ref={listRef}
            className={`card space-y-4 drag-card ${
              dragSource === "list" ? "dragging" : ""
            } ${
              dragOver === "list" && dragSource && dragSource !== "list" ? "drag-target" : ""
            } ${
              dragSource === "calendar" && dragOver === "list" ? "shift-up" : ""
            }`}
            onDragOver={(event) => event.preventDefault()}
            onDragEnter={() => onDragEnter("list")}
            onDrop={(event) => onDrop(event, "list")}
          >
            <div className="flex items-center justify-between">
              <h3 className="text-sm font-semibold text-slate-700">Liste</h3>
              <div className="flex items-center gap-2">
                <button
                  type="button"
                  className="rounded-full border border-slate-200 px-2 py-1 text-xs text-slate-600"
                  onClick={() => toggleCollapse("list")}
                  aria-label={collapsed.list ? "Liste aufklappen" : "Liste zuklappen"}
                  title={collapsed.list ? "Aufklappen" : "Zuklappen"}
                >
                  {collapsed.list ? <IconChevronDown /> : <IconChevronUp />}
                </button>
                <div
                  className="drag-handle"
                  draggable
                  onDragStart={(event) => onDragStart(event, "list")}
                  onDragEnd={onDragEnd}
                  title="Zum Tauschen ziehen"
                  aria-label="Liste verschieben"
                >
                  <IconGrip />
                </div>
              </div>
            </div>
            {!collapsed.list && (
              <>
            <div className="flex flex-wrap items-center justify-between gap-3">
              <input
                value={query}
                onChange={(event) => setQuery(event.target.value)}
                placeholder="Suchen..."
                className="min-w-[220px] rounded-xl border border-slate-300 px-3 py-2 text-sm"
              />
            </div>
        <div className="overflow-x-auto">
          <table className="min-w-full text-left text-sm">
            <thead className="text-xs uppercase tracking-[0.2em] text-slate-500">
              <tr>
                <th className="pb-2">
                  <SortButton
                    label="Datum"
                    active={sortKey === "startAt"}
                    direction={sortDir}
                    onClick={() => toggleSort("startAt")}
                  />
                </th>
                <th className="pb-2">
                  <SortButton
                    label="Titel"
                    active={sortKey === "title"}
                    direction={sortDir}
                    onClick={() => toggleSort("title")}
                  />
                </th>
                <th className="pb-2">
                  <div className="flex items-center gap-2">
                    <SortButton
                      label="Kategorie"
                      active={sortKey === "category"}
                      direction={sortDir}
                      onClick={() => toggleSort("category")}
                    />
                    <select
                      className="rounded-full border border-slate-200 bg-white px-2 py-0.5 text-xs text-slate-600"
                      value={categoryFilter}
                      onChange={(event) => setCategoryFilter(event.target.value)}
                      aria-label="Kategorie filtern"
                    >
                      <option value="ALL">Alle</option>
                      {categoryOptions.map((category) => (
                        <option key={category} value={category}>
                          {category}
                        </option>
                      ))}
                    </select>
                  </div>
                </th>
                <th className="pb-2">
                  <SortButton
                    label="Ort"
                    active={sortKey === "location"}
                    direction={sortDir}
                    onClick={() => toggleSort("location")}
                  />
                </th>
                <th className="pb-2">
                  <SortButton
                    label="Status"
                    active={sortKey === "status"}
                    direction={sortDir}
                    onClick={() => toggleSort("status")}
                  />
                </th>
                <th className="pb-2">Aktionen</th>
              </tr>
            </thead>
            <tbody>
              {displayedEvents.length === 0 ? (
                <tr>
                  <td colSpan={6} className="py-4 text-slate-600">
                    Keine Termine für die aktuelle Auswahl.
                  </td>
                </tr>
              ) : (
                displayedEvents.map((event) => (
                  <tr key={event.id} className="border-t border-slate-200">
                    <td className="py-3 pr-3 whitespace-nowrap">
                      {new Date(event.startAt).toLocaleString("de-DE", {
                        dateStyle: "medium",
                        timeStyle: "short"
                      })}
                    </td>
                    <td className="py-3 pr-3 font-medium">{event.title}</td>
                    <td className="py-3 pr-3">
                      {event.category?.name || "Ohne Kategorie"}
                    </td>
                    <td className="py-3 pr-3">
                      <div className="flex items-center gap-2">
                        <span>{formatLocation(event.location)}</span>
                        {event.locationLat && event.locationLng && (
                          <a
                            className="inline-flex items-center justify-center rounded-full border border-slate-200 p-1 text-slate-600 hover:bg-slate-100"
                            href={`https://maps.google.com/?q=${event.locationLat},${event.locationLng}&z=14`}
                            target="_blank"
                            rel="noreferrer"
                            title="Google Maps"
                            aria-label="Google Maps"
                          >
                            <IconMapPin />
                          </a>
                        )}
                      </div>
                    </td>
                    <td className="py-3 pr-3">
                      <div className="flex items-center gap-2">
                        <StatusIcon status={event.status} />
                      </div>
                    </td>
                    <td className="py-3 pr-3">
                      <div className="flex flex-nowrap gap-2">
                        <ViewToggleButton
                          isSelected={selectedEventIds.has(event.id)}
                          onClick={() => toggleEvent(event.id)}
                        />
                        <button
                          type="button"
                          className="rounded-full border border-slate-200 px-3 py-1 text-xs text-slate-700"
                          onClick={() => setDetailsEvent(event)}
                        >
                          Details
                        </button>
                      </div>
                    </td>
                  </tr>
                ))
              )}
            </tbody>
          </table>
        </div>
              </>
            )}
          </div>
        );
      })}
      {detailsEvent && (
        <div className="fixed inset-0 z-30 flex items-center justify-center bg-black/40 px-4 py-6">
          <div className="card w-full max-w-2xl max-h-[90vh] overflow-y-auto">
            <div className="flex items-center justify-between">
              <h3 className="text-lg font-semibold">Termin Details</h3>
              <button
                type="button"
                className="text-sm text-slate-600"
                onClick={() => setDetailsEvent(null)}
              >
                Schließen
              </button>
            </div>
            <div className="mt-4 grid gap-4 md:grid-cols-2">
              <div className="space-y-2">
                <div>
                  <p className="text-xs uppercase tracking-[0.2em] text-slate-500">
                    Titel
                  </p>
                  <p className="text-sm font-semibold">{detailsEvent.title}</p>
                </div>
                <div>
                  <p className="text-xs uppercase tracking-[0.2em] text-slate-500">
                    Zeitpunkt
                  </p>
                  <p className="text-sm">
                    {new Date(detailsEvent.startAt).toLocaleString("de-DE", {
                      dateStyle: "full",
                      timeStyle: "short"
                    })}
                  </p>
                </div>
                <div>
                  <p className="text-xs uppercase tracking-[0.2em] text-slate-500">
                    Ort
                  </p>
                  <p className="text-sm">{detailsEvent.location || "-"}</p>
                </div>
                <div>
                  <p className="text-xs uppercase tracking-[0.2em] text-slate-500">
                    Kategorie
                  </p>
                  <p className="text-sm">
                    {detailsEvent.category?.name || "Ohne Kategorie"}
                  </p>
                </div>
                {detailsEvent.description && (
                  <div>
                    <p className="text-xs uppercase tracking-[0.2em] text-slate-500">
                      Beschreibung
                    </p>
                    <p className="text-sm text-slate-700">
                      {detailsEvent.description}
                    </p>
                  </div>
                )}
                {detailsEvent.locationLat && detailsEvent.locationLng && (
                  <div className="flex flex-wrap gap-2">
                    <a
                      className="btn-ghost"
                      href={`https://maps.google.com/?q=${detailsEvent.locationLat},${detailsEvent.locationLng}&z=14`}
                      target="_blank"
                      rel="noreferrer"
                    >
                      Google Maps
                    </a>
                    <a
                      className="btn-ghost"
                      href={`https://maps.apple.com/?ll=${detailsEvent.locationLat},${detailsEvent.locationLng}`}
                      target="_blank"
                      rel="noreferrer"
                    >
                      Apple Karten
                    </a>
                    <a
                      className="btn-ghost"
                      href={`https://www.openstreetmap.org/?mlat=${detailsEvent.locationLat}&mlon=${detailsEvent.locationLng}#map=17/${detailsEvent.locationLat}/${detailsEvent.locationLng}`}
                      target="_blank"
                      rel="noreferrer"
                    >
                      OpenStreetMap
                    </a>
                  </div>
                )}
              </div>
              <div className="min-h-[240px] overflow-hidden rounded-xl border border-slate-200 bg-slate-100">
                {placesProvider === "google" &&
                placesKey &&
                (detailsEvent.locationPlaceId ||
                  (detailsEvent.locationLat && detailsEvent.locationLng)) ? (
                  <iframe
                    title="Karte"
                    className="h-[320px] w-full"
                    loading="lazy"
                    referrerPolicy="no-referrer-when-downgrade"
                    src={
                      detailsEvent.locationPlaceId
                        ? `https://www.google.com/maps/embed/v1/place?key=${placesKey}&q=place_id:${detailsEvent.locationPlaceId}&zoom=14`
                        : `https://www.google.com/maps/embed/v1/place?key=${placesKey}&q=${detailsEvent.locationLat},${detailsEvent.locationLng}&zoom=14`
                    }
                  />
                ) : placesProvider === "osm" &&
                  detailsEvent.locationLat &&
                  detailsEvent.locationLng ? (
                  <iframe
                    title="Karte"
                    className="h-[320px] w-full"
                    loading="lazy"
                    src={`https://www.openstreetmap.org/export/embed.html?bbox=${
                      detailsEvent.locationLng - 0.0045
                    },${detailsEvent.locationLat - 0.0045},${
                      detailsEvent.locationLng + 0.0045
                    },${detailsEvent.locationLat + 0.0045}&layer=mapnik&marker=${detailsEvent.locationLat},${detailsEvent.locationLng}`}
                  />
                ) : (
                  <div className="flex h-full items-center justify-center text-sm text-slate-500">
                    Keine Karte verfügbar.
                  </div>
                )}
              </div>
            </div>
          </div>
        </div>
      )}
    </section>
  );
}

function formatLocation(value?: string | null) {
  if (!value) return "-";
  const parts = value.split(",").map((part) => part.trim()).filter(Boolean);
  if (parts.length === 0) return value;
  const postal = parts.find((part) => /\b\d{5}\b/.test(part));
  const street = parts[0] || "";
  const city = parts[1] || "";
  if (postal && city) {
    return street ? `${street}, ${postal} ${city}` : `${postal} ${city}`;
  }
  if (postal) {
    return street ? `${street}, ${postal}` : postal;
  }
  const main = parts.slice(0, 2).join(", ");
  return main || value;
}

function StatusIcon({ status }: { status: string }) {
  if (status === "APPROVED") {
    return (
      <span title="Freigegeben" aria-label="Freigegeben" className="text-emerald-600">
        <svg viewBox="0 0 24 24" className="h-4 w-4" fill="none" stroke="currentColor" strokeWidth="2">
          <path d="M5 12l4 4L19 6" strokeLinecap="round" strokeLinejoin="round" />
        </svg>
      </span>
    );
  }
  if (status === "REJECTED") {
    return (
      <span title="Abgelehnt" aria-label="Abgelehnt" className="text-red-600">
        <svg viewBox="0 0 24 24" className="h-4 w-4" fill="none" stroke="currentColor" strokeWidth="2">
          <path d="M6 6l12 12M18 6l-12 12" strokeLinecap="round" />
        </svg>
      </span>
    );
  }
  return (
    <span title="Offen" aria-label="Offen" className="text-amber-600">
      <svg viewBox="0 0 24 24" className="h-4 w-4" fill="none" stroke="currentColor" strokeWidth="2">
        <path d="M12 6v6l4 2" strokeLinecap="round" strokeLinejoin="round" />
        <circle cx="12" cy="12" r="9" />
      </svg>
    </span>
  );
}

function ViewToggleButton({
  isSelected,
  onClick,
  size = "md"
}: {
  isSelected: boolean;
  onClick: (event: React.MouseEvent<HTMLButtonElement>) => void;
  size?: "sm" | "md";
}) {
  const base =
    size === "sm"
      ? "event-toggle rounded-full bg-white/80 px-2 py-1 text-[10px] text-slate-700"
      : "rounded-full border border-slate-200 px-3 py-1 text-xs text-slate-700";
  return (
    <button
      type="button"
      className={base}
      onClick={onClick}
      aria-label={isSelected ? "In Ansicht" : "Ausblenden"}
      title={isSelected ? "In Ansicht" : "Ausblenden"}
    >
      {isSelected ? <IconBell /> : <IconSleep />}
    </button>
  );
}

function IconBell() {
  return (
    <svg viewBox="0 0 24 24" className="h-4 w-4" fill="none" stroke="currentColor" strokeWidth="2">
      <path d="M6 8a6 6 0 1112 0c0 7 2 7 2 7H4s2 0 2-7" strokeLinecap="round" strokeLinejoin="round" />
      <path d="M10 19a2 2 0 004 0" strokeLinecap="round" />
    </svg>
  );
}

function IconSleep() {
  return (
    <svg viewBox="0 0 24 24" className="h-4 w-4" fill="none" stroke="currentColor" strokeWidth="2">
      <path d="M3 5h6l-6 6h6" strokeLinecap="round" strokeLinejoin="round" />
      <path d="M9 9h6l-6 6h6" strokeLinecap="round" strokeLinejoin="round" />
      <path d="M15 13h6l-6 6h6" strokeLinecap="round" strokeLinejoin="round" />
    </svg>
  );
}

function IconGrip() {
  return (
    <svg viewBox="0 0 24 24" className="h-4 w-4" fill="none" stroke="currentColor" strokeWidth="2">
      <circle cx="8" cy="6" r="1" />
      <circle cx="16" cy="6" r="1" />
      <circle cx="8" cy="12" r="1" />
      <circle cx="16" cy="12" r="1" />
      <circle cx="8" cy="18" r="1" />
      <circle cx="16" cy="18" r="1" />
    </svg>
  );
}

function IconChevronDown() {
  return (
    <svg viewBox="0 0 24 24" className="h-4 w-4" fill="none" stroke="currentColor" strokeWidth="2">
      <path d="M6 9l6 6 6-6" strokeLinecap="round" strokeLinejoin="round" />
    </svg>
  );
}

function IconChevronUp() {
  return (
    <svg viewBox="0 0 24 24" className="h-4 w-4" fill="none" stroke="currentColor" strokeWidth="2">
      <path d="M6 15l6-6 6 6" strokeLinecap="round" strokeLinejoin="round" />
    </svg>
  );
}

function SortButton({
  label,
  active,
  direction,
  onClick
}: {
  label: string;
  active: boolean;
  direction: "asc" | "desc";
  onClick: () => void;
}) {
  return (
    <button
      type="button"
      onClick={onClick}
      className={`inline-flex items-center gap-1 text-xs uppercase tracking-[0.2em] ${
        active ? "text-slate-900" : "text-slate-500"
      }`}
      title="Sortieren"
    >
      {label}
      <SortIcon direction={direction} active={active} />
    </button>
  );
}

function SortIcon({
  direction,
  active
}: {
  direction: "asc" | "desc";
  active: boolean;
}) {
  return (
    <svg
      viewBox="0 0 24 24"
      className={`h-3 w-3 ${active ? "opacity-100" : "opacity-40"}`}
      fill="none"
      stroke="currentColor"
      strokeWidth="2"
    >
      {direction === "asc" ? (
        <path d="M6 15l6-6 6 6" strokeLinecap="round" strokeLinejoin="round" />
      ) : (
        <path d="M6 9l6 6 6-6" strokeLinecap="round" strokeLinejoin="round" />
      )}
    </svg>
  );
}

function IconMapPin() {
  return (
    <svg viewBox="0 0 24 24" className="h-4 w-4" fill="none" stroke="currentColor" strokeWidth="2">
      <path d="M12 21s6-6.5 6-11a6 6 0 10-12 0c0 4.5 6 11 6 11z" strokeLinecap="round" strokeLinejoin="round" />
      <circle cx="12" cy="10" r="2.5" />
    </svg>
  );
}
