"use client";
/* eslint-disable react-hooks/set-state-in-effect */

import React, { useState, useTransition, useEffect, useMemo, useCallback, useRef } from "react";
import Link from "next/link";
import { useRouter } from "next/navigation";
import { publishStop, deleteStop } from "@/actions/stops";
import {
  AdminSearchInput,
  AdminFilterTabs,
  AdminButton,
  AdminIconButton,
  AdminViewModeTabs,
  useToast,
  Skeleton,
  AdminPagination,
} from "@/components/admin/design-system";
import ScheduleImportModal from "@/components/admin/ScheduleImportModal";
import EditStopModal from "@/components/admin/EditStopModal";

type Stop = {
  id: string;
  city: string;
  state: string;
  date: string;
  time: string;
  location: string;
  active: boolean;
  brand_id: string;
  status?: string;
  address?: string | null;
  zip?: string | null;
  cutoff_time?: string | null;
  brands: { name: string } | { name: string }[] | null;
};

type Props = {
  stops: Stop[];
  hideInternalFilterBar?: boolean;
};

type ViewMode = "table" | "cards";
type SortField = "date" | "city" | "location" | "status";
type SortDirection = "asc" | "desc";

const TAB_NUMERIC: Record<"all" | "active" | "inactive" | "draft", "all" | "active" | "inactive" | "draft"> = {
  all: "all",
  active: "active",
  inactive: "inactive",
  draft: "draft",
};

// Icons
const Icons = {
  search: (className: string) => (
    <svg className={className} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
      <circle cx="11" cy="11" r="8"/>
      <path d="m21 21-4.3-4.3"/>
    </svg>
  ),
  plus: (className: string) => (
    <svg className={className} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
      <path d="M12 5v14M5 12h14"/>
    </svg>
  ),
  pin: (className: string) => (
    <svg className={className} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
      <path d="M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0Z"/>
      <circle cx="12" cy="10" r="3"/>
    </svg>
  ),
  upload: (className: string) => (
    <svg className={className} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
      <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
      <polyline points="17 8 12 3 7 8"/>
      <line x1="12" y1="3" x2="12" y2="15"/>
    </svg>
  ),
};

// Page header icon
const StopIconHeader = () => (
  <svg className="h-6 w-6" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
    <path d="M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0Z"/>
    <circle cx="12" cy="10" r="3"/>
  </svg>
);

