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

// Desktop wrapper for the resizable thread drawer. Sizing and the
// absolutely-positioned resize handle live here; the inner aside
// (`ThreadDrawer` below) owns the rounded TL/BL carves + bg.
// `overflow: visible` on the wrapper is critical — the handle sits
// at `left: -GAP_PX` inside the horseshoe void, and the aside's
// `overflow: hidden` would otherwise clip it.
export const ThreadDrawerResizable = style({
  position: 'relative',
  flexShrink: 0,
  flexGrow: 0,
  maxHeight: '100%',
  minHeight: 0,
  display: 'flex',
  flexDirection: 'column',
});

// Resize handle mirror of `PageNavResizeHandle` — sits in the 12px
// horseshoe void to the LEFT of the drawer (page-nav's handle sits in
// the gap to the right of the nav). Same cosmetics: thin indicator bar
// that fades in on hover/focus and stretches/shrinks at the clamps.
export const ThreadDrawerResizeHandle = style({
  position: 'absolute',
  top: 0,
  bottom: 0,
  left: `-${toRem(VOJO_HORSESHOE_GAP_PX)}`,
  width: toRem(VOJO_HORSESHOE_GAP_PX),
  cursor: 'col-resize',
  zIndex: 1,
  background: 'transparent',
  touchAction: 'none',
  outline: 'none',
  selectors: {
    '&::before': {
      content: '""',
      position: 'absolute',
      top: '50%',
      left: '50%',
      width: 2,
      height: toRem(36),
      transform: 'translate(-50%, -50%)',
      borderRadius: 1,
      backgroundColor: color.Surface.OnContainer,
      opacity: 0,
      transition:
        'opacity 140ms ease, height 140ms ease, width 140ms ease, background-color 140ms ease',
    },
    '&:hover::before, &:focus-visible::before': {
      opacity: 0.25,
    },
    '&:focus-visible::before': {
      backgroundColor: color.Primary.Main,
      opacity: 0.45,
    },
    '&[data-dragging="true"]::before': {
      opacity: 0.55,
      height: toRem(48),
      backgroundColor: color.Primary.Main,
    },
    '&[data-dragging="true"][data-at-min="true"]::before': {
      height: toRem(28),
      width: 3,
      opacity: 0.85,
    },
    '&[data-dragging="true"][data-at-max="true"]::before': {
      height: toRem(76),
      width: 2,
      opacity: 0.9,
    },
  },
});

// Layout copies element-web `_ThreadPanel.pcss:73-84`:
// `max-height: 100%` clamps the column to the parent's viewport-bound
// height; `min-height: 0` on the inner Scroll wrapper lets it shrink
// under content (otherwise flex-children grow with content and push
// the composer off-screen — bug observed on cold-load with many
// replies). Comment in element-web: «don't displace the composer».
//
// Horseshoe: rounded TL/BL mirrors the page-nav <-> chat and chat <->
// profile/media seams. Room.tsx paints the 12px void gap to the left
// of the drawer (`showThreadHorseshoe`) and the chat-column gets an
// explicit Background bg so the void can't bleed through.
//
// Sizing (`width`, `flexShrink`) was moved to `ThreadDrawerResizable`
// so the aside fills its resizable wrapper and the wrapper owns the
// flex-row contract with Room.tsx.
export const ThreadDrawer = style({
  flexGrow: 1,
  width: '100%',
  display: 'flex',
  flexDirection: 'column',
  // Match the chat surface (`RoomView.tsx` paints
  // `color.SurfaceVariant.Container` as its Page bg). Bubbles inside
  // the drawer are `color.Surface.Container` so the «darker card on
  // lighter surface» contrast reads identically to the main timeline.
  backgroundColor: color.SurfaceVariant.Container,
  minHeight: 0,
  overflow: 'hidden',
  borderTopLeftRadius: toRem(VOJO_HORSESHOE_RADIUS_PX),
  borderBottomLeftRadius: toRem(VOJO_HORSESHOE_RADIUS_PX),
});

// Mobile push: drawer occupies the whole content column, not a side pane.
// `padding-top: var(--vojo-safe-top)` keeps the drawer's `ThreadDrawerHeader`
// (back arrow + thread title + counter) clear of the Android status-bar
// icons. `#root` no longer reserves the inset itself (`src/index.css`),
// and the chat-column wrapper that hosts this drawer on mobile has no
// safe-top of its own (the silhouette in `RoomViewProfilePanel` owns the
// inset for the chat header — but the thread drawer mounts as a sibling
// and would otherwise land directly under the system icons). The desktop
// `ThreadDrawer` style sits inside the chat row that has `env()` left/right
// only, so it inherits no top inset and doesn't need this padding (and
// would just leave dead space below the chat-column-wrapper's chrome).
export const ThreadDrawerMobile = style({
  flexGrow: 1,
  width: '100%',
  maxHeight: '100%',
  display: 'flex',
  flexDirection: 'column',
  // Same chat-surface tone as the desktop drawer above.
  backgroundColor: color.SurfaceVariant.Container,
  minHeight: 0,
  paddingTop: 'var(--vojo-safe-top, 0px)',
});

