"use client";

import { useEffect, useRef, useState } from "react";
import { api } from "@/lib/api";
import { slugify } from "@/lib/utils";
import { cn } from "@/lib/utils";
import {
  Plus,
  Pencil,
  Trash2,
  X,
  Image as ImageIcon,
  Copy,
  MoreHorizontal,
  Star,
  Eye,
  EyeOff,
  CheckSquare,
  Square,
  ChevronUp,
  ChevronDown,
  Link as LinkIcon,
  Check,
} from "lucide-react";
import { MediaPickerModal } from "@/components/admin/MediaPickerModal";
import { formatMeetupCivilDateLong, getMeetupStartUtc } from "@/lib/meetupEventTime";

interface Meetup {
  id: string;
  title: string;
  description: string;
  date: string;
  time: string;
  location: string;
  link?: string;
  imageId?: string;
  status: string;
  featured: boolean;
  visibility: string;
  organizerId?: string;
  organizer?: { id: string; name: string; slug: string };
  createdAt: string;
  updatedAt: string;
}

interface MeetupForm {
  title: string;
  description: string;
  date: string;
  time: string;
  location: string;
  link: string;
  imageId: string;
  status: string;
  featured: boolean;
  visibility: string;
  organizerId: string;
}

const emptyForm: MeetupForm = {
  title: "",
  description: "",
  date: "",
  time: "",
  location: "",
  link: "",
  imageId: "",
  status: "DRAFT",
  featured: false,
  visibility: "PUBLIC",
  organizerId: "",
};

function defaultOrganizerId(organizers: { id: string; slug: string }[]): string {
  return (
    organizers.find((o) => o.slug === "belgian-bitcoin-embassy")?.id ||
    organizers[0]?.id ||
    ""
  );
}

// Statuses that can be manually set by an admin
const EDITABLE_STATUS_OPTIONS = ["DRAFT", "PUBLISHED", "CANCELLED"] as const;
type EditableStatus = (typeof EDITABLE_STATUS_OPTIONS)[number];

// Display statuses (includes computed Upcoming/Past from PUBLISHED + date)
type DisplayStatus = "DRAFT" | "UPCOMING" | "PAST" | "CANCELLED";

function getDisplayStatus(meetup: { status: string; date: string; time: string }): DisplayStatus {
  if (meetup.status === "CANCELLED") return "CANCELLED";
  if (meetup.status === "DRAFT") return "DRAFT";
  // PUBLISHED (or legacy UPCOMING/PAST values) → derive from Brussels-local start (date + time)
  if (!meetup.date?.trim()) return "DRAFT";
  const start = getMeetupStartUtc(meetup.date, meetup.time || "00:00");
  if (Number.isNaN(start.getTime())) return "DRAFT";
  return start > new Date() ? "UPCOMING" : "PAST";
}

const STATUS_LABELS: Record<string, string> = {
  DRAFT: "Draft",
  PUBLISHED: "Published",
  UPCOMING: "Upcoming",
  PAST: "Past",
  CANCELLED: "Cancelled",
};

// Badge styles use the computed display status
const DISPLAY_STATUS_STYLES: Record<DisplayStatus, string> = {
  DRAFT: "bg-surface-container-highest text-on-surface/60",
  UPCOMING: "bg-green-900/40 text-green-400",
  PAST: "bg-surface-container-highest text-on-surface/40",
  CANCELLED: "bg-red-900/30 text-red-400",
};

function useOutsideClick(ref: React.RefObject<HTMLElement | null>, callback: () => void) {
  useEffect(() => {
    function handleClick(e: MouseEvent) {
      if (ref.current && !ref.current.contains(e.target as Node)) {
        callback();
      }
    }
    document.addEventListener("mousedown", handleClick);
    return () => document.removeEventListener("mousedown", handleClick);
  }, [ref, callback]);
}