export default function StopTableClient({ stops, hideInternalFilterBar = false }: Props) {
  const router = useRouter();
  const { success: showSuccess, error: showError } = useToast();
  const [, startTransition] = useTransition();
  const [search, setSearch] = useState("");
  const [statusFilter, setStatusFilter] = useState<"all" | "active" | "inactive" | "draft">("all");
  const [deleteError, setDeleteError] = useState<string | null>(null);
  const [page, setPage] = useState(0);
  const [isLoading, setIsLoading] = useState(false);
  const [selectedStops, setSelectedStops] = useState<Set<string>>(new Set());
  const [bulkPublishing, setBulkPublishing] = useState(false);
  const [showImport, setShowImport] = useState(false);
  const [editingStop, setEditingStop] = useState<Stop | null>(null);
  const [showAddModal, setShowAddModal] = useState(false);
  const [sortField, setSortField] = useState<SortField>("date");
  const [sortDirection, setSortDirection] = useState<SortDirection>("asc");
  const [viewMode, setViewMode] = useState<ViewMode>("table");
  const PAGE_SIZE = 25;

  useEffect(() => {
    setIsLoading(true);
    const timer = setTimeout(() => setIsLoading(false), 220);
    return () => clearTimeout(timer);
  }, [page, statusFilter, search, sortField, sortDirection]);

  // Compute stats
  const stats = useMemo(() => {
    const now = new Date();
    const today = now.toISOString().split("T")[0];
    const activeStops = stops.filter((s) => s.active && s.status !== "draft");
    const upcomingStops = stops.filter((s) => s.date >= today && s.status !== "draft");
    const draftStops = stops.filter((s) => s.status === "draft");
    return {
      total: stops.length,
      active: activeStops.length,
      upcoming: upcomingStops.length,
      draft: draftStops.length,
    };
  }, [stops]);

  const filtered = useMemo(() => {
    const q = search.trim().toLowerCase();
    return stops.filter((s) => {
      const matchesSearch =
        !q ||
        s.city.toLowerCase().includes(q) ||
        s.location.toLowerCase().includes(q) ||
        s.state.toLowerCase().includes(q);
      const matchesStatus =
        statusFilter === "all" ||
        (statusFilter === "active" && s.active && s.status !== "draft") ||
        (statusFilter === "inactive" && !s.active && s.status !== "draft") ||
        (statusFilter === "draft" && s.status === "draft");
      return matchesSearch && matchesStatus;
    });
  }, [stops, search, statusFilter]);

  const sorted = useMemo(() => {
    return [...filtered].sort((a, b) => {
      let comparison = 0;
      switch (sortField) {
        case "date":
          comparison = a.date.localeCompare(b.date);
          break;
        case "city":
          comparison = a.city.localeCompare(b.city);
          break;
        case "location":
          comparison = a.location.localeCompare(b.location);
          break;
        case "status":
          const statusOrder = { draft: 0, inactive: 1, active: 2 };
          const aStatus = a.status === "draft" ? "draft" : a.active ? "active" : "inactive";
          const bStatus = b.status === "draft" ? "draft" : b.active ? "active" : "inactive";
          comparison = statusOrder[aStatus] - statusOrder[bStatus];
          break;
      }
      return sortDirection === "asc" ? comparison : -comparison;
    });
  }, [filtered, sortField, sortDirection]);

  const statusCounts = useMemo(
    () => ({
      all: stops.length,
      active: stops.filter((s) => s.active && s.status !== "draft").length,
      inactive: stops.filter((s) => !s.active && s.status !== "draft").length,
      draft: stops.filter((s) => s.status === "draft").length,
    }),
    [stops]
  );

  const tabs = useMemo(
    () => [
      { value: "all", label: "All", count: statusCounts.all },
      { value: "active", label: "Active", count: statusCounts.active },
      { value: "inactive", label: "Inactive", count: statusCounts.inactive },
      { value: "draft", label: "Draft", count: statusCounts.draft },
    ],
    [statusCounts]
  );

  const totalPages = Math.max(1, Math.ceil(sorted.length / PAGE_SIZE));
  const paginatedStops = sorted.slice(page * PAGE_SIZE, (page + 1) * PAGE_SIZE);

  const handleSort = useCallback((field: SortField) => {
    if (sortField === field) {
      setSortDirection((d) => (d === "asc" ? "desc" : "asc"));
    } else {
      setSortField(field);
      setSortDirection("asc");
    }
    setPage(0);
  }, [sortField]);

  const toggleSelectAll = () => {
    if (selectedStops.size === paginatedStops.length) {
      setSelectedStops(new Set());
    } else {
      setSelectedStops(new Set(paginatedStops.map((s) => s.id)));
    }
  };

  const toggleStopSelection = (stopId: string) => {
    setSelectedStops((prev) => {
      const next = new Set(prev);
      if (next.has(stopId)) {
        next.delete(stopId);
      } else {
        next.add(stopId);
      }
      return next;
    });
  };

  async function handleBulkPublish() {
    if (selectedStops.size === 0) return;
    setBulkPublishing(true);
    let successCount = 0;
    let failCount = 0;
    for (const stopId of selectedStops) {
      const stop = stops.find((s) => s.id === stopId);
      if (stop && stop.status === "draft") {
        const result = await publishStop(stopId, stop.brand_id);
        if (result.success) {
          successCount++;
        } else {
          failCount++;
        }
      }
    }
    setBulkPublishing(false);
    setSelectedStops(new Set());
    if (failCount === 0) {
      showSuccess(`${successCount} stop${successCount !== 1 ? "s" : ""} published`);
    } else {
      showError("Some stops failed", `${successCount} succeeded, ${failCount} failed`);
    }
    startTransition(() => router.refresh());
  }

  function handleDeleted() {
    setDeleteError(null);
    startTransition(() => router.refresh());
  }

  function refresh() {
    startTransition(() => router.refresh());
  }

  // Sort icon component
  const SortIcon = ({ field }: { field: SortField }) => (
    <span className={`inline-flex ml-1.5 ${sortField === field ? "opacity-100" : "opacity-30"}`}>
      {sortField === field && sortDirection === "desc" ? (
        <svg className="h-3 w-3" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2.5}>
          <path strokeLinecap="round" strokeLinejoin="round" d="M19 9l-7 7-7-7" />
        </svg>
      ) : (
        <svg className="h-3 w-3" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2.5}>
          <path strokeLinecap="round" strokeLinejoin="round" d="M5 15l7-7 7 7" />
        </svg>
      )}
    </span>
  );

  return (
    <>
      {/* Page Header */}
      <div className="flex items-center justify-between mb-6">
        <div className="flex items-center gap-3">
          <div className="flex h-11 w-11 items-center justify-center rounded-xl bg-[var(--admin-accent)]/10">
            <StopIconHeader />
          </div>
          <div>
            <h1 className="text-xl sm:text-2xl font-bold text-[var(--admin-text-primary)] tracking-tight">
              Stops & Routes
            </h1>
            <p className="text-xs text-[var(--admin-text-muted)]">
              {sorted.length} stop{sorted.length !== 1 ? "s" : ""}
              {search || statusFilter !== "all" ? " matching filters" : ""}
            </p>
          </div>
        </div>
        <div className="flex items-center gap-2">
          <AdminButton
            variant="secondary"
            size="sm"
            onClick={() => setShowImport(true)}
            icon={Icons.upload("h-4 w-4")}
          >
            Upload
          </AdminButton>
          <AdminButton
            variant="primary"
            size="sm"
            onClick={() => setShowAddModal(true)}
            icon={Icons.plus("h-4 w-4")}
          >
            Add Stop
          </AdminButton>
        </div>
      </div>

      {/* Stats Cards */}
      <div className="grid grid-cols-2 gap-3 lg:grid-cols-4 mb-6">
        <div className="bg-white rounded-xl border border-[var(--admin-border)] p-4">
          <p className="text-[10px] sm:text-xs text-[var(--admin-text-muted)] font-medium">Total</p>
          <p className="text-xl sm:text-2xl font-bold text-[var(--admin-text-primary)] mt-1 tabular-nums">
            {isLoading ? <Skeleton variant="text" className="w-12 h-6" /> : stats.total}
          </p>
        </div>
        <div className="bg-white rounded-xl border border-[var(--admin-border)] p-4">
          <p className="text-[10px] sm:text-xs text-[var(--admin-text-muted)] font-medium">Active</p>
          <p className="text-xl sm:text-2xl font-bold text-[var(--admin-accent)] mt-1 tabular-nums">
            {isLoading ? <Skeleton variant="text" className="w-10 h-6" /> : stats.active}
          </p>
        </div>
        <div className="bg-white rounded-xl border border-[var(--admin-border)] p-4">
          <p className="text-[10px] sm:text-xs text-[var(--admin-text-muted)] font-medium">Upcoming</p>
          <p className="text-xl sm:text-2xl font-bold text-sky-600 mt-1 tabular-nums">
            {isLoading ? <Skeleton variant="text" className="w-10 h-6" /> : stats.upcoming}
          </p>
        </div>
        <div className="bg-white rounded-xl border border-[var(--admin-border)] p-4">
          <p className="text-[10px] sm:text-xs text-[var(--admin-text-muted)] font-medium">Drafts</p>
          <p className="text-xl sm:text-2xl font-bold text-stone-400 mt-1 tabular-nums">
            {isLoading ? <Skeleton variant="text" className="w-8 h-6" /> : stats.draft}
          </p>
        </div>
      </div>

      {/* Filters */}
      {!hideInternalFilterBar && (
      <div className="flex flex-col sm:flex-row gap-3 mb-6">
        <AdminFilterTabs
          activeTab={statusFilter}
          onTabChange={(value) => {
            setStatusFilter(TAB_NUMERIC[value as keyof typeof TAB_NUMERIC] ?? "all");
            setPage(0);
          }}
          tabs={tabs}
          size="md"
        />
        <AdminSearchInput
          value={search}
          onChange={(e) => {
            setSearch(e.target.value);
            setPage(0);
          }}
          onClear={() => {
            setSearch("");
            setPage(0);
          }}
          placeholder="Search stops..."
          containerClassName="flex-1"
        />
        <AdminViewModeTabs
          activeTab={viewMode}
          onTabChange={(value) => setViewMode(value as ViewMode)}
        />
      </div>
      )}

      {/* Bulk actions bar */}
      {selectedStops.size > 0 && (
        <div className="mb-4 flex items-center justify-between rounded-xl border border-emerald-200 bg-emerald-50/60 px-4 py-2.5">
          <div className="flex items-center gap-3">
            <span className="text-sm font-semibold text-emerald-800 tabular-nums">
              {selectedStops.size} stop{selectedStops.size !== 1 ? "s" : ""} selected
            </span>
            <button
              onClick={() => setSelectedStops(new Set())}
              className="text-xs text-stone-500 hover:text-stone-700"
            >
              Clear
            </button>
          </div>
          <AdminButton
            variant="primary"
            size="sm"
            onClick={handleBulkPublish}
            isLoading={bulkPublishing}
          >
            Publish Selected
          </AdminButton>
        </div>
      )}

      {/* Delete error */}
      {deleteError && (
        <div className="mb-4 rounded-lg border border-red-500/30 bg-red-50 px-4 py-2.5 text-sm text-red-700">
          {deleteError}{" "}
          <button onClick={() => setDeleteError(null)} className="underline hover:no-underline">
            Dismiss
          </button>
        </div>
      )}

      {/* Content */}
      {viewMode === "table" ? (
        <TableView
          stops={paginatedStops}
          sortField={sortField}
          sortDirection={sortDirection}
          onSort={handleSort}
          onEdit={setEditingStop}
          onDelete={(id) => {
            const stop = stops.find((s) => s.id === id);
            if (stop) {
              setEditingStop(stop);
            }
          }}
          onDeleted={handleDeleted}
          onDeleteError={setDeleteError}
          selectedStops={selectedStops}
          onToggleSelectAll={toggleSelectAll}
          onToggleSelect={toggleStopSelection}
          isLoading={isLoading}
          search={search}
          statusFilter={statusFilter}
        />
      ) : (
        <CardView
          stops={paginatedStops}
          onEdit={setEditingStop}
          onDeleted={handleDeleted}
          onDeleteError={setDeleteError}
          isLoading={isLoading}
          search={search}
          statusFilter={statusFilter}
        />
      )}

      {/* Pagination */}
      {totalPages > 1 && (
        <div className="flex items-center justify-between border-t border-[var(--admin-border)] mt-4 pt-4">
          <span className="text-xs text-[var(--admin-text-muted)]">
            Showing {page * PAGE_SIZE + 1}–{Math.min((page + 1) * PAGE_SIZE, sorted.length)} of {sorted.length}
          </span>
          <AdminPagination
            currentPage={page}
            totalPages={totalPages}
            onPageChange={setPage}
          />
        </div>
      )}

      {showImport && (
        <ScheduleImportModal
          brandId={stops[0]?.brand_id ?? ""}
          onClose={() => setShowImport(false)}
          onComplete={refresh}
        />
      )}

      <EditStopModal
        isOpen={showAddModal || editingStop !== null}
        onClose={() => {
          setShowAddModal(false);
          setEditingStop(null);
        }}
        brandId={stops[0]?.brand_id ?? ""}
        stop={editingStop}
        onSuccess={refresh}
      />
    </>
  );
}

