import { globalStyle, keyframes, style } from '@vanilla-extract/css';
import { RecipeVariants, recipe } from '@vanilla-extract/recipes';
import { DefaultReset, color, config, toRem } from 'folds';
import {
  VOJO_BUBBLE_BAND_PX,
  VOJO_HORSESHOE_GAP_PX,
  VOJO_STICKY_DATE_TOP_PX,
} from '../../styles/horseshoe';

// Timeline band (every room class — 1:1 bubble, group, channel) — centre the
// message column in the same band
// the AI-bot chat uses (ThreadDrawerContentAssistant), so on wide web viewports
// the chat is centred instead of spreading edge-to-edge. Inert on mobile (band
// > viewport). The composer mirrors this via ComposerBubbleBand; both read the
// shared VOJO_BUBBLE_BAND_PX so they can't desync. The horizontal gutter is the
// SAME as the AI-bot chat (ThreadDrawerContentAssistant): 12px on native, 40px on
// desktop, applied to both edges so peer (left) and own (right) messages share
// the bot's «ideal» edge indent. MUST match ComposerBubbleBand or the message
// column and the input box won't line up.
export const BubbleTimelineBand = style({
  width: '100%',
  maxWidth: toRem(VOJO_BUBBLE_BAND_PX),
  marginLeft: 'auto',
  marginRight: 'auto',
  boxSizing: 'border-box',
  paddingLeft: toRem(VOJO_HORSESHOE_GAP_PX),
  paddingRight: toRem(VOJO_HORSESHOE_GAP_PX),
  '@media': {
    'screen and (min-width: 600px)': {
      paddingLeft: toRem(40),
      paddingRight: toRem(40),
    },
  },
});

// Day capsule for the timeline («Среда, 4 июня» / «Сегодня»), shared by every
// room class (1:1 bubble, group, channel) —
// a single dark-blue pill in the message-input tone (Surface.Container, the same
// token the composer card paints with), centred, with generous rounding. No
// border, no echo.
//
// It's a real CSS `position: sticky` element (engaged via the
// `[data-sticky-dates="on"]` rule below), so while you scroll through a day it
// stays pinned at the top, then settles back into its empty slot when you reach
// that day's start. Because sticky is compositor-driven it NEVER jitters (the old
// JS-transform emulation did).
export const BubbleDayCapsule = style({
  display: 'inline-flex',
  alignItems: 'center',
  justifyContent: 'center',
  padding: `${toRem(5)} ${config.space.S400}`,
  borderRadius: toRem(14),
  backgroundColor: color.Surface.Container,
  // Token (not a literal) so the date stays readable in BOTH themes — a
  // hard-coded light grey was ~1.7:1 on the white light-theme capsule.
  color: color.Surface.OnContainer,
  fontSize: toRem(13),
  lineHeight: toRem(18),
  fontWeight: 500,
  whiteSpace: 'nowrap',
});

// Centred row holding the inline day capsule, and the real sticky element. The
// gap should read as EQUAL above and below the capsule. The previous day's last
// message adds nothing below itself (rows space via margin-top only), but the
// next day's first message adds its own SENDER_GAP (S300) on top — so the row's
// bottom margin is S300 less than its top (S500), making the effective gap
// symmetric at ~S500 on both sides.
export const BubbleDayCapsuleRow = style({
  display: 'flex',
  justifyContent: 'center',
  margin: `${config.space.S500} 0 ${config.space.S300}`,
});

// Stickiness is toggled by an attribute the RoomTimeline scroll effect sets on
// the scroll container: ON while scrolled up into history, OFF at the live
// bottom (so no date is stuck at the top while the composer is up). Toggling
// `position` (sticky↔static) causes no layout shift — sticky reserves the same
// in-flow slot as static. The row's containing block is the tall timeline
// column, so the pill has the full day to stick across.
globalStyle(`[data-sticky-dates='on'] ${BubbleDayCapsuleRow}`, {
  position: 'sticky',
  top: toRem(VOJO_STICKY_DATE_TOP_PX),
  zIndex: 3,
});

// Timeline scroll container — a plain native scroller (replaces folds' <Scroll>).
// We deliberately do NOT style `::-webkit-scrollbar`: defining it forces a
// space-RESERVING classic bar even on Android, which pushed own (right) messages
// ~6px further from the edge than peer (left) ones. With no webkit rule, Android
// WebView draws its NATIVE OVERLAY bar — thin, auto-hiding, and reserving ZERO
// space — so the scrollbar is no longer counted in the message gutter and both
// sides sit at the same inset. `scrollbar-width: thin` keeps the desktop bar slim;
// `scrollbar-color` gives it a subtle thumb on a transparent track.
export const TimelineScroll = style({
  width: '100%',
  height: '100%',
  overflowX: 'hidden',
  overflowY: 'auto',
  scrollbarWidth: 'thin',
  scrollbarColor: `${color.SurfaceVariant.ContainerLine} transparent`,
});

export const TimelineFloat = recipe({
  base: [
    DefaultReset,
    {
      position: 'absolute',
      left: '50%',
      transform: 'translateX(-50%)',
      zIndex: 1,
      minWidth: 'max-content',
    },
  ],
  variants: {
    position: {
      Top: {
        top: config.space.S400,
      },
    },
  },
  defaultVariants: {
    position: 'Top',
  },
});

export type TimelineFloatVariants = RecipeVariants<typeof TimelineFloat>;

// "Jump to latest" FAB. Bottom-right, circular, lavender brand accent.
// `data-hidden` encodes visibility (state inline-styled would clobber the
// `:active` press feedback). Inline `bottom` at the use site offsets for
// the live composer height.
export const JumpToLatestFab = style([
  DefaultReset,
  {
    position: 'absolute',
    right: config.space.S400,
    width: toRem(44),
    height: toRem(44),
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'center',
    backgroundColor: color.Primary.Main,
    color: color.Primary.OnMain,
    borderRadius: '50%',
    border: 'none',
    cursor: 'pointer',
    boxShadow: '0 4px 12px rgba(0, 0, 0, 0.28), 0 2px 4px rgba(0, 0, 0, 0.16)',
    transition: 'transform 180ms ease-out, opacity 180ms ease-out, background-color 120ms ease',
    zIndex: 5,
    transform: 'scale(1)',
    opacity: 1,
    selectors: {
      '&[data-hidden="true"]': {
        transform: 'scale(0.6)',
        opacity: 0,
        pointerEvents: 'none',
      },
      '&:active': {
        transform: 'scale(0.94)',
      },
    },
    '@media': {
      '(prefers-reduced-motion: reduce)': {
        transition: 'none',
      },
    },
  },
]);

// Mouse-only hover brighten; touch sessions stay flat to avoid the stuck
// `:hover` paint on Android WebView (same precedent as ChatComposer).
globalStyle(`:root[data-input="mouse"] ${JumpToLatestFab}:hover`, {
  filter: 'brightness(1.08)',
});

// Bounce animation played when a fresh live message arrives while the
// user is scrolled away from the live edge — signals "there's something
// new below" without dragging in a numeric badge. The slot is keyed by
// a counter at the use site so each new message remounts the span and
// restarts the animation.
const pulseKeyframes = keyframes({
  '0%': { transform: 'scale(1)' },
  '40%': { transform: 'scale(1.28)' },
  '100%': { transform: 'scale(1)' },
});

export const FabIconPulseSlot = style({
  display: 'flex',
  animation: `${pulseKeyframes} 520ms ease-out`,
  '@media': {
    '(prefers-reduced-motion: reduce)': {
      animation: 'none',
    },
  },
});