export const ThreadDrawerHeader = style({
  flexShrink: 0,
  padding: `0 ${config.space.S200} 0 ${config.space.S400}`,
  borderBottomWidth: config.borderWidth.B300,
});

// Critical pair: `flexGrow: 1` lets the scroll wrapper take remaining
// space, `minHeight: 0` is what allows it to actually SHRINK under
// content (without it, flex-children grow to natural content size →
// composer pushed off viewport). `overflow: hidden` clips so the
// inner folds `<Scroll>` (which is `overflow: auto`) is the only
// scroller. Same trio that element-web uses on the timeline wrapper.
export const ThreadDrawerScroll = style({
  flexGrow: 1,
  minHeight: 0,
  overflow: 'hidden',
  position: 'relative',
});

// M4a: top padding bumped from S400 (16px) to S700 (32px). `<Message>`'s
// action bar (`MessageOptionsBase`, top: -30px in styles.css.ts:8-16)
// sits 30px above its row. Mid-list rows have the previous row's height
// absorbing that negative position, but the FIRST row (root event)
// only has this container's top padding above it — S400 wasn't enough,
// so the bar clipped at the scroll viewport's top edge on hover. S700
// gives the bar 32px of clearance, enough to render the ~28-32px hover
// bar fully on the root.
//
// Left/right padding zeroed: `ChannelRow` already provides an S400
// (16px) horizontal gutter per row, and stacking two S400 paddings
// pushed the avatar 32px from the drawer edge — a perceptibly off
// «double-gutter» look in the narrow side pane. With this gutter
// removed, the avatar sits at row-padding (16px) from the drawer's
// rounded edge, matching the channels main-timeline rhythm.
export const ThreadDrawerContent = style({
  display: 'flex',
  flexDirection: 'column',
  gap: config.space.S400,
  paddingTop: config.space.S700,
  paddingBottom: config.space.S400,
});

// Assistant transcript variant: the channels `<Message>` hover action bar (which the S700 top
// pad above clears) never renders here (assistant rows are plain divs), so the 32px would just be
// dead space under the header. Tighten it to a small, comfortable gap.
//
// Centring: the AI surface mounts this drawer with `variant="mobile"` even on desktop (it fills
// the bot content column, not a side pane), so on a wide web viewport the transcript would spread
// edge-to-edge — the user complaint that messages are "thrown into the corners". Cap it to the
// 960px bridge band (apps/widget-telegram `.app`) and centre it, with the same 40px desktop gutter
// the host hero uses (BotShell.HeroInner) so the bot's text lines up under the hero name. The row
// styles below drop their own horizontal padding so the gutter lives only here. On narrow screens
// the cap is inert and the 16px mobile gutter matches the previous layout — native is unchanged.
export const ThreadDrawerContentAssistant = style([
  ThreadDrawerContent,
  {
    paddingTop: config.space.S400,
    width: '100%',
    maxWidth: toRem(VOJO_BUBBLE_BAND_PX),
    marginLeft: 'auto',
    marginRight: 'auto',
    boxSizing: 'border-box',
    // 12px horseshoe-gap on mobile (aligns the bot text with the hero name + the composer, which
    // both use it), 40px hero gutter on desktop. Matches ThreadComposerAssistant / ComposerWrap.
    paddingLeft: toRem(VOJO_HORSESHOE_GAP_PX),
    paddingRight: toRem(VOJO_HORSESHOE_GAP_PX),
    '@media': {
      'screen and (min-width: 600px)': {
        paddingLeft: toRem(40),
        paddingRight: toRem(40),
      },
    },
  },
]);

export const ThreadDivider = style({
  height: 1,
  backgroundColor: color.Surface.ContainerLine,
  margin: `0 ${config.space.S400}`,
  flexShrink: 0,
});

// Two-line drawer header caption + subtitle (M3 polish). The caption is
// uppercase tracking-wide ALL-CAPS «ТРЕД», the subtitle is the channel
// reference «в #channel».
export const ThreadDrawerHeaderCaption = style({
  textTransform: 'uppercase',
  letterSpacing: '0.08em',
  fontWeight: 600,
  color: color.SurfaceVariant.OnContainer,
  opacity: 0.6,
});

export const ThreadDrawerHeaderSubtitle = style({
  color: color.Surface.OnContainer,
  fontWeight: 500,
});

// Counter row between the root and replies: dot + «N ОТВЕТОВ» uppercase
// label. Replaces the static 1-px divider when at least one reply exists.
export const ThreadCounterRow = style({
  display: 'flex',
  alignItems: 'center',
  gap: config.space.S200,
  padding: `${config.space.S100} ${config.space.S400}`,
  borderTop: `1px solid ${color.Surface.ContainerLine}`,
  borderBottom: `1px solid ${color.Surface.ContainerLine}`,
  flexShrink: 0,
});