// ── Table View ─────────────────────────────────────────────────────────────────

function TableView({
  stops,
  sortField,
  sortDirection,
  onSort,
  onEdit,
  onDelete,
  onDeleted,
  onDeleteError,
  selectedStops,
  onToggleSelectAll,
  onToggleSelect,
  isLoading,
  search,
  statusFilter,
}: {
  stops: Stop[];
  sortField: SortField;
  sortDirection: SortDirection;
  onSort: (field: SortField) => void;
  onEdit: (stop: Stop) => void;
  onDelete: (id: string) => void;
  onDeleted: () => void;
  onDeleteError: (msg: string) => void;
  selectedStops: Set<string>;
  onToggleSelectAll: () => void;
  onToggleSelect: (id: string) => void;
  isLoading: boolean;
  search: string;
  statusFilter: string;
}) {
  return (
    <div className="overflow-visible rounded-xl border border-[var(--admin-border)] bg-white">
      <table className="w-full text-sm">
        <thead className="bg-stone-50">
          <tr>
            <th className="w-10 px-4 py-3">
              <input
                type="checkbox"
                checked={selectedStops.size === stops.length && stops.length > 0}
                onChange={onToggleSelectAll}
                className="h-4 w-4 rounded border-stone-300 text-emerald-600 focus:ring-emerald-500 cursor-pointer"
                aria-label="Select all"
              />
            </th>
            <th className="text-left px-4 py-3 font-semibold text-[var(--admin-text-muted)] text-xs cursor-pointer hover:text-stone-600 transition-colors" onClick={() => onSort("date")}>
              <span className="inline-flex items-center">
                When
                <SortIcon field="date" sortField={sortField} sortDirection={sortDirection} />
              </span>
            </th>
            <th className="text-left px-4 py-3 font-semibold text-[var(--admin-text-muted)] text-xs cursor-pointer hover:text-stone-600 transition-colors" onClick={() => onSort("city")}>
              <span className="inline-flex items-center">
                Where
                <SortIcon field="city" sortField={sortField} sortDirection={sortDirection} />
              </span>
            </th>
            <th className="text-left px-4 py-3 font-semibold text-[var(--admin-text-muted)] text-xs cursor-pointer hover:text-stone-600 transition-colors" onClick={() => onSort("location")}>
              <span className="inline-flex items-center">
                Venue
                <SortIcon field="location" sortField={sortField} sortDirection={sortDirection} />
              </span>
            </th>
            <th className="text-left px-4 py-3 font-semibold text-[var(--admin-text-muted)] text-xs cursor-pointer hover:text-stone-600 transition-colors" onClick={() => onSort("status")}>
              <span className="inline-flex items-center">
                Status
                <SortIcon field="status" sortField={sortField} sortDirection={sortDirection} />
              </span>
            </th>
            <th className="px-4 py-3" />
          </tr>
        </thead>
        <tbody className="divide-y divide-[var(--admin-border)]">
          {isLoading ? (
            Array.from({ length: 8 }).map((_, i) => (
              <tr key={i}>
                <td className="px-4 py-3.5"><Skeleton variant="rect" className="h-4 w-4" /></td>
                <td className="px-4 py-3.5"><Skeleton variant="text" className="w-24 h-4" /></td>
                <td className="px-4 py-3.5"><Skeleton variant="text" className="w-32 h-4" /></td>
                <td className="px-4 py-3.5"><Skeleton variant="text" className="w-40 h-4" /></td>
                <td className="px-4 py-3.5"><Skeleton variant="rect" className="w-16 h-5 rounded-full" /></td>
                <td className="px-4 py-3.5"><Skeleton variant="rect" className="w-6 h-6" /></td>
              </tr>
            ))
          ) : stops.length === 0 ? (
            <tr>
              <td colSpan={6} className="px-4 py-16 text-center">
                <div className="flex h-16 w-16 mx-auto items-center justify-center rounded-full bg-stone-100 mb-4">
                  {Icons.pin("h-8 w-8 text-stone-400")}
                </div>
                <p className="text-sm font-medium text-stone-600">
                  {search || statusFilter !== "all"
                    ? "No stops match your filters"
                    : "No stops yet"}
                </p>
                <p className="text-xs text-stone-400 mt-1">
                  {search || statusFilter !== "all"
                    ? "Try a different search or clear the filters"
                    : "Add your first stop to get started"}
                </p>
              </td>
            </tr>
          ) : (
            stops.map((stop) => (
              <StopRow
                key={stop.id}
                stop={stop}
                onEdit={() => onEdit(stop)}
                onDelete={() => onDelete(stop.id)}
                onDeleted={onDeleted}
                onDeleteError={onDeleteError}
                isSelected={selectedStops.has(stop.id)}
                onToggleSelect={() => onToggleSelect(stop.id)}
              />
            ))
          )}
        </tbody>
      </table>
    </div>
  );
}

