'use client';

/**
 * VideoPlayer — composable shell over `media-chrome` web components.
 *
 * The shell is just a `<MediaController>` wrapper + a `<CanvasDispatcher>`
 * that mounts the right media element (`<video>`, `<youtube-video>`,
 * `<vimeo-video>`, `<hls-video>`, `<iframe>`) into the `media` slot.
 *
 * Custom layouts: pass `children` to replace the default control bar.
 * `controls={false}` opts out of any control surface (useful for
 * iframe sources where the embed renders its own UI).
 */

import { useEffect, useMemo, useRef, type CSSProperties } from 'react';
import { MediaController, MediaGestureReceiver } from 'media-chrome/react';
import { cn } from '@djangocfg/ui-core/lib';
import './styles/video-player.css';

import type { VideoPlayerProps, AspectRatioValue } from './types';
import { parseEmbedUrl } from './utils/parse-embed-url';
import { CanvasDispatcher } from './canvas/canvas-dispatcher';
import {
  ControlsBar,
  PlayButton,
  CenterPlay,
  SeekBar,
  Volume,
  PlaybackRate,
  Pip,
  Fullscreen,
} from './parts';

function aspectRatioStyle(ar: AspectRatioValue): CSSProperties | undefined {
  if (ar === 'fill') return { height: '100%' };
  if (ar === 'auto') return undefined;
  return { aspectRatio: String(ar) };
}

export function VideoPlayer({
  source,
  controls = true,
  aspectRatio = 16 / 9,
  className,
  children,
  autoFocus = false,
  ...settings
}: VideoPlayerProps) {
  const normalized = useMemo(
    () => (typeof source === 'string' ? parseEmbedUrl(source) : source),
    [source],
  );

  // Provider embeds (YouTube / Vimeo) render their own native control set
  // inside an opaque iframe. media-chrome can request play/pause but its
  // `[mediapaused]` state desyncs from the real player, and YouTube's ToS
  // chrome (title bar, branding tray, share/clock icons) bleeds through and
  // CANNOT be hidden — so layering OUR controls on top produces a duplicate,
  // jittery UI (two play affordances, two bottom bars). For these sources we
  // let the native player own playback entirely: one coherent control set,
  // native hover behaviour, zero duplication. Direct media (native `<video>`,
  // HLS) is fully driven by media-chrome, so we keep OUR themed controls.
  const isProviderEmbed =
    normalized.type === 'iframe' ||
    normalized.type === 'youtube' ||
    normalized.type === 'vimeo';
  const showControls = controls && !isProviderEmbed;

  // MediaController is a custom element; without `tabindex` it cannot take
  // focus, so its built-in keyboard shortcuts (space/arrows/f) never fire.
  // We type the ref through the element interface (HTMLElement methods are
  // all we use) — media-chrome's full MediaController type pulls private
  // fields we don't need to see.
  const controllerRef = useRef<HTMLElement | null>(null);

  useEffect(() => {
    if (!autoFocus) return;
    const el = controllerRef.current;
    if (!el) return;
    if (!el.hasAttribute('tabindex')) el.setAttribute('tabindex', '0');
    el.focus({ preventScroll: true });
  }, [autoFocus]);

  return (
    <MediaController
      ref={(el) => {
        controllerRef.current = el as unknown as HTMLElement | null;
      }}
      // Fade controls + scrim after 2.5s of inactivity while playing;
      // they reappear on mousemove / pause / focus (media-chrome built-in).
      autohide="2.5"
      className={cn(
        'video-player relative block w-full overflow-hidden rounded-lg bg-black',
        'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/50',
        className,
      )}
      style={aspectRatioStyle(aspectRatio)}
    >
      <CanvasDispatcher source={normalized} {...settings} />
      {/* Click / tap anywhere on the video toggles play. media-chrome's
          gesture receiver handles desktop click + mobile tap (and on touch
          a tap also reveals/hides the controls). Only mounted for direct
          media — provider embeds own their own click handling natively. */}
      {showControls && <MediaGestureReceiver />}
      {children ??
        (showControls && (
          <>
            {/* Big centered play over the poster / paused frame. */}
            <CenterPlay />
            <ControlsBar>
              <PlayButton />
              <SeekBar />
              <Volume iconOnly />
              <PlaybackRate />
              <Pip />
              <Fullscreen />
            </ControlsBar>
          </>
        ))}
    </MediaController>
  );
}