export const ThreadCounterDot = style({
  flexShrink: 0,
  width: '6px',
  height: '6px',
  borderRadius: '50%',
  backgroundColor: color.Primary.Main,
});

export const ThreadCounterText = style({
  textTransform: 'uppercase',
  letterSpacing: '0.08em',
  fontSize: '11px',
  fontWeight: 600,
  color: color.SurfaceVariant.OnContainer,
  opacity: 0.7,
});

// Thread composer wrap — geometry mirrors the personal-chat composer
// in `RoomView.tsx`: a 12px outer pad on the sides + bottom (matches
// the horseshoe void gap) frames a card whose visual chrome is owned
// by `ChatComposer` from `RoomView.css.ts`. The class itself is
// reapplied to the inner wrap in `ThreadDrawer.tsx` so the same
// `globalStyle` rules (`Surface.Container` bg, 32px radius, dark
// touch-hover gate) reach the Editor inside.
export const ThreadComposer = style({
  flexShrink: 0,
  padding: `0 ${toRem(VOJO_HORSESHOE_GAP_PX)} ${toRem(VOJO_HORSESHOE_GAP_PX)}`,
});

// Assistant (AI bot) composer: centred in the same 960px bridge band as the transcript so the
// input form width matches the messages on wide web viewports (the user's "input form sized to the
// bridge content width" ask). Desktop gets the 40px hero gutter; mobile/native keep the 12px
// horseshoe-void padding the base ThreadComposer uses, so native is unchanged.
export const ThreadComposerAssistant = style([
  ThreadComposer,
  {
    width: '100%',
    maxWidth: toRem(VOJO_BUBBLE_BAND_PX),
    marginLeft: 'auto',
    marginRight: 'auto',
    boxSizing: 'border-box',
    '@media': {
      'screen and (min-width: 600px)': {
        paddingLeft: toRem(40),
        paddingRight: toRem(40),
      },
    },
  },
]);

// Bubble chrome itself lives in `Channel.css.ts` and applies via the
// row's `data-bubble="true"` marker (set by `ChannelLayout` when
// `headerInBubble` is enabled). Both the thread drawer and the
// channels main timeline opt in, so the look is shared.

export const ThreadEmptyState = style({
  padding: `${config.space.S500} ${config.space.S300}`,
  textAlign: 'center',
});

export const ThreadErrorState = style({
  padding: config.space.S400,
  display: 'flex',
  flexDirection: 'column',
  alignItems: 'center',
  gap: config.space.S300,
});

// --- Assistant (ChatGPT-style) transcript -----------------------------------------
// Used when ThreadDrawer is mounted with messageStyle="assistant" (the AI bot surface).
// The bot's turn is full-width plain text; the user's turn is a right-aligned bubble.

// Bot reply: no avatar/name/timestamp, just the rendered body. The horizontal gutter is owned by
// `ThreadDrawerContentAssistant` (the centred 960px band). The text column itself is capped to a
// ~768px reading measure (~70-75ch, ChatGPT-style) and left-aligned within the band, so long bot
// prose doesn't stretch to 100+ chars/line on a wide desktop. On mobile the band is already < 768
// so the cap is inert. User bubbles (right-aligned) keep the full band width.
export const AssistantBotRow = style({
  width: '100%',
  maxWidth: toRem(768),
  color: color.Surface.OnContainer,
});

// User turn: right-aligned row holding a bubble. Gutter lives on the centred content band above.
export const AssistantUserRow = style({
  display: 'flex',
  justifyContent: 'flex-end',
});

export const AssistantUserBubble = style({
  maxWidth: '85%',
  minWidth: 0,
  padding: `${config.space.S200} ${config.space.S400}`,
  borderRadius: config.radii.R400,
  // Match the input-form tone (RoomView.css `ChatComposer .Editor` = Surface.Container, the dark
  // card the user types into) rather than the brand lavender, so a sent bubble reads as the same
  // surface as the composer it came from.
  backgroundColor: color.Surface.Container,
  color: color.Surface.OnContainer,
});

// "Bot is typing" dots, shown after the last turn while the bot composes a reply.
const typingBlink = keyframes({
  '0%, 80%, 100%': { opacity: 0.2, transform: 'translateY(0)' },
  '40%': { opacity: 1, transform: `translateY(-${toRem(2)})` },
});

export const TypingDots = style({
  display: 'inline-flex',
  alignItems: 'center',
  gap: toRem(4),
  padding: `${config.space.S200} 0`,
});

export const TypingDot = style({
  width: toRem(6),
  height: toRem(6),
  borderRadius: '50%',
  backgroundColor: color.Surface.OnContainer,
  opacity: 0.2,
  animationName: typingBlink,
  animationDuration: '1.2s',
  animationIterationCount: 'infinite',
  selectors: {
    '&:nth-child(2)': { animationDelay: '0.2s' },
    '&:nth-child(3)': { animationDelay: '0.4s' },
  },
  '@media': {
    '(prefers-reduced-motion: reduce)': {
      animationName: 'none',
      opacity: 0.5,
    },
  },
});