// ── Card View ──────────────────────────────────────────────────────────────────

function CardView({
  stops,
  onEdit,
  onDeleted,
  onDeleteError,
  isLoading,
  search,
  statusFilter,
}: {
  stops: Stop[];
  onEdit: (stop: Stop) => void;
  onDeleted: () => void;
  onDeleteError: (msg: string) => void;
  isLoading: boolean;
  search: string;
  statusFilter: string;
}) {
  return (
    <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4">
      {stops.length === 0 ? (
        <div className="col-span-full text-center py-16 rounded-xl border border-[var(--admin-border)] bg-white">
          <div className="flex h-16 w-16 mx-auto items-center justify-center rounded-full bg-stone-100 mb-4">
            {Icons.pin("h-8 w-8 text-stone-400")}
          </div>
          <p className="text-sm font-medium text-stone-600">
            {search || statusFilter !== "all"
              ? "No stops match your filters"
              : "No stops yet"}
          </p>
          <p className="text-xs text-stone-400 mt-1">
            {search || statusFilter !== "all"
              ? "Try a different search or clear the filters"
              : "Add your first stop to get started"}
          </p>
        </div>
      ) : (
        stops.map((stop) => (
          <StopCard
            key={stop.id}
            stop={stop}
            onEdit={() => onEdit(stop)}
            onDeleted={onDeleted}
            onDeleteError={onDeleteError}
          />
        ))
      )}
    </div>
  );
}

