import { useState, useEffect, useRef } from "react";
import ReactDOM from "react-dom";
import { useNavigate } from "react-router-dom";
import { useAuth } from "../auth/AuthContext";
import api from "../api/client";

// ─── constants ────────────────────────────────────────────────────────────────

// Row layout: Vesper Pro / Vesper Plus / Vesper | Agnus / Agnus Mini | Chronos Pro / Chronos
const BOARD_TYPES = [
  { value: "vesper_pro",  name: "Vesper Pro",   codename: "vesper-pro",    family: "vesper"  },
  { value: "vesper_plus", name: "Vesper+",      codename: "vesper-plus",   family: "vesper"  },
  { value: "vesper",      name: "Vesper",       codename: "vesper-basic",  family: "vesper"  },
  { value: "agnus",       name: "Agnus",        codename: "agnus-basic",   family: "agnus"   },
  { value: "agnus_mini",  name: "Agnus Mini",   codename: "agnus-mini",    family: "agnus"   },
  { value: "chronos_pro", name: "Chronos Pro",  codename: "chronos-pro",   family: "chronos" },
  { value: "chronos",     name: "Chronos",      codename: "chronos-basic", family: "chronos" },
];

const BOARD_FAMILY_COLORS = {
  vesper:  { selectedBg: "#0a1929", selectedBorder: "#3b82f6", selectedText: "#60a5fa", hoverBorder: "#3b82f6", glowColor: "rgba(59,130,246,0.35)", idleBorder: "#1d3a5c", idleText: "#7ca8d4" },
  agnus:   { selectedBg: "#1a1400", selectedBorder: "#f59e0b", selectedText: "#fbbf24", hoverBorder: "#f59e0b", glowColor: "rgba(245,158,11,0.35)",  idleBorder: "#4a3800", idleText: "#c79d3a" },
  chronos: { selectedBg: "#1a0808", selectedBorder: "#ef4444", selectedText: "#f87171", hoverBorder: "#ef4444", glowColor: "rgba(239,68,68,0.35)",   idleBorder: "#5c1a1a", idleText: "#d47a7a" },
};

const BOARD_TYPE_LABELS = {
  vesper: "Vesper", vesper_plus: "Vesper+", vesper_pro: "Vesper Pro",
  agnus: "Agnus", agnus_mini: "Agnus Mini",
  chronos: "Chronos", chronos_pro: "Chronos Pro",
};

const STATUS_STYLES = {
  manufactured:   { bg: "var(--lc-manufactured-bg)",   color: "var(--lc-manufactured-text)" },
  flashed:        { bg: "var(--lc-flashed-bg)",         color: "var(--lc-flashed-text)" },
  provisioned:    { bg: "var(--lc-provisioned-bg)",     color: "var(--lc-provisioned-text)" },
  sold:           { bg: "var(--lc-sold-bg)",            color: "var(--lc-sold-text)" },
  claimed:        { bg: "var(--lc-claimed-bg)",         color: "var(--lc-claimed-text)" },
  decommissioned: { bg: "var(--lc-decommissioned-bg)", color: "var(--lc-decommissioned-text)" },
};

const PROTECTED_STATUSES = ["sold", "claimed"];

// ─── column definitions ───────────────────────────────────────────────────────

const ALL_COLUMNS = [
  { id: "serial",    label: "Serial Number",  default: true },
  { id: "type",      label: "Type",           default: true },
  { id: "version",   label: "Version",        default: true },
  { id: "status",    label: "Status",         default: true },
  { id: "batch",     label: "Batch",          default: true },
  { id: "created",   label: "Created",        default: true },
  { id: "owner",     label: "Customer",       default: true },
  { id: "users",     label: "Device Users",   default: true },
  { id: "name",      label: "Device Name",    default: false },
];

const COL_STORAGE_KEY = "mfg_inventory_columns";
const COL_ORDER_KEY   = "mfg_inventory_col_order";

function loadColumnPrefs() {
  try {
    const vis   = JSON.parse(localStorage.getItem(COL_STORAGE_KEY) || "null");
    const order = JSON.parse(localStorage.getItem(COL_ORDER_KEY)   || "null");
    const visible = vis || Object.fromEntries(ALL_COLUMNS.map((c) => [c.id, c.default]));
    const orderedIds = order || ALL_COLUMNS.map((c) => c.id);
    // Merge any new columns not in saved order
    for (const c of ALL_COLUMNS) {
      if (!orderedIds.includes(c.id)) orderedIds.push(c.id);
    }
    return { visible, orderedIds };
  } catch {
    return {
      visible:    Object.fromEntries(ALL_COLUMNS.map((c) => [c.id, c.default])),
      orderedIds: ALL_COLUMNS.map((c) => c.id),
    };
  }
}

function saveColumnPrefs(visible, orderedIds) {
  localStorage.setItem(COL_STORAGE_KEY, JSON.stringify(visible));
  localStorage.setItem(COL_ORDER_KEY,   JSON.stringify(orderedIds));
}

// ─── helper components ────────────────────────────────────────────────────────

function StatusBadge({ status }) {
  const style = STATUS_STYLES[status] || STATUS_STYLES.manufactured;
  return (
    <span
      className="px-2 py-0.5 text-xs rounded-full capitalize font-medium"
      style={{ backgroundColor: style.bg, color: style.color }}
    >
      {status}
    </span>
  );
}

