import React, { MouseEventHandler, ReactNode, useRef } from 'react';
import { toRem } from 'folds';
import {
  StreamMediaBubble,
  StreamMediaUsernameLabel,
  StreamMediaUsernameOverlay,
} from './StreamMedia.css';
import { logMedia, useMediaMeasureDebug } from './streamMediaDebug';

const STREAM_MEDIA_MAX_DIM = 320;
const STREAM_MEDIA_MIN_ASPECT = 3 / 4;
const STREAM_MEDIA_MAX_ASPECT = 4 / 3;

export type StreamMediaShellProps = {
  naturalW?: number;
  naturalH?: number;
  own: boolean;
  overlay?: ReactNode;
  senderId?: string;
  onUsernameClick?: MouseEventHandler<HTMLButtonElement>;
  onUsernameContextMenu?: MouseEventHandler<HTMLButtonElement>;
  children: ReactNode;
};

function computeBoxStyle(naturalW?: number, naturalH?: number): React.CSSProperties {
  // Explicit pixel width + height — required so the inner content (folds
  // ImageContent / VideoContent — `RelativeBase` with `height: 100%`) gets
  // a definite parent height to resolve against. `max-width: 100%` from
  // StreamMediaBubble + the surrounding StreamBubble's mediaMode
  // `display: block; width: 100%` chain shrinks the bubble on narrow
  // viewports; the small aspect drift this introduces is masked by
  // `object-fit: cover` (image) / `contain` (video) on the inner element.
  const naturalAspect = naturalW && naturalH ? naturalW / naturalH : NaN;
  if (
    !Number.isFinite(naturalAspect) ||
    naturalAspect < STREAM_MEDIA_MIN_ASPECT ||
    naturalAspect > STREAM_MEDIA_MAX_ASPECT
  ) {
    return { width: toRem(STREAM_MEDIA_MAX_DIM), height: toRem(STREAM_MEDIA_MAX_DIM) };
  }
  if (naturalAspect >= 1) {
    const w = Math.min(STREAM_MEDIA_MAX_DIM, naturalW!);
    return { width: toRem(w), height: toRem(w / naturalAspect) };
  }
  const h = Math.min(STREAM_MEDIA_MAX_DIM, naturalH!);
  return { width: toRem(h * naturalAspect), height: toRem(h) };
}

// Shared chrome for image / video timeline bubbles: square-ish bubble with
// asymmetric notch + 1px pseudo-frame, and the sender username overlaid
// top-left as a text chip. Caller plugs in the actual media renderer as
// `children`.
//
// Tab order: chip rendered BEFORE children so keyboard focus visits the
// username (top-left visual) before the media tap target — matches reading
// order.
export function StreamMediaShell({
  naturalW,
  naturalH,
  own,
  overlay,
  senderId,
  onUsernameClick,
  onUsernameContextMenu,
  children,
}: StreamMediaShellProps) {
  const bubbleRef = useRef<HTMLDivElement>(null);
  const computedStyle = computeBoxStyle(naturalW, naturalH);

  logMedia('StreamMediaShell', {
    own,
    naturalW,
    naturalH,
    overlayPresent: !!overlay,
    senderId,
    computedStyle: { ...computedStyle },
  });

  useMediaMeasureDebug(bubbleRef, [computedStyle.width, computedStyle.height]);

  return (
    <div ref={bubbleRef} className={StreamMediaBubble({ own })} style={computedStyle}>
      {overlay && (
        <div className={StreamMediaUsernameOverlay}>
          <button
            type="button"
            className={StreamMediaUsernameLabel}
            data-user-id={senderId}
            onClick={(e) => {
              e.stopPropagation();
              onUsernameClick?.(e);
            }}
            onContextMenu={(e) => {
              e.stopPropagation();
              onUsernameContextMenu?.(e);
            }}
          >
            {overlay}
          </button>
        </div>
      )}
      {children}
    </div>
  );
}