// ── Shared helpers ─────────────────────────────────────────────────────────────

function SortIcon({ field, sortField, sortDirection }: { field: SortField; sortField: SortField; sortDirection: SortDirection }) {
  return (
    <span className={`inline-flex ml-1.5 ${sortField === field ? "opacity-100" : "opacity-30"}`}>
      {sortField === field && sortDirection === "desc" ? (
        <svg className="h-3 w-3" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2.5}>
          <path strokeLinecap="round" strokeLinejoin="round" d="M19 9l-7 7-7-7" />
        </svg>
      ) : (
        <svg className="h-3 w-3" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2.5}>
          <path strokeLinecap="round" strokeLinejoin="round" d="M5 15l7-7 7 7" />
        </svg>
      )}
    </span>
  );
}

function formatDate(iso: string): { date: string; weekday: string; isToday: boolean; isPast: boolean } {
  const [y, m, d] = iso.split("-").map((s) => parseInt(s, 10));
  if (!y || !m || !d) return { date: iso, weekday: "", isToday: false, isPast: false };
  
  const today = new Date();
  const todayStr = today.toISOString().split("T")[0];
  
  const dt = new Date(y, m - 1, d);
  const weekday = dt.toLocaleDateString("en-US", { weekday: "short" });
  const month = dt.toLocaleDateString("en-US", { month: "short" });
  
  return { 
    date: `${month} ${d}`, 
    weekday,
    isToday: iso === todayStr,
    isPast: iso < todayStr
  };
}