function UsersHoverCell({ userList, resolvedUsersMap }) {
  const [popupPos, setPopupPos] = useState(null);
  const triggerRef = useRef(null);
  const count = userList.length;

  const handleMouseEnter = () => {
    if (!triggerRef.current) return;
    const rect = triggerRef.current.getBoundingClientRect();
    setPopupPos({ top: rect.top + window.scrollY, left: rect.left + window.scrollX });
  };
  const handleMouseLeave = () => setPopupPos(null);

  if (count === 0) return <span className="text-xs" style={{ color: "var(--text-muted)" }}>—</span>;
  return (
    <>
      <span
        ref={triggerRef}
        className="px-2 py-0.5 text-xs rounded-full font-medium cursor-default"
        style={{ backgroundColor: "#431407", color: "#fb923c" }}
        onMouseEnter={handleMouseEnter}
        onMouseLeave={handleMouseLeave}
      >
        {count} user{count !== 1 ? "s" : ""}
      </span>
      {popupPos && typeof document !== "undefined" &&
        ReactDOM.createPortal(
          <div
            onMouseEnter={() => setPopupPos(popupPos)}
            onMouseLeave={() => setPopupPos(null)}
            className="rounded-lg border shadow-xl p-3"
            style={{
              position: "absolute",
              top: popupPos.top - 8,
              left: popupPos.left,
              transform: "translateY(-100%)",
              zIndex: 9999,
              minWidth: 220, maxWidth: 300,
              backgroundColor: "var(--bg-card)",
              borderColor: "var(--border-primary)",
              pointerEvents: "none",
            }}
          >
            <p className="text-xs font-semibold mb-2" style={{ color: "var(--text-muted)" }}>
              Assigned Users
            </p>
            <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
              {userList.map((uid) => {
                const u = resolvedUsersMap[uid];
                const initials = (u?.display_name || u?.email || uid)[0]?.toUpperCase() || "U";
                return (
                  <div key={uid} style={{ display: "flex", alignItems: "center", gap: 8 }}>
                    <div style={{
                      width: 26, height: 26, borderRadius: "50%", flexShrink: 0,
                      display: "flex", alignItems: "center", justifyContent: "center",
                      backgroundColor: "#431407", color: "#fb923c", fontSize: 10, fontWeight: 700,
                    }}>{initials}</div>
                    <div style={{ minWidth: 0 }}>
                      <p className="text-xs font-medium" style={{ color: "var(--text-primary)" }}>
                        {u?.display_name || uid}
                      </p>
                      {u?.email && <p className="text-xs" style={{ color: "var(--text-muted)" }}>{u.email}</p>}
                    </div>
                  </div>
                );
              })}
            </div>
          </div>,
          document.body
        )
      }
    </>
  );
}

function formatHwVersion(v) {
  if (!v) return "—";
  if (/^\d+\.\d+/.test(v)) return `Rev ${v}`;
  const n = parseInt(v, 10);
  if (!isNaN(n)) return `Rev ${n}.0`;
  return `Rev ${v}`;
}

function formatDate(iso) {
  if (!iso) return "—";
  try {
    return new Date(iso).toLocaleDateString("en-GB", { day: "numeric", month: "short", year: "numeric" });
  } catch { return iso; }
}

// ─── Column Toggle Dropdown ───────────────────────────────────────────────────

function ColumnToggle({ visible, orderedIds, onChange, onReorder }) {
  const [open, setOpen] = useState(false);
  const [dragging, setDragging] = useState(null);
  const ref = useRef(null);

  // Close on outside click
  useEffect(() => {
    const handler = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener("mousedown", handler);
    return () => document.removeEventListener("mousedown", handler);
  }, []);

  const handleDragStart = (id) => setDragging(id);
  const handleDragOver  = (e, id) => {
    e.preventDefault();
    if (dragging && dragging !== id) {
      const next = [...orderedIds];
      const from = next.indexOf(dragging);
      const to   = next.indexOf(id);
      next.splice(from, 1);
      next.splice(to, 0, dragging);
      onReorder(next);
    }
  };
  const handleDragEnd = () => setDragging(null);

  const visibleCount = Object.values(visible).filter(Boolean).length;

  return (
    <div className="relative" ref={ref}>
      <button
        onClick={() => setOpen((v) => !v)}
        className="flex items-center gap-1.5 px-3 py-2 text-sm rounded-md border hover:opacity-80 cursor-pointer transition-opacity"
        style={{
          backgroundColor: "var(--bg-input)",
          borderColor: "var(--border-input)",
          color: "var(--text-secondary)",
        }}
      >
        <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
          <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" />
        </svg>
        Columns ({visibleCount})
      </button>

      {open && (
        <div
          className="absolute right-0 top-full mt-1 z-20 rounded-lg border shadow-lg p-2"
          style={{ backgroundColor: "var(--bg-card)", borderColor: "var(--border-primary)", width: 200 }}
        >
          <p className="text-xs font-medium px-2 py-1 mb-1" style={{ color: "var(--text-muted)" }}>
            Drag to reorder
          </p>
          {orderedIds.map((id) => {
            const col = ALL_COLUMNS.find((c) => c.id === id);
            if (!col) return null;
            return (
              <div
                key={id}
                draggable
                onDragStart={() => handleDragStart(id)}
                onDragOver={(e) => handleDragOver(e, id)}
                onDragEnd={handleDragEnd}
                className="flex items-center gap-2 px-2 py-1.5 rounded cursor-grab select-none"
                style={{
                  backgroundColor: dragging === id ? "var(--bg-card-hover)" : "transparent",
                  opacity: dragging === id ? 0.5 : 1,
                }}
              >
                <span style={{ color: "var(--text-muted)", fontSize: 10 }}>⠿</span>
                <label className="flex items-center gap-2 cursor-pointer flex-1">
                  <input
                    type="checkbox"
                    checked={!!visible[id]}
                    onChange={(e) => onChange(id, e.target.checked)}
                    className="cursor-pointer"
                    onClick={(e) => e.stopPropagation()}
                  />
                  <span className="text-sm" style={{ color: "var(--text-secondary)" }}>{col.label}</span>
                </label>
              </div>
            );
          })}
        </div>
      )}
    </div>
  );
}

// ─── Board Type Tile ──────────────────────────────────────────────────────────

function BoardTypeTile({ bt, isSelected, pal, onClick }) {
  const [hovered, setHovered] = useState(false);
  const borderColor = isSelected ? pal.selectedBorder : hovered ? pal.hoverBorder : pal.idleBorder;
  const boxShadow   = isSelected
    ? `0 0 0 1px ${pal.selectedBorder}, 0 0 14px 4px ${pal.glowColor}`
    : hovered ? `0 0 12px 3px ${pal.glowColor}` : "none";
  return (
    <button
      onClick={onClick}
      onMouseEnter={() => setHovered(true)}
      onMouseLeave={() => setHovered(false)}
      className="rounded-lg border p-3 text-left cursor-pointer"
      style={{
        backgroundColor: isSelected ? pal.selectedBg : "var(--bg-card-hover)",
        borderColor, boxShadow,
        transition: "border-color 0.15s, box-shadow 0.15s, background-color 0.15s",
      }}
    >
      <p className="text-xs font-bold tracking-wide"
        style={{ color: isSelected ? pal.selectedText : hovered ? pal.idleText : "var(--text-heading)" }}>
        {bt.name}
      </p>
      <p className="text-xs font-mono mt-0.5 opacity-60" style={{ color: "var(--text-muted)" }}>{bt.codename}</p>
    </button>
  );
}

