import { useState, type ReactNode } from "react";
import { useTranslation } from "react-i18next";
import { Check, Pencil, Pin, PinOff, RotateCcw } from "lucide-react";
import { useScrollFade } from "../../lib/useScrollFade";
import { useHoverFocusWithin } from "../../lib/useHoverFocusWithin";
import { useMediaQuery } from "../../lib/useMediaQuery";
import { IconButton } from "./IconButton";
import { Pressable } from "./Pressable";
import Modal from "./Modal";
import { SURFACE } from "./surfaces";
// The shared floating side panel — one shell for the Feed / Plex / Playlists rails so they read as
// one system, and the same peek-open model as the nav rail: unpinned it sits as a small tab docked
// against the rail's right edge (this panel is the flex sibling right after it) and expands into a
// rounded glass card on hover/focus WITHOUT pushing content; pinned it stays expanded in-flow.
// `collapsed` (persisted per-account) therefore means "unpinned".
//
// On touch, and in a window below 768 (C2), there is no hover to peek with and no room to pin: the tab
// (shown at every width) opens the panel as a DRAWER over the content, with a scrim — ui/Modal's
// start-edge drawer, so Esc, Back, a tap outside, the focus trap and the scroll lock are the dialog's
// own. Pinning stays a button in the panel's header, offered only ≥ 1024 where a pinned panel leaves
// the content room; a pin saved on a desktop is left alone below that, not honoured.
// Where the panel is a drawer rather than a peeking card: a coarse pointer, or a window too narrow to
// lay a panel beside the content. And where a pinned panel still leaves the content room (≥ 1024).
const DRAWER_QUERY = "(pointer: coarse), (max-width: 767.98px)";
const PIN_ROOM_QUERY = "(min-width: 1024px)";
export default function SidePanel({
title,
icon,
count = 0,
collapsed,
onToggleCollapse,
editing = false,
onToggleEditing,
onReset,
editHint,
actions,
iconExpanded,
onTitleClick,
titleActionLabel,
children,
}: {
title: string;
icon: ReactNode;
count?: number;
collapsed: boolean;
onToggleCollapse: () => void;
// Customize (reorder/hide) mode — omit onToggleEditing to hide the pencil entirely.
editing?: boolean;
onToggleEditing?: () => void;
onReset?: () => void;
editHint?: string;
// Extra header controls shown when NOT editing (e.g. the feed's Clear all + Share view).
actions?: ReactNode;
// Optional override for the icon in the EXPANDED header only (the collapsed tab keeps the plain
// `icon`) — the feed passes its saved-views popover trigger here so the header icon opens the picker.
iconExpanded?: ReactNode;
// When set, the expanded-header title becomes a button (the feed opens its Personal Views modal).
onTitleClick?: () => void;
// Accessible name / tooltip describing what onTitleClick does (the plain title text alone doesn't).
titleActionLabel?: string;
children: ReactNode;
}) {
const { t } = useTranslation();
const fade = useScrollFade();
const peek = useHoverFocusWithin();
const drawerMode = useMediaQuery(DRAWER_QUERY, false);
const pinRoom = useMediaQuery(PIN_ROOM_QUERY, true);
const canPin = !drawerMode || pinRoom;
const pinned = !collapsed && canPin;
// A drawer never peeks: a tap would fire the emulated hover and open the card under the finger.
const expanded = pinned || (!drawerMode && peek.active);
const [drawerOpen, setDrawerOpen] = useState(false);
// Turning the tablet to a width where the panel is a card again, or pinning it, ends the drawer —
// adjusted during render, so it cannot come back open on the next turn.
if (drawerOpen && (!drawerMode || pinned)) setDrawerOpen(false);
const titleNode = onTitleClick ? (