function MoreMenu({
  meetup,
  onCopyUrl,
}: {
  meetup: Meetup;
  onCopyUrl: () => void;
}) {
  const [open, setOpen] = useState(false);
  const [copied, setCopied] = useState(false);
  const ref = useRef<HTMLDivElement>(null);
  useOutsideClick(ref, () => setOpen(false));

  const handleCopy = () => {
    onCopyUrl();
    setCopied(true);
    setTimeout(() => {
      setCopied(false);
      setOpen(false);
    }, 1500);
  };

  return (
    <div className="relative" ref={ref}>
      <button
        onClick={() => setOpen((v) => !v)}
        className="p-2 rounded-lg hover:bg-surface-container-high text-on-surface/60 hover:text-on-surface transition-colors"
        title="More options"
      >
        <MoreHorizontal size={16} />
      </button>
      {open && (
        <div className="absolute right-0 top-full mt-1 z-50 w-48 bg-surface-container-low border border-surface-container-highest rounded-xl shadow-lg overflow-hidden">
          <button
            onClick={handleCopy}
            className="flex items-center gap-2 w-full px-4 py-3 text-sm text-on-surface/80 hover:bg-surface-container-high hover:text-on-surface transition-colors"
          >
            {copied ? <Check size={14} className="text-green-400" /> : <LinkIcon size={14} />}
            {copied ? "Copied!" : "Copy Event URL"}
          </button>
        </div>
      )}
    </div>
  );
}

function StatusDropdown({
  meetup,
  onChange,
}: {
  meetup: { status: string; date: string; time: string };
  onChange: (v: string) => void;
}) {
  const [open, setOpen] = useState(false);
  const ref = useRef<HTMLDivElement>(null);
  useOutsideClick(ref, () => setOpen(false));

  const displayStatus = getDisplayStatus(meetup);

  return (
    <div className="relative" ref={ref}>
      <button
        onClick={() => setOpen((v) => !v)}
        className={cn(
          "rounded-full px-3 py-1 text-xs font-bold cursor-pointer hover:opacity-80 transition-opacity",
          DISPLAY_STATUS_STYLES[displayStatus]
        )}
      >
        {STATUS_LABELS[displayStatus]}
      </button>
      {open && (
        <div className="absolute left-0 top-full mt-1 z-50 w-36 bg-surface-container-low border border-surface-container-highest rounded-xl shadow-lg overflow-hidden">
          {EDITABLE_STATUS_OPTIONS.map((s) => (
            <button
              key={s}
              onClick={() => {
                onChange(s);
                setOpen(false);
              }}
              className={cn(
                "flex items-center gap-2 w-full px-3 py-2 text-xs font-bold transition-colors hover:bg-surface-container-high",
                meetup.status === s ? "text-on-surface" : "text-on-surface/60"
              )}
            >
              <span className={cn("w-2 h-2 rounded-full", {
                "bg-on-surface/40": s === "DRAFT",
                "bg-green-400": s === "PUBLISHED",
                "bg-red-400": s === "CANCELLED",
              })} />
              {STATUS_LABELS[s]}
            </button>
          ))}
        </div>
      )}
    </div>
  );
}