function formatTime(t: string): string {
  if (!t) return "";
  const [hStr, mStr] = t.split(":");
  const h = parseInt(hStr, 10);
  if (Number.isNaN(h)) return t;
  const period = h >= 12 ? "PM" : "AM";
  const hh = h === 0 ? 12 : h > 12 ? h - 12 : h;
  return `${hh}:${mStr} ${period}`;
}

// ── Row Component ───────────────────────────────────────────────────────────────

function StopRow({
  stop,
  onEdit,
  onDelete,
  onDeleted,
  onDeleteError,
  isSelected,
  onToggleSelect,
}: {
  stop: Stop;
  onEdit: () => void;
  onDelete: () => void;
  onDeleted: () => void;
  onDeleteError: (msg: string) => void;
  isSelected: boolean;
  onToggleSelect: () => void;
}) {
  const { success: showSuccess, error: showError } = useToast();
  const [openMenu, setOpenMenu] = useState<string | null>(null);
  const [deletingId, setDeletingId] = useState<string | null>(null);
  const [confirmDelete, setConfirmDelete] = useState<string | null>(null);
  const [publishingId, setPublishingId] = useState<string | null>(null);

  const { date, weekday, isToday, isPast } = formatDate(stop.date);
  const time = formatTime(stop.time);

  async function handlePublish() {
    setPublishingId(stop.id);
    const result = await publishStop(stop.id, stop.brand_id);
    setPublishingId(null);
    if (result.success) {
      showSuccess("Stop published", "The stop is now visible on the storefront");
      onDeleted();
    } else {
      showError("Failed to publish", result.error ?? "Please try again");
    }
  }

  async function handleDelete() {
    setDeletingId(stop.id);
    const result = await deleteStop(stop.id, stop.brand_id);
    setDeletingId(null);
    setConfirmDelete(null);
    setOpenMenu(null);
    if (result.success) {
      showSuccess("Stop deleted", "The stop has been removed");
      onDeleted();
    } else {
      onDeleteError(result.error ?? "Delete failed");
    }
  }

  return (
    <tr
      onClick={onEdit}
      className={`group cursor-pointer transition-all duration-150 ${
        isSelected 
          ? "bg-emerald-50/60" 
          : "hover:bg-stone-50/80"
      } ${isPast && stop.status !== "draft" ? "opacity-60" : ""}`}
    >
      <td className="px-4 py-3.5" onClick={(e) => e.stopPropagation()}>
        <input
          type="checkbox"
          checked={isSelected}
          onChange={() => {}}
          onClick={(e) => {
            e.stopPropagation();
            onToggleSelect();
          }}
          className="h-4 w-4 rounded border-stone-300 text-emerald-600 focus:ring-emerald-500 cursor-pointer"
          aria-label={`Select stop in ${stop.city}`}
        />
      </td>

      <td className="px-4 py-3.5">
        <div className="flex flex-col leading-tight">
          <div className="flex items-center gap-1.5">
            {isToday && (
              <span className="rounded bg-sky-100 px-1.5 py-0.5 text-[10px] font-bold uppercase tracking-wide text-sky-700">
                Today
              </span>
            )}
            <span className={`font-semibold tabular-nums ${isPast ? "text-stone-400" : "text-stone-800"}`}>
              {date}
            </span>
          </div>
          <span className="text-[11px] text-stone-500 tabular-nums">
            {weekday} {time && `· ${time}`}
          </span>
        </div>
      </td>

      <td className="px-4 py-3.5">
        <div className="flex flex-col leading-tight">
          <span className={`font-semibold ${isPast ? "text-stone-400" : "text-stone-800"}`}>{stop.city}</span>
          <span className="text-[11px] text-stone-500 tabular-nums">{stop.state}</span>
        </div>
      </td>

      <td className="px-4 py-3.5">
        <div className="flex flex-col leading-tight">
          <span className="text-stone-600">{stop.location}</span>
          {stop.address && (
            <span className="text-[11px] text-stone-400 truncate max-w-[260px]">
              {stop.address}
            </span>
          )}
        </div>
      </td>

      <td className="px-4 py-3.5">
        <span
          className={`inline-flex items-center gap-1.5 rounded-full px-2.5 py-0.5 text-[10px] font-semibold ${
            stop.status === "draft"
              ? "bg-amber-100 text-amber-700 border border-amber-200"
              : stop.active
                ? "bg-emerald-100 text-emerald-700 border border-emerald-200"
                : "bg-stone-100 text-stone-500 border border-stone-200"
          }`}
        >
          <span
            className={`h-1.5 w-1.5 rounded-full ${
              stop.status === "draft"
                ? "bg-amber-500"
                : stop.active
                  ? "bg-emerald-500"
                  : "bg-stone-400"
            }`}
          />
          {stop.status === "draft" ? "Draft" : stop.active ? "Active" : "Inactive"}
        </span>
      </td>

      <td className="px-4 py-3.5 text-right" onClick={(e) => e.stopPropagation()}>
        <div className="relative inline-flex items-center justify-end gap-1">
          <AdminButton
            variant="ghost"
            size="sm"
            onClick={onEdit}
          >
            Edit
          </AdminButton>
          <button
            onClick={(e) => {
              e.preventDefault();
              e.stopPropagation();
              setOpenMenu(openMenu === stop.id ? null : stop.id);
            }}
            className="rounded-lg px-2 py-1.5 text-xs text-[var(--admin-text-muted)] hover:text-red-600 hover:bg-red-50 transition-colors"
            aria-label="Stop actions"
          >
            <svg className="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
              <path strokeLinecap="round" strokeLinejoin="round" d="M12 5v.01M12 12v.01M12 19v.01M12 6a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2z" />
            </svg>
          </button>

          {openMenu === stop.id && (
            <>
              <div
                className="fixed inset-0 z-10"
                onClick={(e) => {
                  e.stopPropagation();
                  setOpenMenu(null);
                  setConfirmDelete(null);
                }}
              />
              <div className="absolute right-0 top-full mt-1 z-20 w-44 rounded-xl bg-white border border-[var(--admin-border)] shadow-xl overflow-hidden">
                {stop.status === "draft" && (
                  <button
                    onClick={(e) => {
                      e.stopPropagation();
                      handlePublish();
                      setOpenMenu(null);
                    }}
                    disabled={publishingId === stop.id}
                    className="w-full text-left px-4 py-2.5 text-sm font-medium text-emerald-700 hover:bg-emerald-50 transition-colors disabled:opacity-50 flex items-center gap-2"
                  >
                    <svg className="h-4 w-4 text-emerald-500" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
                      <path strokeLinecap="round" strokeLinejoin="round" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
                    </svg>
                    {publishingId === stop.id ? "Publishing…" : "Publish"}
                  </button>
                )}
                <Link
                  href={`/admin/stops/new?duplicate=${stop.id}`}
                  onClick={(e) => e.stopPropagation()}
                  className="flex items-center gap-2 px-4 py-2.5 text-sm text-stone-600 hover:bg-stone-50 transition-colors"
                >
                  <svg className="h-4 w-4 text-stone-400" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
                    <path strokeLinecap="round" strokeLinejoin="round" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z" />
                  </svg>
                  Duplicate
                </Link>
                <button
                  onClick={(e) => {
                    e.stopPropagation();
                    setOpenMenu(null);
                    setConfirmDelete(stop.id);
                  }}
                  className="w-full text-left px-4 py-2.5 text-sm text-red-600 hover:bg-red-50 transition-colors flex items-center gap-2"
                >
                  <svg className="h-4 w-4 text-red-400" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
                    <path strokeLinecap="round" strokeLinejoin="round" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
                  </svg>
                  Delete
                </button>
              </div>
            </>
          )}

          {confirmDelete === stop.id && (
            <>
              <div
                className="fixed inset-0 z-30"
                onClick={(e) => {
                  e.stopPropagation();
                  setConfirmDelete(null);
                  setOpenMenu(null);
                }}
              />
              <div className="absolute right-0 top-full mt-1 z-40 w-72 rounded-xl bg-white border border-[var(--admin-border)] shadow-xl p-4">
                <p className="text-sm font-semibold text-stone-800">
                  Delete &ldquo;{stop.city}, {stop.state}&rdquo;?
                </p>
                <p className="mt-1.5 text-xs text-stone-500">
                  This will remove the stop. If it has active orders, you must resolve those first.
                </p>
                <div className="mt-4 flex gap-2 justify-end">
                  <AdminButton
                    variant="secondary"
                    size="sm"
                    onClick={(e) => {
                      e.stopPropagation();
                      setConfirmDelete(null);
                      setOpenMenu(null);
                    }}
                  >
                    Cancel
                  </AdminButton>
                  <AdminButton
                    variant="danger"
                    size="sm"
                    onClick={(e) => {
                      e.stopPropagation();
                      handleDelete();
                    }}
                    disabled={deletingId === stop.id}
                    isLoading={deletingId === stop.id}
                  >
                    {deletingId === stop.id ? "Deleting…" : "Delete"}
                  </AdminButton>
                </div>
              </div>
            </>
          )}
        </div>
      </td>
    </tr>
  );
}

