import { style } from '@vanilla-extract/css';
import { color, toRem } from 'folds';
import { VOJO_HORSESHOE_GAP_PX, VOJO_HORSESHOE_RADIUS_PX } from '../../styles/horseshoe';

// Re-exported so the TSX can pick up the constants without crossing
// the vanilla-extract / runtime boundary twice.
export const HORSESHOE_RADIUS_PX = VOJO_HORSESHOE_RADIUS_PX;
export const HORSESHOE_GAP_PX = VOJO_HORSESHOE_GAP_PX;

// Outer container — `position: relative` anchor for the two absolutely-
// positioned panes (`appBody` and `silhouette`). `overflow: hidden`
// clips anything that overflows the wrapper's bounds and crops the
// rounded carves on both panes against the container's bg (which is
// painted with `VOJO_HORSESHOE_VOID_COLOR` inline when the sheet is
// active, so the carved-out areas read as the same near-black seam
// used everywhere else in the app).
//
// `flex: 1` so the container fills whatever flex slot it's mounted in
// (PageNav's inner column for the Direct route).
//
// `marginTop: -var(--vojo-safe-top)` extends the container UP over the
// status-bar safe-top zone reserved by `PageNav` via `padding-top`,
// and the compensating `paddingTop: var(--vojo-safe-top)` on `appBody`
// keeps the wrapped DM list anchored at the same visual Y as before
// the shift. The combination has two load-bearing effects:
//
//   (1) The settings-sheet clip-path mask on `appBody` carves rounded
//       BL/BR into an opaque surface that already paints THROUGH the
//       status-bar strip — without the upward extension the carve
//       would visibly stop at the bottom of the system-tray strip.
//   (2) `appBody`'s bg paints the safe-top strip itself in the same
//       `SurfaceVariant.Container` tone as `PageNav-inner` / the
//       pager's static header, giving the system-tray text a
//       consistent backdrop across surfaces.
//
// Note: the curtain never RESTS inside the safe-top zone — every snap
// destination floors at `top: 0` of the stage (= `y = safe-top` in
// viewport), preserving the system-tray strip. (A live drag may
// transiently overshoot above it under the finger — the free-range
// gestures are unclamped by design — but the release always settles
// back to a legal snap.) See the «pinned visual contract» comment in
// `components/stream-header/geometry.ts` for the full invariant.
export const container = style({
  position: 'relative',
  display: 'flex',
  flex: 1,
  flexDirection: 'column',
  minWidth: 0,
  minHeight: 0,
  overflow: 'hidden',
  marginTop: 'calc(-1 * var(--vojo-safe-top, 0px))',
});

// === App body === Holds the wrapped children (the DM list — header,
// scroll content, DirectSelfRow). Fills the container via `inset: 0`.
// Does NOT translate or shrink — the DM list stays exactly where it
// was in the closed state. Instead, the bottom of the pane is masked
// away by an animated `clip-path:
// inset(...)` with rounded BL/BR corners — the user sees the visible
// top portion of the DM list with a rounded carve at the new bottom
// edge, exactly like the profile horseshoe shows the chat with a
// rounded TOP carve as the panel masks it from above.
//
// Why clip-path rather than flex-shrink + margin-bottom: a flex-
// shrink approach changes the scroll-container's height every render,
// and the DM list's `@tanstack/react-virtual` re-measures items mid-
// gesture. Why not `transform: translateY` either: translating moves
// the whole pane up off the top of the viewport, including the
// StreamHeader the user wants to keep visible. Clip-path leaves
// layout unchanged — the DM list keeps its scroll position, its
// measured heights, and its top items in place; only the bottom edge
// of what's visible gets carved into the void below.
//
// `backgroundColor: SurfaceVariant.Container` is load-bearing on two
// counts: (1) it must be OPAQUE so the container's void colour
// (painted inline when the sheet is active) doesn't bleed through gaps
// between DM list rows; (2) the safe-top padding region of THIS
// element is what paints the system-tray strip when the wrapper
// container is extended up over it (see `container.marginTop` above).
// Picking `SurfaceVariant.Container` (not `Background.Container`)
// matches the Bots / ChannelsRoot status-bar tone exactly — Bots
// renders `PageNav-inner.bg = SurfaceVariant.Container` in the safe-
// top zone, and the StreamHeader curtain (`Background.Container`)
// overpaints that lighter strip with the darker tone as it's dragged
// up. Mirroring the same two tones here gives Direct the same visible
// «curtain darkens the strip» transition the user expects.
//
// `flex: column` so the children (which expect a flex column parent
// — PageNav uses it) still stack naturally. `paddingTop:
// var(--vojo-safe-top)` reserves status-bar space INSIDE appBody so
// the wrapped StreamHeader.stage starts at the same Y as before the
// `container.marginTop` shift extended us upward.
export const appBody = style({
  position: 'absolute',
  top: 0,
  left: 0,
  right: 0,
  bottom: 0,
  display: 'flex',
  flexDirection: 'column',
  minWidth: 0,
  minHeight: 0,
  backgroundColor: color.SurfaceVariant.Container,
  paddingTop: 'var(--vojo-safe-top, 0px)',
  willChange: 'clip-path',
});