export default function EventsPage() {
  const [meetups, setMeetups] = useState<Meetup[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState("");
  const [showForm, setShowForm] = useState(false);
  const [editingId, setEditingId] = useState<string | null>(null);
  const [form, setForm] = useState<MeetupForm>(emptyForm);
  const [saving, setSaving] = useState(false);
  const [showMediaPicker, setShowMediaPicker] = useState(false);
  const formRef = useRef<HTMLDivElement>(null);

  // Filters
  const [filterStatus, setFilterStatus] = useState("ALL");
  const [filterCity, setFilterCity] = useState("ALL");
  const [sortDir, setSortDir] = useState<"asc" | "desc">("asc");

  // Bulk selection
  const [selected, setSelected] = useState<Set<string>>(new Set());
  const [bulkLoading, setBulkLoading] = useState(false);

  const [organizers, setOrganizers] = useState<{ id: string; name: string; slug: string }[]>([]);
  const [showAddOrganizer, setShowAddOrganizer] = useState(false);
  const [newOrgName, setNewOrgName] = useState("");
  const [newOrgSlug, setNewOrgSlug] = useState("");
  const [savingOrganizer, setSavingOrganizer] = useState(false);

  const loadMeetups = async () => {
    try {
      const [data, orgs] = await Promise.all([
        api.getMeetups({ admin: true }),
        api.getOrganizers(),
      ]);
      setMeetups(data as Meetup[]);
      setOrganizers(orgs);
    } catch (err: any) {
      setError(err.message);
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    loadMeetups();
  }, []);

  const openCreate = () => {
    setForm({ ...emptyForm, organizerId: defaultOrganizerId(organizers) });
    setShowAddOrganizer(false);
    setNewOrgName("");
    setNewOrgSlug("");
    setEditingId(null);
    setShowForm(true);
    setTimeout(() => formRef.current?.scrollIntoView({ behavior: "smooth", block: "start" }), 50);
  };

  const handleCreateOrganizer = async () => {
    const slug = newOrgSlug.trim() || slugify(newOrgName);
    if (!newOrgName.trim() || !slug) return;
    setSavingOrganizer(true);
    setError("");
    try {
      const o = await api.createOrganizer({ name: newOrgName.trim(), slug });
      setOrganizers((prev) => [...prev, o].sort((a, b) => a.name.localeCompare(b.name)));
      setForm((f) => ({ ...f, organizerId: o.id }));
      setShowAddOrganizer(false);
      setNewOrgName("");
      setNewOrgSlug("");
    } catch (err: any) {
      setError(err.message);
    } finally {
      setSavingOrganizer(false);
    }
  };

  const openEdit = (meetup: Meetup) => {
    setShowAddOrganizer(false);
    setNewOrgName("");
    setNewOrgSlug("");
    setForm({
      title: meetup.title,
      description: meetup.description || "",
      date: meetup.date?.split("T")[0] || meetup.date || "",
      time: meetup.time || "",
      location: meetup.location || "",
      link: meetup.link || "",
      imageId: meetup.imageId || "",
      status: meetup.status || "DRAFT",
      featured: meetup.featured || false,
      visibility: meetup.visibility || "PUBLIC",
      organizerId: meetup.organizerId || meetup.organizer?.id || defaultOrganizerId(organizers),
    });
    setEditingId(meetup.id);
    setShowForm(true);
    setTimeout(() => formRef.current?.scrollIntoView({ behavior: "smooth", block: "start" }), 50);
  };

  const handleSave = async () => {
    setSaving(true);
    setError("");
    try {
      const payload = {
        title: form.title,
        description: form.description,
        date: form.date,
        time: form.time || "00:00",
        location: form.location,
        link: form.link,
        imageId: form.imageId || null,
        status: form.status,
        featured: form.featured,
        visibility: form.visibility,
        organizerId: form.organizerId || undefined,
      };

      if (editingId) {
        const updated = await api.updateMeetup(editingId, payload);
        setMeetups((prev) => prev.map((m) => (m.id === editingId ? updated : m)));
      } else {
        const created = await api.createMeetup(payload);
        setMeetups((prev) => [...prev, created]);
      }
      setShowForm(false);
      setEditingId(null);
    } catch (err: any) {
      setError(err.message);
    } finally {
      setSaving(false);
    }
  };

  const handleDelete = async (id: string) => {
    if (!confirm("Delete this meetup?")) return;
    setMeetups((prev) => prev.filter((m) => m.id !== id));
    try {
      await api.deleteMeetup(id);
    } catch (err: any) {
      setError(err.message);
      await loadMeetups();
    }
  };

  const handleDuplicate = async (id: string) => {
    try {
      const dup = await api.duplicateMeetup(id);
      setMeetups((prev) => [dup, ...prev]);
      openEdit(dup);
    } catch (err: any) {
      setError(err.message);
    }
  };

  const handlePatch = async (id: string, patch: Partial<Meetup>) => {
    setMeetups((prev) => prev.map((m) => (m.id === id ? { ...m, ...patch } : m)));
    try {
      await api.updateMeetup(id, patch);
    } catch (err: any) {
      setError(err.message);
      await loadMeetups();
    }
  };

  const handleCopyUrl = (meetup: Meetup) => {
    const origin = typeof window !== "undefined" ? window.location.origin : "";
    navigator.clipboard.writeText(`${origin}/events/${meetup.id}`);
  };

  const toggleSelect = (id: string) => {
    setSelected((prev) => {
      const next = new Set(prev);
      if (next.has(id)) next.delete(id);
      else next.add(id);
      return next;
    });
  };

  const selectAll = () => {
    if (selected.size === filtered.length) {
      setSelected(new Set());
    } else {
      setSelected(new Set(filtered.map((m) => m.id)));
    }
  };

  const handleBulk = async (action: "delete" | "publish" | "duplicate") => {
    if (selected.size === 0) return;
    if (action === "delete" && !confirm(`Delete ${selected.size} meetup(s)?`)) return;
    setBulkLoading(true);
    try {
      const ids = Array.from(selected);
      if (action === "delete") {
        await api.bulkMeetupAction("delete", ids);
        setMeetups((prev) => prev.filter((m) => !ids.includes(m.id)));
      } else if (action === "publish") {
        await api.bulkMeetupAction("publish", ids);
        setMeetups((prev) => prev.map((m) => (ids.includes(m.id) ? { ...m, status: "PUBLISHED" } : m)));
      } else if (action === "duplicate") {
        const result = await api.bulkMeetupAction("duplicate", ids);
        setMeetups((prev) => [...(result as Meetup[]), ...prev]);
      }
      setSelected(new Set());
    } catch (err: any) {
      setError(err.message);
      await loadMeetups();
    } finally {
      setBulkLoading(false);
    }
  };

  // Derived: unique cities
  const cities = Array.from(new Set(meetups.map((m) => m.location).filter(Boolean))).sort();

  // Filter tabs use computed display status
  const FILTER_STATUS_OPTIONS: Array<{ value: string; label: string }> = [
    { value: "ALL", label: "All" },
    { value: "UPCOMING", label: "Upcoming" },
    { value: "PAST", label: "Past" },
    { value: "DRAFT", label: "Draft" },
    { value: "CANCELLED", label: "Cancelled" },
  ];

  // Filtered + sorted
  const filtered = meetups
    .filter((m) => {
      if (filterStatus !== "ALL" && getDisplayStatus(m) !== filterStatus) return false;
      if (filterCity !== "ALL" && m.location !== filterCity) return false;
      return true;
    })
    .sort((a, b) => {
      const da = a.date || "";
      const db = b.date || "";
      return sortDir === "asc" ? da.localeCompare(db) : db.localeCompare(da);
    });

  const allSelected = filtered.length > 0 && selected.size === filtered.length;

  if (loading) {
    return (
      <div className="flex items-center justify-center min-h-[60vh]">
        <div className="text-on-surface/50">Loading meetups...</div>
      </div>
    );
  }

  return (
    <div className="space-y-5">
      {/* Header */}
      <div className="flex items-center justify-between">
        <h1 className="text-2xl font-bold text-on-surface">Events</h1>
        <button
          onClick={openCreate}
          className="flex items-center gap-2 px-4 py-2 rounded-lg bg-gradient-to-r from-primary to-primary-container text-on-primary font-semibold text-sm hover:opacity-90 transition-opacity"
        >
          <Plus size={16} />
          New Event
        </button>
      </div>

      {error && (
        <div className="flex items-center justify-between bg-error-container/20 text-error text-sm px-4 py-3 rounded-lg">
          <span>{error}</span>
          <button onClick={() => setError("")}>
            <X size={14} />
          </button>
        </div>
      )}

      {/* Create / Edit Form */}
      {showForm && (
        <div ref={formRef} className="bg-surface-container-low rounded-xl p-6">
          <div className="flex items-center justify-between mb-5">
            <h2 className="text-lg font-semibold text-on-surface">
              {editingId ? "Edit Event" : "New Event"}
            </h2>
            <button
              onClick={() => setShowForm(false)}
              className="text-on-surface/50 hover:text-on-surface"
            >
              <X size={20} />
            </button>
          </div>
          <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
            <input
              placeholder="Title (e.g. #54 Belgian Bitcoin Embassy Meetup)"
              value={form.title}
              onChange={(e) => setForm({ ...form, title: e.target.value })}
              className="bg-surface-container-highest text-on-surface rounded-lg px-4 py-3 w-full focus:outline-none focus:ring-1 focus:ring-primary/40 md:col-span-2"
            />
            <input
              placeholder="Location"
              value={form.location}
              onChange={(e) => setForm({ ...form, location: e.target.value })}
              className="bg-surface-container-highest text-on-surface rounded-lg px-4 py-3 w-full focus:outline-none focus:ring-1 focus:ring-primary/40"
            />
            <input
              type="date"
              value={form.date}
              onChange={(e) => setForm({ ...form, date: e.target.value })}
              className="bg-surface-container-highest text-on-surface rounded-lg px-4 py-3 w-full focus:outline-none focus:ring-1 focus:ring-primary/40"
            />
            <input
              type="time"
              value={form.time}
              onChange={(e) => setForm({ ...form, time: e.target.value })}
              className="bg-surface-container-highest text-on-surface rounded-lg px-4 py-3 w-full focus:outline-none focus:ring-1 focus:ring-primary/40"
            />
            <div>
              <label className="text-on-surface/60 text-xs mb-2 block">Status</label>
              <select
                value={form.status}
                onChange={(e) => setForm({ ...form, status: e.target.value })}
                className="bg-surface-container-highest text-on-surface rounded-lg px-4 py-3 w-full focus:outline-none focus:ring-1 focus:ring-primary/40"
              >
                {EDITABLE_STATUS_OPTIONS.map((s) => (
                  <option key={s} value={s}>
                    {STATUS_LABELS[s]}
                  </option>
                ))}
              </select>
            </div>
            <div>
              <label className="text-on-surface/60 text-xs mb-2 block">Visibility</label>
              <select
                value={form.visibility}
                onChange={(e) => setForm({ ...form, visibility: e.target.value })}
                className="bg-surface-container-highest text-on-surface rounded-lg px-4 py-3 w-full focus:outline-none focus:ring-1 focus:ring-primary/40"
              >
                <option value="PUBLIC">Public</option>
                <option value="HIDDEN">Hidden</option>
              </select>
            </div>
            <div className="md:col-span-2 space-y-3">
              <label className="text-on-surface/60 text-xs block">Organizer</label>
              <div className="flex flex-col sm:flex-row gap-3 sm:items-center">
                <select
                  value={form.organizerId}
                  onChange={(e) => setForm({ ...form, organizerId: e.target.value })}
                  className="bg-surface-container-highest text-on-surface rounded-lg px-4 py-3 w-full sm:flex-1 focus:outline-none focus:ring-1 focus:ring-primary/40"
                >
                  {organizers.length === 0 ? (
                    <option value="">No organizers — add one in Organizers</option>
                  ) : (
                    organizers.map((o) => (
                      <option key={o.id} value={o.id}>
                        {o.name}
                      </option>
                    ))
                  )}
                </select>
                <button
                  type="button"
                  onClick={() => setShowAddOrganizer((v) => !v)}
                  className="px-4 py-2 rounded-lg bg-surface-container-highest text-on-surface/80 hover:text-on-surface text-sm font-medium shrink-0"
                >
                  {showAddOrganizer ? "Cancel add" : "Add new organizer"}
                </button>
              </div>
              {showAddOrganizer && (
                <div className="rounded-lg border border-surface-container-highest p-4 space-y-3">
                  <input
                    placeholder="Organizer name"
                    value={newOrgName}
                    onChange={(e) => {
                      const name = e.target.value;
                      setNewOrgName(name);
                      setNewOrgSlug(slugify(name));
                    }}
                    className="bg-surface-container-highest text-on-surface rounded-lg px-4 py-3 w-full focus:outline-none focus:ring-1 focus:ring-primary/40"
                  />
                  <input
                    placeholder="URL slug"
                    value={newOrgSlug}
                    onChange={(e) => setNewOrgSlug(e.target.value)}
                    className="bg-surface-container-highest text-on-surface rounded-lg px-4 py-3 w-full focus:outline-none focus:ring-1 focus:ring-primary/40"
                  />
                  <button
                    type="button"
                    onClick={handleCreateOrganizer}
                    disabled={savingOrganizer || !newOrgName.trim()}
                    className="px-4 py-2 rounded-lg bg-primary/20 text-primary font-semibold text-sm hover:bg-primary/30 disabled:opacity-50"
                  >
                    {savingOrganizer ? "Creating…" : "Create and select"}
                  </button>
                </div>
              )}
            </div>
            <div className="md:col-span-2">
              <label className="text-on-surface/60 text-xs mb-2 block">
                External registration link{" "}
                <span className="text-on-surface/40">(optional)</span>
              </label>
              <input
                placeholder="https://..."
                value={form.link}
                onChange={(e) => setForm({ ...form, link: e.target.value })}
                className="bg-surface-container-highest text-on-surface rounded-lg px-4 py-3 w-full focus:outline-none focus:ring-1 focus:ring-primary/40"
              />
            </div>
            <textarea
              placeholder="Description"
              value={form.description}
              onChange={(e) => setForm({ ...form, description: e.target.value })}
              rows={3}
              className="bg-surface-container-highest text-on-surface rounded-lg px-4 py-3 w-full focus:outline-none focus:ring-1 focus:ring-primary/40 md:col-span-2"
            />
            <div className="md:col-span-2">
              <label className="text-on-surface/60 text-xs mb-2 block">
                Event image <span className="text-on-surface/40">(optional)</span>
              </label>
              <div className="flex items-center gap-3">
                {form.imageId && (
                  <div className="relative w-20 h-20 rounded-lg overflow-hidden bg-surface-container-highest shrink-0">
                    <img
                      src={`/media/${form.imageId}?w=200`}
                      alt="Selected"
                      className="w-full h-full object-cover"
                    />
                  </div>
                )}
                <button
                  type="button"
                  onClick={() => setShowMediaPicker(true)}
                  className="flex items-center gap-2 px-4 py-2 rounded-lg bg-surface-container-highest text-on-surface/70 hover:text-on-surface text-sm transition-colors"
                >
                  <ImageIcon size={16} />
                  {form.imageId ? "Change Image" : "Select Image"}
                </button>
                {form.imageId && (
                  <button
                    type="button"
                    onClick={() => setForm({ ...form, imageId: "" })}
                    className="px-3 py-2 rounded-lg text-error/70 hover:text-error text-sm transition-colors"
                  >
                    Remove
                  </button>
                )}
              </div>
            </div>
          </div>

          <div className="flex items-center gap-4 mt-4 pt-4 border-t border-surface-container-highest">
            <label className="flex items-center gap-2 cursor-pointer select-none">
              <input
                type="checkbox"
                checked={form.featured}
                onChange={(e) => setForm({ ...form, featured: e.target.checked })}
                className="hidden"
              />
              <span
                className={cn(
                  "flex items-center gap-1.5 text-sm transition-colors",
                  form.featured ? "text-primary" : "text-on-surface/50 hover:text-on-surface"
                )}
              >
                <Star size={15} className={form.featured ? "fill-primary" : ""} />
                Featured
              </span>
            </label>
          </div>

          <div className="flex gap-3 mt-4">
            <button
              onClick={handleSave}
              disabled={
                saving ||
                !form.title ||
                !form.date ||
                (!editingId && !form.organizerId)
              }
              className="px-6 py-2 rounded-lg bg-gradient-to-r from-primary to-primary-container text-on-primary font-semibold text-sm hover:opacity-90 transition-opacity disabled:opacity-50"
            >
              {saving ? "Saving..." : "Save"}
            </button>
            <button
              onClick={() => setShowForm(false)}
              className="px-6 py-2 rounded-lg bg-surface-container-highest text-on-surface font-semibold text-sm hover:bg-surface-container-high transition-colors"
            >
              Cancel
            </button>
          </div>
        </div>
      )}

      {showMediaPicker && (
        <MediaPickerModal
          selectedId={form.imageId || null}
          onSelect={(id) => {
            setForm({ ...form, imageId: id });
            setShowMediaPicker(false);
          }}
          onClose={() => setShowMediaPicker(false)}
        />
      )}

      {/* Filters */}
      <div className="flex flex-wrap items-center gap-2">
        {/* Status filter */}
        <div className="flex items-center bg-surface-container-low rounded-lg overflow-hidden">
          {FILTER_STATUS_OPTIONS.map(({ value, label }) => (
            <button
              key={value}
              onClick={() => setFilterStatus(value)}
              className={cn(
                "px-3 py-1.5 text-xs font-semibold transition-colors",
                filterStatus === value
                  ? "bg-primary text-on-primary"
                  : "text-on-surface/60 hover:text-on-surface hover:bg-surface-container-high"
              )}
            >
              {label}
            </button>
          ))}
        </div>

        {/* City filter */}
        {cities.length > 1 && (
          <select
            value={filterCity}
            onChange={(e) => setFilterCity(e.target.value)}
            className="bg-surface-container-low text-on-surface/70 text-xs rounded-lg px-3 py-1.5 focus:outline-none focus:ring-1 focus:ring-primary/40"
          >
            <option value="ALL">All cities</option>
            {cities.map((c) => (
              <option key={c} value={c}>
                {c}
              </option>
            ))}
          </select>
        )}

        {/* Sort */}
        <button
          onClick={() => setSortDir((d) => (d === "asc" ? "desc" : "asc"))}
          className="flex items-center gap-1.5 px-3 py-1.5 text-xs font-semibold text-on-surface/60 hover:text-on-surface bg-surface-container-low rounded-lg transition-colors"
        >
          {sortDir === "asc" ? <ChevronUp size={12} /> : <ChevronDown size={12} />}
          Date
        </button>

        <span className="ml-auto text-xs text-on-surface/40">
          {filtered.length} event{filtered.length !== 1 ? "s" : ""}
        </span>
      </div>

      {/* Bulk action bar */}
      {selected.size > 0 && (
        <div className="flex items-center gap-3 bg-surface-container-low rounded-xl px-4 py-3 border border-primary/20">
          <span className="text-sm text-on-surface/70 font-medium">
            {selected.size} selected
          </span>
          <div className="flex items-center gap-2 ml-auto">
            <button
              onClick={() => handleBulk("duplicate")}
              disabled={bulkLoading}
              className="flex items-center gap-1.5 px-3 py-1.5 text-xs font-semibold rounded-lg bg-surface-container-high text-on-surface/70 hover:text-on-surface transition-colors disabled:opacity-50"
            >
              <Copy size={12} />
              Duplicate
            </button>
            <button
              onClick={() => handleBulk("publish")}
              disabled={bulkLoading}
              className="flex items-center gap-1.5 px-3 py-1.5 text-xs font-semibold rounded-lg bg-surface-container-high text-on-surface/70 hover:text-on-surface transition-colors disabled:opacity-50"
            >
              Publish
            </button>
            <button
              onClick={() => handleBulk("delete")}
              disabled={bulkLoading}
              className="flex items-center gap-1.5 px-3 py-1.5 text-xs font-semibold rounded-lg bg-error-container/20 text-error/70 hover:text-error transition-colors disabled:opacity-50"
            >
              <Trash2 size={12} />
              Delete
            </button>
            <button
              onClick={() => setSelected(new Set())}
              className="ml-1 text-on-surface/40 hover:text-on-surface"
            >
              <X size={14} />
            </button>
          </div>
        </div>
      )}

      {/* Event list */}
      <div className="space-y-2">
        {filtered.length === 0 ? (
          <p className="text-on-surface/50 text-sm py-8 text-center">No events found.</p>
        ) : (
          <>
            {/* Select-all row */}
            <div className="flex items-center gap-2 px-2 pb-1">
              <button
                onClick={selectAll}
                className="text-on-surface/40 hover:text-on-surface transition-colors"
                title={allSelected ? "Deselect all" : "Select all"}
              >
                {allSelected ? <CheckSquare size={15} /> : <Square size={15} />}
              </button>
              <span className="text-xs text-on-surface/40">
                {allSelected ? "Deselect all" : "Select all"}
              </span>
            </div>

            {filtered.map((meetup) => (
              <div
                key={meetup.id}
                className={cn(
                  "bg-surface-container-low rounded-xl p-4 flex items-center gap-3 transition-colors",
                  selected.has(meetup.id) && "ring-1 ring-primary/30 bg-surface-container"
                )}
              >
                {/* Checkbox */}
                <button
                  onClick={() => toggleSelect(meetup.id)}
                  className="shrink-0 text-on-surface/40 hover:text-on-surface transition-colors"
                >
                  {selected.has(meetup.id) ? (
                    <CheckSquare size={16} className="text-primary" />
                  ) : (
                    <Square size={16} />
                  )}
                </button>

                {/* Image */}
                {meetup.imageId ? (
                  <div className="w-14 h-14 rounded-lg overflow-hidden bg-surface-container-highest shrink-0">
                    <img
                      src={`/media/${meetup.imageId}?w=100`}
                      alt=""
                      className="w-full h-full object-cover"
                    />
                  </div>
                ) : (
                  <div className="w-14 h-14 rounded-lg bg-surface-container-highest shrink-0 flex items-center justify-center">
                    <ImageIcon size={18} className="text-on-surface/20" />
                  </div>
                )}

                {/* Info */}
                <div className="flex-1 min-w-0">
                  <div className="flex flex-wrap items-center gap-2 mb-1">
                    <h3 className="text-on-surface font-semibold truncate">{meetup.title}</h3>
                    {meetup.featured && (
                      <Star size={12} className="text-primary fill-primary shrink-0" />
                    )}
                    {meetup.visibility === "HIDDEN" && (
                      <EyeOff size={12} className="text-on-surface/40 shrink-0" />
                    )}
                  </div>
                  {meetup.organizer?.name && (
                    <p className="text-on-surface/40 text-xs mb-1 truncate">
                      {meetup.organizer.name}
                    </p>
                  )}
                  <div className="flex flex-wrap items-center gap-2">
                    <StatusDropdown
                      meetup={meetup}
                      onChange={(v) => handlePatch(meetup.id, { status: v })}
                    />
                    <span className="text-on-surface/50 text-xs">
                      {meetup.date ? formatMeetupCivilDateLong(meetup.date) : "No date"}
                      {meetup.location && ` · ${meetup.location}`}
                    </span>
                  </div>
                </div>

                {/* Actions */}
                <div className="flex items-center gap-1 shrink-0">
                  {/* Featured toggle */}
                  <button
                    onClick={() => handlePatch(meetup.id, { featured: !meetup.featured })}
                    className={cn(
                      "p-2 rounded-lg transition-colors",
                      meetup.featured
                        ? "text-primary hover:text-primary/70"
                        : "text-on-surface/30 hover:text-on-surface hover:bg-surface-container-high"
                    )}
                    title={meetup.featured ? "Unfeature" : "Feature"}
                  >
                    <Star size={15} className={meetup.featured ? "fill-primary" : ""} />
                  </button>

                  {/* Visibility toggle */}
                  <button
                    onClick={() =>
                      handlePatch(meetup.id, {
                        visibility: meetup.visibility === "PUBLIC" ? "HIDDEN" : "PUBLIC",
                      })
                    }
                    className={cn(
                      "p-2 rounded-lg transition-colors",
                      meetup.visibility === "HIDDEN"
                        ? "text-on-surface/30 hover:text-on-surface hover:bg-surface-container-high"
                        : "text-on-surface/60 hover:text-on-surface hover:bg-surface-container-high"
                    )}
                    title={meetup.visibility === "PUBLIC" ? "Hide event" : "Make public"}
                  >
                    {meetup.visibility === "HIDDEN" ? <EyeOff size={15} /> : <Eye size={15} />}
                  </button>

                  {/* Edit */}
                  <button
                    onClick={() => openEdit(meetup)}
                    className="p-2 rounded-lg hover:bg-surface-container-high text-on-surface/60 hover:text-on-surface transition-colors"
                    title="Edit"
                  >
                    <Pencil size={15} />
                  </button>

                  {/* Duplicate */}
                  <button
                    onClick={() => handleDuplicate(meetup.id)}
                    className="p-2 rounded-lg hover:bg-surface-container-high text-on-surface/60 hover:text-on-surface transition-colors"
                    title="Duplicate"
                  >
                    <Copy size={15} />
                  </button>

                  {/* Delete */}
                  <button
                    onClick={() => handleDelete(meetup.id)}
                    className="p-2 rounded-lg hover:bg-error-container/30 text-on-surface/60 hover:text-error transition-colors"
                    title="Delete"
                  >
                    <Trash2 size={15} />
                  </button>

                  {/* More menu */}
                  <MoreMenu meetup={meetup} onCopyUrl={() => handleCopyUrl(meetup)} />
                </div>
              </div>
            ))}
          </>
        )}
      </div>
    </div>
  );
}