// ─── Add Device Modal ─────────────────────────────────────────────────────────

function AddDeviceModal({ onClose, onCreated }) {
  const [boardType, setBoardType]   = useState(null);
  const [boardVersion, setBoardVersion] = useState("1.0");
  const [creating, setCreating]     = useState(false);
  const [error, setError]           = useState("");

  const handleCreate = async () => {
    if (!boardType) return;
    setError("");
    setCreating(true);
    try {
      const batch = await api.post("/manufacturing/batch", {
        board_type: boardType,
        board_version: boardVersion.trim(),
        quantity: 1,
      });
      onCreated(batch.serial_numbers[0]);
      onClose();
    } catch (err) {
      setError(err.message);
    } finally {
      setCreating(false);
    }
  };

  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center" style={{ backgroundColor: "rgba(0,0,0,0.6)" }}>
      <div className="rounded-xl border p-6 w-full max-w-lg"
        style={{ backgroundColor: "var(--bg-card)", borderColor: "var(--border-primary)" }}>
        <h2 className="text-base font-bold mb-4" style={{ color: "var(--text-heading)" }}>Add Single Device</h2>

        <p className="text-sm mb-3" style={{ color: "var(--text-secondary)" }}>Board Type</p>
        <div className="space-y-2" style={{ marginBottom: 16 }}>
          {/* Row 1: Vesper family — 3 columns */}
          <div style={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 8 }}>
            {BOARD_TYPES.filter((b) => b.family === "vesper").map((bt) => (
              <BoardTypeTile key={bt.value} bt={bt} isSelected={boardType === bt.value} pal={BOARD_FAMILY_COLORS[bt.family]} onClick={() => setBoardType(bt.value)} />
            ))}
          </div>
          {/* Row 2: Agnus family — 2 columns (left-aligned in 3-col grid) */}
          <div style={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 8 }}>
            <div style={{ gridColumn: "1 / 3", display: "grid", gridTemplateColumns: "1fr 1fr", gap: 8 }}>
              {BOARD_TYPES.filter((b) => b.family === "agnus").map((bt) => (
                <BoardTypeTile key={bt.value} bt={bt} isSelected={boardType === bt.value} pal={BOARD_FAMILY_COLORS[bt.family]} onClick={() => setBoardType(bt.value)} />
              ))}
            </div>
          </div>
          {/* Row 3: Chronos family — 2 columns (left-aligned in 3-col grid) */}
          <div style={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 8 }}>
            <div style={{ gridColumn: "1 / 3", display: "grid", gridTemplateColumns: "1fr 1fr", gap: 8 }}>
              {BOARD_TYPES.filter((b) => b.family === "chronos").map((bt) => (
                <BoardTypeTile key={bt.value} bt={bt} isSelected={boardType === bt.value} pal={BOARD_FAMILY_COLORS[bt.family]} onClick={() => setBoardType(bt.value)} />
              ))}
            </div>
          </div>
        </div>

        <label className="block text-sm font-medium mb-1" style={{ color: "var(--text-secondary)" }}>
          Board Revision
        </label>
        <div className="flex items-center gap-2 mb-4">
          <span className="text-sm" style={{ color: "var(--text-muted)" }}>Rev</span>
          <input
            type="text"
            value={boardVersion}
            onChange={(e) => setBoardVersion(e.target.value)}
            placeholder="1.0"
            className="px-3 py-2 rounded-md text-sm border w-28"
            style={{ backgroundColor: "var(--bg-input)", borderColor: "var(--border-input)", color: "var(--text-primary)" }}
          />
        </div>

        {error && (
          <div className="text-xs rounded p-2 border mb-3"
            style={{ backgroundColor: "var(--danger-bg)", borderColor: "var(--danger)", color: "var(--danger-text)" }}>
            {error}
          </div>
        )}

        <div className="flex gap-3 justify-end">
          <button onClick={onClose} className="px-4 py-1.5 text-sm rounded-md cursor-pointer hover:opacity-80"
            style={{ backgroundColor: "var(--bg-card-hover)", color: "var(--text-secondary)" }}>
            Cancel
          </button>
          <button
            onClick={handleCreate}
            disabled={!boardType || creating}
            className="px-4 py-1.5 text-sm rounded-md font-medium cursor-pointer hover:opacity-90 disabled:opacity-40"
            style={{ backgroundColor: "var(--btn-primary)", color: "var(--text-white)" }}
          >
            {creating ? "Creating…" : "Create Device"}
          </button>
        </div>
      </div>
    </div>
  );
}

// ─── New Batch Modal ──────────────────────────────────────────────────────────

