'use client';

// Inner shell that runs inside <PlayerProvider>. Owns variant selection,
// keyboard shortcuts and MediaSession wiring; renders the picked layout.

import { useCallback, useEffect, useImperativeHandle, useState } from 'react';
import { useIsPhone } from '@djangocfg/ui-core/hooks';
import { usePlayerAudio, usePlayerControls, usePlayerMeta } from './context/selectors';
import { useElementWidth } from './hooks/useResizeObserver';
import { useKeyboardShortcuts } from './hooks/useKeyboardShortcuts';
import { useMediaSession } from './hooks/useMediaSession';
import { CompactLayout, DefaultLayout } from './parts/Layout';
import type { PlayerHandle, PlayerProps, PlayerVariant } from './types';

const COMPACT_BREAKPOINT = 480;

type Props = Pick<
  PlayerProps,
  | 'className'
  | 'variant'
  | 'waveform'
  | 'reactiveCover'
  | 'onPrev'
  | 'onNext'
  | 'enableKeyboardShortcuts'
  | 'ariaLabel'
  | 'seekStartsPlayback'
  | 'autoFocus'
> & {
  handleRef?: React.Ref<PlayerHandle>;
};

export function PlayerShell({
  className = '',
  variant = 'auto',
  waveform,
  reactiveCover = false,
  onPrev,
  onNext,
  enableKeyboardShortcuts = true,
  ariaLabel,
  seekStartsPlayback = true,
  autoFocus = false,
  handleRef,
}: Props) {
  const [container, setContainer] = useState<HTMLDivElement | null>(null);
  const audio = usePlayerAudio();
  const controls = usePlayerControls();
  const meta = usePlayerMeta();
  const width = useElementWidth(container);
  const isPhone = useIsPhone();

  // `auto` resolves to the layout best for the available space:
  // - on a phone viewport we always use compact (regardless of container);
  // - otherwise compact only when the container itself is narrower than
  //   COMPACT_BREAKPOINT.
  const resolvedVariant: PlayerVariant =
    variant === 'auto'
      ? isPhone || (width > 0 && width < COMPACT_BREAKPOINT)
        ? 'compact'
        : 'default'
      : variant;

  useMediaSession(audio, meta, controls, onPrev, onNext);
  const hotkeys = useKeyboardShortcuts({
    audio,
    controls,
    enabled: enableKeyboardShortcuts,
  });

  // Compose the container state-ref with the hotkey scoping ref. Both want
  // to see the same DOM node — one for layout/keyboard-focus management, the
  // other for react-hotkeys-hook's scoped listener.
  const setRootRef = useCallback(
    (node: HTMLDivElement | null) => {
      setContainer(node);
      hotkeys.ref(node);
    },
    [hotkeys],
  );

  useImperativeHandle(
    handleRef,
    (): PlayerHandle => ({
      audio,
      play: () => controls.play(),
      pause: () => controls.pause(),
      seek: (s: number) => controls.seek(s),
      getCurrentTime: () => audio.currentTime,
      getDuration: () => (Number.isFinite(audio.duration) ? audio.duration : 0),
      focus: () => container?.focus(),
    }),
    [audio, controls, container],
  );

  // Keyboard shortcuts work only when the container can take focus.
  useEffect(() => {
    if (!container || container.hasAttribute('tabindex')) return;
    container.setAttribute('tabindex', '0');
  }, [container]);

  // Declarative autoFocus: focus the container once the DOM node is ready.
  // Parents that want a *fresh* focus per source remount us via `key={src}`.
  useEffect(() => {
    if (!autoFocus || !container) return;
    container.focus({ preventScroll: true });
  }, [autoFocus, container]);

  return (
    <div
      ref={setRootRef}
      role="group"
      aria-label={ariaLabel ?? 'Audio player'}
      className={`audioplayer @container/player rounded-lg border border-border/60 bg-card text-foreground shadow-none focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/50 ${className}`}
    >
      {resolvedVariant === 'compact' ? (
        <CompactLayout waveform={waveform} seekStartsPlayback={seekStartsPlayback} />
      ) : (
        <DefaultLayout
          waveform={waveform}
          reactiveCover={reactiveCover}
          onPrev={onPrev}
          onNext={onNext}
          seekStartsPlayback={seekStartsPlayback}
        />
      )}
    </div>
  );
}