// === Silhouette === The Settings sheet's surface. Anchored at the
// bottom of the container; its height animates 0 → railHeight as the
// user drags up. Rounded TL/TR carve the top edge against the void
// gap between it and the translated-up appBody.
//
// `overflow: hidden` clips `panelContent` (which is railHeight tall,
// top-anchored) so the visible portion of the panel is just the
// silhouette's current height — the user sees more of the panel
// content reveal from the top as silhouette grows.
//
// Background: `SurfaceVariant.Container` (Dawn bg = #181a20) — the
// chat-pane tone, same as the Settings PageNav inside (set via
// `surface="surfaceVariant"`). Load-bearing: the silhouette's bg
// shows through the 20px drag-handle band at the top so the seam
// matches the PageNav tone. With `Background.Container` (#0d0e11)
// here, the user saw a dark stripe at that seam on Samsung S24
// edge-to-edge; matching silhouette to the PageNav tone closes it.
// Same idea as commit 77bb72d which dynamically retunes
// `--vojo-safe-area-bg` while a Room is mounted to keep the
// system-bar strips and the chat surface in lockstep.
export const silhouette = style({
  position: 'absolute',
  bottom: 0,
  left: 0,
  right: 0,
  display: 'flex',
  flexDirection: 'column',
  overflow: 'hidden',
  backgroundColor: color.SurfaceVariant.Container,
  willChange: 'height, border-top-left-radius, border-top-right-radius',
});

// Anchored at the TOP of `silhouette` so as silhouette grows from 0
// upward, more of the panel content reveals from the top down. The
// handle and Settings title are at the top of `panelContent`, so they
// are visible at the very first pixel of drag — gives the user
// immediate "I'm opening Settings" feedback.
//
// Android nav-bar clearance is owned by `MainActivity.java`'s
// WindowInsets listener (the WebView is already sized above the nav
// bar). No `padding-bottom: env(...)` here — that would stack on top
// of the native padding and clip the Settings menu's bottom rows.
export const panelContent = style({
  position: 'absolute',
  top: 0,
  left: 0,
  right: 0,
  display: 'flex',
  flexDirection: 'column',
});

// Drag handle band — sits at the TOP of `panelContent` so it appears
// at the top edge of the emerging sheet as the user drags up. Mirror
// of the profile horseshoe handle (20px tall + 36×4 grabber). The
// whole band is the ONLY drag-to-close target — touches on the
// panel body below this strip do NOT initiate drag, so Settings's
// internal scroll works without conflict.
//
// `touchAction: none` ensures the browser doesn't try to scroll
// when the user drags on the handle (the whole gesture is ours).
export const panelHandle = style({
  flexShrink: 0,
  height: toRem(20),
  display: 'flex',
  alignItems: 'center',
  justifyContent: 'center',
  cursor: 'grab',
  touchAction: 'none',
  userSelect: 'none',
  selectors: {
    '&:active': { cursor: 'grabbing' },
  },
});

export const panelHandleBar = style({
  width: toRem(36),
  height: toRem(4),
  borderRadius: toRem(4),
  // Darker than the silhouette's SurfaceVariant bg so the grabber
  // reads against the panel without competing with content. The
  // Dawn `Background.Container` (#0d0e11) is one notch deeper than
  // `SurfaceVariant.Container` (#181a20) — same step-down used by
  // chat bubbles vs the chat surface.
  backgroundColor: color.Background.Container,
});

// Holds the Settings tree. `flex: 1` so it grows to fill the
// remaining `panelContent` height below the handle. No drag listeners
// here — Settings's own internal scroll handles touch events; the
// drag-to-close gesture is reserved for `panelHandle`.
export const panelBody = style({
  flex: 1,
  display: 'flex',
  flexDirection: 'column',
  minHeight: 0,
  minWidth: 0,
});