function NewBatchModal({ onClose, onCreated }) {
  const [boardType, setBoardType]       = useState(null);
  const [boardVersion, setBoardVersion] = useState("1.0");
  const [quantity, setQuantity]         = useState(1);
  const [saving, setSaving]             = useState(false);
  const [error, setError]               = useState("");
  const [result, setResult]             = useState(null);
  const [copied, setCopied]             = useState(false);

  const handleSubmit = async (e) => {
    e.preventDefault();
    if (!boardType) return;
    setError("");
    setSaving(true);
    try {
      const data = await api.post("/manufacturing/batch", {
        board_type: boardType,
        board_version: boardVersion.trim(),
        quantity: Number(quantity),
      });
      setResult(data);
      if (onCreated) onCreated(data);
    } catch (err) {
      setError(err.message);
    } finally {
      setSaving(false);
    }
  };

  const copyAll = () => {
    if (!result) return;
    navigator.clipboard.writeText(result.serial_numbers.join("\n"));
    setCopied(true);
    setTimeout(() => setCopied(false), 2000);
  };

  const inputStyle = { backgroundColor: "var(--bg-input)", borderColor: "var(--border-input)", color: "var(--text-primary)" };

  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center" style={{ backgroundColor: "rgba(0,0,0,0.7)" }}
      onClick={onClose}>
      <div className="rounded-xl border w-full max-w-xl overflow-y-auto"
        style={{ backgroundColor: "var(--bg-card)", borderColor: "var(--border-primary)", maxHeight: "90vh" }}
        onClick={(e) => e.stopPropagation()}>
        <div style={{ padding: "20px 24px", borderBottom: "1px solid var(--border-primary)", display: "flex", alignItems: "center", justifyContent: "space-between" }}>
          <h2 className="text-base font-bold" style={{ color: "var(--text-heading)" }}>New Batch</h2>
          <button onClick={onClose} style={{ background: "none", border: "none", color: "var(--text-muted)", fontSize: 22, cursor: "pointer", lineHeight: 1 }}>×</button>
        </div>

        <div style={{ padding: "20px 24px" }}>
          {!result ? (
            <form onSubmit={handleSubmit}>
              <p className="text-sm mb-3" style={{ color: "var(--text-secondary)" }}>Board Type</p>
              <div className="space-y-2 mb-5">
                <div style={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 8 }}>
                  {BOARD_TYPES.filter((b) => b.family === "vesper").map((bt) => (
                    <BoardTypeTile key={bt.value} bt={bt} isSelected={boardType === bt.value}
                      pal={BOARD_FAMILY_COLORS[bt.family]} onClick={() => setBoardType(bt.value)} />
                  ))}
                </div>
                <div style={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 8 }}>
                  <div style={{ gridColumn: "1 / 3", display: "grid", gridTemplateColumns: "1fr 1fr", gap: 8 }}>
                    {BOARD_TYPES.filter((b) => b.family === "agnus").map((bt) => (
                      <BoardTypeTile key={bt.value} bt={bt} isSelected={boardType === bt.value}
                        pal={BOARD_FAMILY_COLORS[bt.family]} onClick={() => setBoardType(bt.value)} />
                    ))}
                  </div>
                </div>
                <div style={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 8 }}>
                  <div style={{ gridColumn: "1 / 3", display: "grid", gridTemplateColumns: "1fr 1fr", gap: 8 }}>
                    {BOARD_TYPES.filter((b) => b.family === "chronos").map((bt) => (
                      <BoardTypeTile key={bt.value} bt={bt} isSelected={boardType === bt.value}
                        pal={BOARD_FAMILY_COLORS[bt.family]} onClick={() => setBoardType(bt.value)} />
                    ))}
                  </div>
                </div>
              </div>

              <div className="flex gap-4 mb-5">
                <div className="flex-1">
                  <label className="block text-sm font-medium mb-1" style={{ color: "var(--text-secondary)" }}>Board Revision</label>
                  <div className="flex items-center gap-2">
                    <span className="text-sm" style={{ color: "var(--text-muted)" }}>Rev</span>
                    <input type="text" value={boardVersion} onChange={(e) => setBoardVersion(e.target.value)}
                      placeholder="1.0" className="px-3 py-2 rounded-md text-sm border w-28"
                      style={inputStyle} />
                  </div>
                </div>
                <div className="flex-1">
                  <label className="block text-sm font-medium mb-1" style={{ color: "var(--text-secondary)" }}>Quantity</label>
                  <input type="number" value={quantity} onChange={(e) => setQuantity(e.target.value)}
                    min={1} max={100} className="px-3 py-2 rounded-md text-sm border w-full"
                    style={inputStyle} />
                </div>
              </div>

              {error && (
                <div className="text-xs rounded p-2 border mb-3"
                  style={{ backgroundColor: "var(--danger-bg)", borderColor: "var(--danger)", color: "var(--danger-text)" }}>
                  {error}
                </div>
              )}

              <div className="flex gap-3 justify-end">
                <button type="button" onClick={onClose} className="px-4 py-1.5 text-sm rounded-md cursor-pointer hover:opacity-80"
                  style={{ backgroundColor: "var(--bg-card-hover)", color: "var(--text-secondary)" }}>
                  Cancel
                </button>
                <button type="submit" disabled={!boardType || saving}
                  className="px-4 py-1.5 text-sm rounded-md font-medium cursor-pointer hover:opacity-90 disabled:opacity-40"
                  style={{ backgroundColor: "var(--btn-primary)", color: "var(--text-white)" }}>
                  {saving ? "Creating…" : `Create Batch (${quantity})`}
                </button>
              </div>
            </form>
          ) : (
            <div>
              <div className="rounded-lg p-4 mb-4 border" style={{ backgroundColor: "var(--bg-primary)", borderColor: "var(--border-secondary)" }}>
                <p className="text-sm font-medium mb-1" style={{ color: "var(--text-heading)" }}>
                  Batch created: {result.batch_id}
                </p>
                <p className="text-xs mb-2" style={{ color: "var(--text-muted)" }}>
                  {result.board_type} · Rev {result.board_version} · {result.serial_numbers.length} device{result.serial_numbers.length !== 1 ? "s" : ""}
                </p>
                <pre className="text-xs font-mono rounded p-3 max-h-48 overflow-y-auto"
                  style={{ backgroundColor: "var(--bg-card)", color: "var(--text-primary)", border: "1px solid var(--border-secondary)" }}>
                  {result.serial_numbers.join("\n")}
                </pre>
              </div>
              <div className="flex gap-3 justify-end">
                <button onClick={copyAll}
                  className="px-4 py-1.5 text-sm rounded-md font-medium cursor-pointer hover:opacity-90"
                  style={{ backgroundColor: "var(--bg-card-hover)", color: "var(--text-secondary)", border: "1px solid var(--border-primary)" }}>
                  {copied ? "Copied!" : "Copy Serial Numbers"}
                </button>
                <button onClick={onClose}
                  className="px-4 py-1.5 text-sm rounded-md font-medium cursor-pointer hover:opacity-90"
                  style={{ backgroundColor: "var(--btn-primary)", color: "var(--text-white)" }}>
                  Done
                </button>
              </div>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

// ─── Delete Not Provisioned Modal ─────────────────────────────────────────────

function DeleteUnprovisionedModal({ onClose, onDeleted }) {
  const [scanning, setScanning]   = useState(true);
  const [candidates, setCandidates] = useState([]);
  const [deleting, setDeleting]   = useState(false);
  const [error, setError]         = useState("");

  useEffect(() => {
    (async () => {
      try {
        const data = await api.get("/manufacturing/devices?status=manufactured&limit=500");
        setCandidates(data.devices || []);
      } catch (err) {
        setError(err.message);
      } finally {
        setScanning(false);
      }
    })();
  }, []);

  const handleDelete = async () => {
    setDeleting(true);
    setError("");
    try {
      const result = await api.request("/manufacturing/devices", { method: "DELETE" });
      onDeleted(result.count || 0);
      onClose();
    } catch (err) {
      setError(err.message);
    } finally {
      setDeleting(false);
    }
  };

  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center" style={{ backgroundColor: "rgba(0,0,0,0.6)" }}>
      <div className="rounded-xl border p-6 w-full max-w-lg"
        style={{ backgroundColor: "var(--bg-card)", borderColor: "var(--danger)" }}>
        <h2 className="text-base font-bold mb-2" style={{ color: "var(--danger-text)" }}>
          Delete Not Provisioned Devices
        </h2>
        <p className="text-sm mb-4" style={{ color: "var(--text-secondary)" }}>
          The following devices have status <strong>manufactured</strong> and have never been flashed or provisioned.
          They will be permanently deleted.
        </p>

        {scanning ? (
          <p className="text-sm py-4 text-center" style={{ color: "var(--text-muted)" }}>Scanning…</p>
        ) : candidates.length === 0 ? (
          <p className="text-sm py-4 text-center" style={{ color: "var(--text-muted)" }}>
            No unprovisioned devices found.
          </p>
        ) : (
          <div className="rounded-md border overflow-hidden mb-4" style={{ borderColor: "var(--border-primary)", maxHeight: 240, overflowY: "auto" }}>
            <table className="w-full text-xs">
              <thead>
                <tr style={{ backgroundColor: "var(--bg-secondary)", borderBottom: "1px solid var(--border-primary)" }}>
                  <th className="px-3 py-2 text-left font-medium" style={{ color: "var(--text-muted)" }}>Serial</th>
                  <th className="px-3 py-2 text-left font-medium" style={{ color: "var(--text-muted)" }}>Type</th>
                  <th className="px-3 py-2 text-left font-medium" style={{ color: "var(--text-muted)" }}>Created</th>
                </tr>
              </thead>
              <tbody>
                {candidates.map((d) => (
                  <tr key={d.id} style={{ borderBottom: "1px solid var(--border-secondary)" }}>
                    <td className="px-3 py-2 font-mono" style={{ color: "var(--text-primary)" }}>{d.serial_number}</td>
                    <td className="px-3 py-2" style={{ color: "var(--text-secondary)" }}>{BOARD_TYPE_LABELS[d.hw_type] || d.hw_type}</td>
                    <td className="px-3 py-2" style={{ color: "var(--text-muted)" }}>{formatDate(d.created_at)}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}

        {error && (
          <div className="text-xs rounded p-2 border mb-3"
            style={{ backgroundColor: "var(--danger-bg)", borderColor: "var(--danger)", color: "var(--danger-text)" }}>
            {error}
          </div>
        )}

        <div className="flex gap-3 justify-end">
          <button onClick={onClose} className="px-4 py-1.5 text-sm rounded-md cursor-pointer hover:opacity-80"
            style={{ backgroundColor: "var(--bg-card-hover)", color: "var(--text-secondary)" }}>
            Cancel
          </button>
          <button
            onClick={handleDelete}
            disabled={deleting || scanning || candidates.length === 0}
            className="px-4 py-1.5 text-sm rounded-md font-medium cursor-pointer hover:opacity-90 disabled:opacity-40"
            style={{ backgroundColor: "var(--danger)", color: "#fff" }}
          >
            {deleting ? "Deleting…" : `Delete ${candidates.length} Device${candidates.length !== 1 ? "s" : ""}`}
          </button>
        </div>
      </div>
    </div>
  );
}

// ─── Multi-select Delete Modal ────────────────────────────────────────────────

function MultiDeleteModal({ selected, devices, onClose, onDeleted }) {
  const [deleting, setDeleting] = useState(false);
  const [error, setError]       = useState("");

  const selectedDevices = devices.filter((d) => selected.has(d.id));
  const hasProtected = selectedDevices.some((d) => PROTECTED_STATUSES.includes(d.mfg_status));

  const handleDelete = async () => {
    setDeleting(true);
    setError("");
    try {
      // Only delete non-protected devices from this modal
      const toDelete = selectedDevices.filter((d) => !PROTECTED_STATUSES.includes(d.mfg_status));
      await Promise.all(
        toDelete.map((d) =>
          api.request(`/manufacturing/devices/${d.serial_number}`, { method: "DELETE" })
        )
      );
      onDeleted(toDelete.map((d) => d.id));
      onClose();
    } catch (err) {
      setError(err.message);
    } finally {
      setDeleting(false);
    }
  };

  const safeCount = selectedDevices.filter((d) => !PROTECTED_STATUSES.includes(d.mfg_status)).length;
  const protectedCount = selectedDevices.length - safeCount;

  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center" style={{ backgroundColor: "rgba(0,0,0,0.6)" }}>
      <div className="rounded-xl border p-6 w-full max-w-md"
        style={{ backgroundColor: "var(--bg-card)", borderColor: "var(--danger)" }}>
        <h2 className="text-base font-bold mb-3" style={{ color: "var(--danger-text)" }}>
          Delete {selectedDevices.length} Device{selectedDevices.length !== 1 ? "s" : ""}
        </h2>

        {hasProtected && (
          <div className="text-sm rounded-md p-3 border mb-3"
            style={{ backgroundColor: "#2e1a00", borderColor: "#fb923c", color: "#fb923c" }}>
            ⚠ {protectedCount} selected device{protectedCount !== 1 ? "s are" : " is"} sold/claimed and will be <strong>skipped</strong>.
            To delete those, open each device individually.
          </div>
        )}

        <p className="text-sm mb-4" style={{ color: "var(--text-secondary)" }}>
          {safeCount > 0
            ? `${safeCount} device${safeCount !== 1 ? "s" : ""} will be permanently deleted.`
            : "No deletable devices in your selection (all are sold/claimed)."}
        </p>

        {error && (
          <div className="text-xs rounded p-2 border mb-3"
            style={{ backgroundColor: "var(--danger-bg)", borderColor: "var(--danger)", color: "var(--danger-text)" }}>
            {error}
          </div>
        )}

        <div className="flex gap-3 justify-end">
          <button onClick={onClose} className="px-4 py-1.5 text-sm rounded-md cursor-pointer hover:opacity-80"
            style={{ backgroundColor: "var(--bg-card-hover)", color: "var(--text-secondary)" }}>
            Cancel
          </button>
          <button
            onClick={handleDelete}
            disabled={deleting || safeCount === 0}
            className="px-4 py-1.5 text-sm rounded-md font-medium cursor-pointer hover:opacity-90 disabled:opacity-40"
            style={{ backgroundColor: "var(--danger)", color: "#fff" }}
          >
            {deleting ? "Deleting…" : `Delete ${safeCount}`}
          </button>
        </div>
      </div>
    </div>
  );
}

// ─── Main Component ───────────────────────────────────────────────────────────

export default function DeviceInventory() {
  const navigate = useNavigate();
  const { hasPermission } = useAuth();
  const canAdd    = hasPermission("manufacturing", "add");
  const canDelete = hasPermission("manufacturing", "delete");

  const [devices, setDevices] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError]     = useState("");

  const [search, setSearch]           = useState("");
  const [statusFilter, setStatusFilter] = useState("");
  const [hwTypeFilter, setHwTypeFilter] = useState("");

  // Column preferences
  const [colPrefs, setColPrefs] = useState(loadColumnPrefs);

  // Pagination
  const [pageSize, setPageSize] = useState(20);
  const [page, setPage] = useState(1);

  // Customer name lookup: { [customer_id]: { name, surname } }
  const [customerMap, setCustomerMap] = useState({});
  // User display lookup: { [uid]: { display_name, email } }
  const [resolvedUsersMap, setResolvedUsersMap] = useState({});

  // Hover state for checkbox reveal: rowId | null
  const [hoveredRow, setHoveredRow] = useState(null);

  // Selection
  const [selected, setSelected]   = useState(new Set());
  const allIds = devices.map((d) => d.id);
  const allSelected = allIds.length > 0 && allIds.every((id) => selected.has(id));

  // Modals
  const [showAddDevice, setShowAddDevice]               = useState(false);
  const [showBatchModal, setShowBatchModal]             = useState(false);
  const [showDeleteUnprovisioned, setShowDeleteUnprovisioned] = useState(false);
  const [showMultiDelete, setShowMultiDelete]           = useState(false);

  const fetchDevices = async () => {
    setLoading(true);
    setError("");
    try {
      const params = new URLSearchParams();
      if (search)       params.set("search", search);
      if (statusFilter) params.set("status", statusFilter);
      if (hwTypeFilter) params.set("hw_type", hwTypeFilter);
      params.set("limit", "500");
      const qs = params.toString();
      const data = await api.get(`/manufacturing/devices${qs ? `?${qs}` : ""}`);
      const devs = data.devices || [];
      setDevices(devs);
      setSelected(new Set());

      // Fetch customer names for assigned devices
      const customerIds = [...new Set(devs.map((d) => d.customer_id).filter(Boolean))];
      if (customerIds.length) {
        const entries = await Promise.all(
          customerIds.map((id) =>
            api.get(`/manufacturing/customers/${id}`)
              .then((c) => [id, c])
              .catch(() => [id, { name: "", surname: "" }])
          )
        );
        setCustomerMap(Object.fromEntries(entries));
      }

      // Fetch user display info for all user_list UIDs
      const allUids = [...new Set(devs.flatMap((d) => d.user_list || []))];
      if (allUids.length) {
        const entries = await Promise.all(
          allUids.map((uid) =>
            api.get(`/users/${uid}`)
              .then((u) => [uid, { display_name: u.display_name || "", email: u.email || "" }])
              .catch(() => [uid, { display_name: "", email: "" }])
          )
        );
        setResolvedUsersMap(Object.fromEntries(entries));
      }
    } catch (err) {
      setError(err.message);
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => { fetchDevices(); setPage(1); }, [search, statusFilter, hwTypeFilter]);

  const updateColVisible = (id, visible) => {
    const next = { ...colPrefs.visible, [id]: visible };
    setColPrefs((p) => ({ ...p, visible: next }));
    saveColumnPrefs(next, colPrefs.orderedIds);
  };

  const updateColOrder = (orderedIds) => {
    setColPrefs((p) => ({ ...p, orderedIds }));
    saveColumnPrefs(colPrefs.visible, orderedIds);
  };

  const toggleRow = (id, e) => {
    e.stopPropagation();
    setSelected((prev) => {
      const next = new Set(prev);
      if (next.has(id)) next.delete(id); else next.add(id);
      return next;
    });
  };

  const toggleAll = () => {
    if (allSelected) setSelected(new Set());
    else setSelected(new Set(allIds));
  };

  const visibleCols = colPrefs.orderedIds
    .map((id) => ALL_COLUMNS.find((c) => c.id === id))
    .filter((c) => c && colPrefs.visible[c.id]);

  const totalPages = pageSize > 0 ? Math.ceil(devices.length / pageSize) : 1;
  const safePage = Math.min(page, Math.max(1, totalPages));
  const pagedDevices = pageSize > 0
    ? devices.slice((safePage - 1) * pageSize, safePage * pageSize)
    : devices;

  const renderCell = (col, device) => {
    switch (col.id) {
      case "serial":  return (
        <span style={{ display: "inline-flex", alignItems: "center", gap: 6 }}>
          <span className="font-mono text-xs" style={{ color: "var(--text-primary)" }}>{device.serial_number}</span>
          {/^[A-Z0-9]{10,}$/.test(device.serial_number || "") && (
            <span style={{ fontSize: 9, fontWeight: 700, padding: "1px 5px", borderRadius: 3, backgroundColor: "#2e1a00", color: "#fb923c", letterSpacing: "0.04em" }}>
              LEGACY
            </span>
          )}
        </span>
      );
      case "type":    return <span style={{ color: "var(--text-secondary)" }}>{BOARD_TYPE_LABELS[device.hw_type] || device.hw_type}</span>;
      case "version": return <span style={{ color: "var(--text-muted)" }}>{formatHwVersion(device.hw_version)}</span>;
      case "status":  return <StatusBadge status={device.mfg_status} />;
      case "batch":   return <span className="font-mono text-xs" style={{ color: "var(--text-muted)" }}>{device.mfg_batch_id || "—"}</span>;
      case "created": return <span className="text-xs" style={{ color: "var(--text-muted)" }}>{formatDate(device.created_at)}</span>;
      case "owner": {
        if (!device.customer_id) return <span className="text-xs" style={{ color: "var(--text-muted)" }}>—</span>;
        const cust = customerMap[device.customer_id];
        const fullName = cust ? [cust.name, cust.surname].filter(Boolean).join(" ") : "";
        return (
          <span className="text-sm font-medium" style={{ color: fullName ? "var(--text-primary)" : "var(--text-muted)", whiteSpace: "nowrap" }}>
            {fullName || "—"}
          </span>
        );
      }
      case "users":
        return <UsersHoverCell userList={device.user_list || []} resolvedUsersMap={resolvedUsersMap} />;
      case "name":    return <span className="text-xs" style={{ color: "var(--text-muted)" }}>{device.device_name || "—"}</span>;
      default:        return null;
    }
  };

  return (
    <div>
      {/* Header */}
      <div className="flex items-center justify-between mb-6">
        <div>
          <h1 className="text-2xl font-bold" style={{ color: "var(--text-heading)" }}>Device Inventory</h1>
          <p className="text-sm mt-0.5" style={{ color: "var(--text-muted)" }}>
            {devices.length} device{devices.length !== 1 ? "s" : ""}
            {statusFilter || hwTypeFilter || search ? " (filtered)" : ""}
          </p>
        </div>
        <div className="flex items-center gap-2">
          {canDelete && (
            <button
              onClick={() => setShowDeleteUnprovisioned(true)}
              className="px-3 py-2 text-sm rounded-md font-medium hover:opacity-80 cursor-pointer transition-opacity"
              style={{ backgroundColor: "var(--danger-bg)", color: "var(--danger-text)", border: "1px solid var(--danger)" }}
            >
              Delete Not Provisioned
            </button>
          )}
          {canAdd && (
            <button
              onClick={() => setShowAddDevice(true)}
              className="px-3 py-2 text-sm rounded-md font-medium hover:opacity-90 cursor-pointer transition-opacity"
              style={{ backgroundColor: "var(--bg-card-hover)", color: "var(--text-secondary)", border: "1px solid var(--border-primary)" }}
            >
              + Add Device
            </button>
          )}
          {canAdd && (
            <button
              onClick={() => setShowBatchModal(true)}
              className="px-4 py-2 text-sm rounded-md font-medium hover:opacity-90 cursor-pointer transition-opacity"
              style={{ backgroundColor: "var(--btn-primary)", color: "var(--text-white)" }}
            >
              + New Batch
            </button>
          )}
        </div>
      </div>

      {/* Filters + column toggle */}
      <div className="flex flex-wrap gap-3 mb-4">
        <input
          type="text"
          placeholder="Search serial, batch, owner…"
          value={search}
          onChange={(e) => setSearch(e.target.value)}
          className="px-3 py-2 rounded-md text-sm border flex-1 min-w-48"
          style={{ backgroundColor: "var(--bg-input)", borderColor: "var(--border-input)", color: "var(--text-primary)" }}
        />
        <select
          value={statusFilter}
          onChange={(e) => setStatusFilter(e.target.value)}
          className="px-3 py-2 rounded-md text-sm border"
          style={{ backgroundColor: "var(--bg-input)", borderColor: "var(--border-input)", color: "var(--text-primary)" }}
        >
          <option value="">All Statuses</option>
          <option value="manufactured">Manufactured</option>
          <option value="flashed">Flashed</option>
          <option value="provisioned">Provisioned</option>
          <option value="sold">Sold</option>
          <option value="claimed">Claimed</option>
          <option value="decommissioned">Decommissioned</option>
        </select>
        <select
          value={hwTypeFilter}
          onChange={(e) => setHwTypeFilter(e.target.value)}
          className="px-3 py-2 rounded-md text-sm border"
          style={{ backgroundColor: "var(--bg-input)", borderColor: "var(--border-input)", color: "var(--text-primary)" }}
        >
          <option value="">All Types</option>
          {BOARD_TYPES.map((bt) => (
            <option key={bt.value} value={bt.value}>{bt.name}</option>
          ))}
        </select>
        <ColumnToggle
          visible={colPrefs.visible}
          orderedIds={colPrefs.orderedIds}
          onChange={updateColVisible}
          onReorder={updateColOrder}
        />
        <select
          value={String(pageSize)}
          onChange={(e) => { setPageSize(Number(e.target.value)); setPage(1); }}
          className="px-3 py-2 rounded-md text-sm border"
          style={{ backgroundColor: "var(--bg-input)", borderColor: "var(--border-input)", color: "var(--text-primary)" }}
        >
          <option value="10">Show 10</option>
          <option value="20">Show 20</option>
          <option value="50">Show 50</option>
          <option value="0">Show All</option>
        </select>
      </div>

      {/* Multi-select action bar */}
      {selected.size > 0 && canDelete && (
        <div
          className="flex items-center justify-between px-4 py-2 rounded-md mb-3"
          style={{ backgroundColor: "var(--bg-card)", border: "1px solid var(--border-primary)" }}
        >
          <span className="text-sm" style={{ color: "var(--text-secondary)" }}>
            {selected.size} device{selected.size !== 1 ? "s" : ""} selected
          </span>
          <div className="flex gap-2">
            <button
              onClick={() => setSelected(new Set())}
              className="px-3 py-1.5 text-xs rounded-md cursor-pointer hover:opacity-80"
              style={{ backgroundColor: "var(--bg-card-hover)", color: "var(--text-secondary)" }}
            >
              Clear
            </button>
            <button
              onClick={() => setShowMultiDelete(true)}
              className="px-3 py-1.5 text-xs rounded-md font-medium cursor-pointer hover:opacity-90"
              style={{ backgroundColor: "var(--danger)", color: "#fff" }}
            >
              Delete Selected
            </button>
          </div>
        </div>
      )}

      {error && (
        <div className="text-sm rounded-md p-3 mb-4 border"
          style={{ backgroundColor: "var(--danger-bg)", borderColor: "var(--danger)", color: "var(--danger-text)" }}>
          {error}
        </div>
      )}

      {/* Table */}
      <div className="rounded-lg border overflow-hidden" style={{ borderColor: "var(--border-primary)" }}>
        <div className="overflow-x-auto" style={{ overflowX: "auto" }}>
          <table className="w-full text-sm">
            <thead>
              <tr style={{ backgroundColor: "var(--bg-secondary)", borderBottom: "1px solid var(--border-primary)" }}>
                {visibleCols.map((col, colIdx) => (
                  <th key={col.id}
                    className="py-3 font-medium"
                    style={{
                      color: "var(--text-muted)",
                      textAlign: col.id === "status" ? "center" : "left",
                      whiteSpace: "nowrap",
                      paddingLeft: 16,
                      paddingRight: colIdx === visibleCols.length - 1 ? 4 : 16,
                    }}>
                    {col.label}
                  </th>
                ))}
                {/* Checkbox header — only shown when something is selected */}
                <th style={{ width: 36, minWidth: 36, padding: "0 8px", textAlign: "center" }}>
                  {selected.size > 0 && (
                    <input type="checkbox" checked={allSelected} onChange={toggleAll} className="cursor-pointer" />
                  )}
                </th>
              </tr>
            </thead>
            <tbody>
              {loading ? (
                <tr>
                  <td colSpan={visibleCols.length + 1} className="px-4 py-8 text-center text-sm" style={{ color: "var(--text-muted)" }}>
                    Loading…
                  </td>
                </tr>
              ) : devices.length === 0 ? (
                <tr>
                  <td colSpan={visibleCols.length + 1} className="px-4 py-8 text-center text-sm" style={{ color: "var(--text-muted)" }}>
                    No devices found.
                  </td>
                </tr>
              ) : (
                pagedDevices.map((device, rowIdx) => {
                  const isSelected = selected.has(device.id);
                  const isAlt = rowIdx % 2 === 1;
                  const isHovered = hoveredRow === device.id;
                  const showCheckbox = isSelected || selected.size > 0 || isHovered;
                  return (
                    <tr
                      key={device.id}
                      className="cursor-pointer transition-colors"
                      style={{
                        borderBottom: "1px solid var(--border-secondary)",
                        backgroundColor: isSelected ? "var(--bg-card)" : isAlt ? "var(--bg-row-alt)" : "",
                      }}
                      onMouseEnter={(e) => {
                        setHoveredRow(device.id);
                        if (!isSelected) e.currentTarget.style.backgroundColor = "var(--bg-card-hover)";
                      }}
                      onMouseLeave={(e) => {
                        setHoveredRow(null);
                        if (!isSelected) e.currentTarget.style.backgroundColor = isAlt ? "var(--bg-row-alt)" : "";
                      }}
                    >
                      {/* Data cells */}
                      {visibleCols.map((col, colIdx) => (
                        <td
                          key={col.id}
                          className="py-3"
                          style={{
                            textAlign: col.id === "status" ? "center" : "left",
                            paddingLeft: 16,
                            paddingRight: colIdx === visibleCols.length - 1 ? 4 : 16,
                          }}
                          onClick={() => navigate(`/manufacturing/devices/${device.serial_number}`)}
                        >
                          {renderCell(col, device)}
                        </td>
                      ))}
                      {/* Hover-reveal checkbox on the right */}
                      <td style={{ width: 36, minWidth: 36, padding: "0 8px", textAlign: "center" }}
                        onClick={(e) => toggleRow(device.id, e)}>
                        <input
                          type="checkbox"
                          checked={isSelected}
                          onChange={() => {}}
                          className="cursor-pointer"
                          style={{ opacity: showCheckbox ? 1 : 0, transition: "opacity 0.15s" }}
                        />
                      </td>
                    </tr>
                  );
                })
              )}
            </tbody>
          </table>
        </div>
        {pageSize > 0 && totalPages > 1 && (
          <div className="flex items-center justify-between px-4 py-3 border-t" style={{ borderColor: "var(--border-primary)" }}>
            <span className="text-xs" style={{ color: "var(--text-muted)" }}>
              Page {safePage} of {totalPages} — {devices.length} total
            </span>
            <div className="flex items-center gap-1">
              <button onClick={() => setPage(1)} disabled={safePage === 1}
                className="px-2 py-1 text-xs rounded disabled:opacity-40 cursor-pointer"
                style={{ color: "var(--text-secondary)", backgroundColor: "var(--bg-card-hover)" }}>«</button>
              <button onClick={() => setPage((p) => Math.max(1, p - 1))} disabled={safePage === 1}
                className="px-2 py-1 text-xs rounded disabled:opacity-40 cursor-pointer"
                style={{ color: "var(--text-secondary)", backgroundColor: "var(--bg-card-hover)" }}>‹</button>
              {Array.from({ length: totalPages }, (_, i) => i + 1)
                .filter((p) => p === 1 || p === totalPages || Math.abs(p - safePage) <= 2)
                .reduce((acc, p, idx, arr) => {
                  if (idx > 0 && p - arr[idx - 1] > 1) acc.push("…");
                  acc.push(p);
                  return acc;
                }, [])
                .map((p, idx) => p === "…"
                  ? <span key={`e${idx}`} className="px-1 text-xs" style={{ color: "var(--text-muted)" }}>…</span>
                  : <button key={p} onClick={() => setPage(p)}
                      className="px-2 py-1 text-xs rounded cursor-pointer"
                      style={{ backgroundColor: p === safePage ? "var(--accent)" : "var(--bg-card-hover)", color: p === safePage ? "var(--bg-primary)" : "var(--text-secondary)", fontWeight: p === safePage ? 700 : 400 }}>
                      {p}
                    </button>
                )}
              <button onClick={() => setPage((p) => Math.min(totalPages, p + 1))} disabled={safePage === totalPages}
                className="px-2 py-1 text-xs rounded disabled:opacity-40 cursor-pointer"
                style={{ color: "var(--text-secondary)", backgroundColor: "var(--bg-card-hover)" }}>›</button>
              <button onClick={() => setPage(totalPages)} disabled={safePage === totalPages}
                className="px-2 py-1 text-xs rounded disabled:opacity-40 cursor-pointer"
                style={{ color: "var(--text-secondary)", backgroundColor: "var(--bg-card-hover)" }}>»</button>
            </div>
          </div>
        )}
      </div>

      {/* Modals */}
      {showBatchModal && (
        <NewBatchModal
          onClose={() => setShowBatchModal(false)}
          onCreated={() => { fetchDevices(); }}
        />
      )}

      {showAddDevice && (
        <AddDeviceModal
          onClose={() => setShowAddDevice(false)}
          onCreated={() => fetchDevices()}
        />
      )}

      {showDeleteUnprovisioned && (
        <DeleteUnprovisionedModal
          onClose={() => setShowDeleteUnprovisioned(false)}
          onDeleted={(count) => {
            fetchDevices();
          }}
        />
      )}

      {showMultiDelete && (
        <MultiDeleteModal
          selected={selected}
          devices={devices}
          onClose={() => setShowMultiDelete(false)}
          onDeleted={(deletedIds) => {
            setDevices((prev) => prev.filter((d) => !deletedIds.includes(d.id)));
            setSelected(new Set());
          }}
        />
      )}
    </div>
  );
}