// ── Card Component ─────────────────────────────────────────────────────────────

function StopCard({
  stop,
  onEdit,
  onDeleted,
  onDeleteError,
}: {
  stop: Stop;
  onEdit: () => void;
  onDeleted: () => void;
  onDeleteError: (msg: string) => void;
}) {
  const { success: showSuccess, error: showError } = useToast();
  const [confirmDelete, setConfirmDelete] = useState(false);
  const [deleting, setDeleting] = useState(false);

  const { date, weekday, isToday, isPast } = formatDate(stop.date);
  const time = formatTime(stop.time);

  async function handleDelete() {
    setDeleting(true);
    const result = await deleteStop(stop.id, stop.brand_id);
    setDeleting(false);
    if (result.success) {
      showSuccess("Stop deleted", "The stop has been removed");
      onDeleted();
    } else {
      onDeleteError(result.error ?? "Delete failed");
    }
  }

  return (
    <div
      className={`group relative rounded-xl border border-[var(--admin-border)] bg-white hover:shadow-md hover:border-[var(--admin-accent)]/30 transition-all overflow-hidden ${
        isPast && stop.status !== "draft" ? "opacity-70" : ""
      }`}
    >
      {/* Header with date */}
      <div className="bg-gradient-to-br from-stone-50 to-stone-100/50 px-4 pt-4 pb-3 border-b border-stone-100">
        <div className="flex items-start justify-between">
          <div>
            <div className="flex items-center gap-1.5 mb-1">
              {isToday && (
                <span className="rounded bg-sky-100 px-1.5 py-0.5 text-[10px] font-bold uppercase tracking-wide text-sky-700">
                  Today
                </span>
              )}
            </div>
            <p className="text-lg font-bold text-stone-800 tabular-nums">{date}</p>
            <p className="text-xs text-stone-500 tabular-nums">{weekday} {time && `· ${time}`}</p>
          </div>
          <span
            className={`shrink-0 rounded-full px-2.5 py-0.5 text-[10px] font-semibold ${
              stop.status === "draft"
                ? "bg-amber-100 text-amber-700 border border-amber-200"
                : stop.active
                  ? "bg-emerald-100 text-emerald-700 border border-emerald-200"
                  : "bg-stone-100 text-stone-500 border border-stone-200"
            }`}
          >
            {stop.status === "draft" ? "Draft" : stop.active ? "Active" : "Inactive"}
          </span>
        </div>
      </div>

      {/* Content */}
      <div className="p-4">
        <button onClick={onEdit} className="block w-full text-left">
          <h3 className="font-semibold text-[var(--admin-text-primary)] group-hover:text-[var(--admin-accent)] transition-colors">
            {stop.city}, {stop.state}
          </h3>
          <p className="text-xs text-stone-500 mt-1 line-clamp-2">
            {stop.location}
          </p>
          {stop.address && (
            <p className="text-xs text-stone-400 mt-1 line-clamp-1">
              {stop.address}
            </p>
          )}
        </button>

        <div className="flex items-center gap-2 mt-4 pt-3 border-t border-stone-100">
          <AdminButton
            variant="secondary"
            size="sm"
            onClick={onEdit}
            className="flex-1"
          >
            Edit
          </AdminButton>
          <button
            onClick={() => setConfirmDelete(true)}
            className="rounded-lg border border-[var(--admin-border)] px-3 py-2 text-xs font-semibold text-[var(--admin-text-muted)] hover:bg-red-50 hover:text-red-600 hover:border-red-200 transition-colors"
          >
            <svg className="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
              <path strokeLinecap="round" strokeLinejoin="round" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
            </svg>
          </button>
        </div>
      </div>

      {/* Delete confirm */}
      {confirmDelete && (
        <div className="absolute inset-0 z-50 flex items-center justify-center bg-white/95 backdrop-blur-sm">
          <div className="bg-white rounded-xl shadow-xl p-4 max-w-[280px] mx-4 border border-[var(--admin-border)]">
            <p className="text-sm font-semibold text-stone-900">
              Delete &ldquo;{stop.city}, {stop.state}&rdquo;?
            </p>
            <p className="mt-1 text-xs text-stone-500">
              This will remove the stop. If it has active orders, you must resolve those first.
            </p>
            <div className="flex gap-2 mt-3">
              <button
                onClick={() => setConfirmDelete(false)}
                className="flex-1 rounded-lg border border-[var(--admin-border)] px-3 py-2 text-xs font-semibold text-stone-700 hover:bg-stone-50"
              >
                Cancel
              </button>
              <button
                onClick={handleDelete}
                disabled={deleting}
                className="flex-1 rounded-lg bg-red-600 px-3 py-2 text-xs font-bold text-white disabled:opacity-50 hover:bg-red-500"
              >
                {deleting ? "..." : "Delete"}
              </button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}
