'use client';

import { Volume2, VolumeX } from 'lucide-react';
import { useEffect, useRef, useState } from 'react';
import { useMediaQuery } from '@djangocfg/ui-core/hooks';
import { usePlayerAudio, usePlayerControls } from '../../context/selectors';
import { IconButton } from './IconButton';

const CLOSE_DELAY_MS = 120;

// `audio.volume` is read-only on iOS Safari (controlled by hardware buttons),
// so a JS slider does nothing useful there. Detect once at module load.
function isIosSafari(): boolean {
  if (typeof navigator === 'undefined') return false;
  const ua = navigator.userAgent;
  const iOS = /iPad|iPhone|iPod/.test(ua) ||
    (navigator.platform === 'MacIntel' && (navigator as { maxTouchPoints?: number }).maxTouchPoints! > 1);
  return iOS;
}
const HIDE_VOLUME = isIosSafari();

export function VolumeControl() {
  const audio = usePlayerAudio();
  const { setVolume, toggleMute } = usePlayerControls();
  const [volume, setVol] = useState(audio.volume);
  const [muted, setMuted] = useState(audio.muted);
  const [isOpen, setOpen] = useState(false);
  const closeTimer = useRef<ReturnType<typeof setTimeout> | null>(null);

  // Touch devices have no hover — open the popover on click instead.
  const isTouch = useMediaQuery('(hover: none), (pointer: coarse)');

  useEffect(() => {
    const sync = () => {
      setVol(audio.volume);
      setMuted(audio.muted);
    };
    audio.addEventListener('volumechange', sync);
    return () => audio.removeEventListener('volumechange', sync);
  }, [audio]);

  useEffect(() => {
    return () => {
      if (closeTimer.current) clearTimeout(closeTimer.current);
    };
  }, []);

  // Close on outside-click in touch mode.
  const containerRef = useRef<HTMLDivElement | null>(null);
  useEffect(() => {
    if (!isOpen || !isTouch) return;
    const onDown = (e: PointerEvent) => {
      if (!containerRef.current) return;
      if (!containerRef.current.contains(e.target as Node)) setOpen(false);
    };
    document.addEventListener('pointerdown', onDown);
    return () => document.removeEventListener('pointerdown', onDown);
  }, [isOpen, isTouch]);

  if (HIDE_VOLUME) {
    // iOS Safari can't change volume via JS — keep mute toggle only.
    return (
      <IconButton
        label={muted ? 'Unmute' : 'Mute'}
        shortcut="M"
        active={muted}
        onClick={() => {
          toggleMute();
          setMuted(audio.muted);
        }}
      >
        {muted || volume === 0 ? <VolumeX size={16} strokeWidth={1.75} /> : <Volume2 size={16} strokeWidth={1.75} />}
      </IconButton>
    );
  }

  const cancelClose = () => {
    if (closeTimer.current) {
      clearTimeout(closeTimer.current);
      closeTimer.current = null;
    }
  };
  const scheduleClose = () => {
    cancelClose();
    closeTimer.current = setTimeout(() => setOpen(false), CLOSE_DELAY_MS);
  };
  const open = () => {
    cancelClose();
    setOpen(true);
  };

  const Icon = muted || volume === 0 ? VolumeX : Volume2;

  // Hover bindings only apply on devices with real hover. On touch the popover
  // is toggled by the icon click.
  const hoverHandlers = isTouch
    ? {}
    : {
        onPointerEnter: open,
        onPointerLeave: scheduleClose,
        onFocusCapture: open,
        onBlurCapture: (e: React.FocusEvent) => {
          if (!e.currentTarget.contains(e.relatedTarget as Node | null)) scheduleClose();
        },
      };

  return (
    <div ref={containerRef} className="relative" {...hoverHandlers}>
      <IconButton
        label={isOpen ? 'Close volume' : muted ? 'Unmute' : 'Volume'}
        shortcut={isTouch ? undefined : 'M'}
        active={muted}
        // Inside the popover wrapper — disable IconButton's tooltip when the
        // popover is open (the popover already shows controls; nesting Radix
        // tooltip+popover content fights for focus/dismiss).
        noTooltip={isOpen}
        onClick={() => {
          if (isTouch) {
            setOpen((v) => !v);
            return;
          }
          toggleMute();
          setMuted(audio.muted);
        }}
      >
        <Icon size={16} strokeWidth={1.75} />
      </IconButton>
      {isOpen && (
        <div
          className="absolute bottom-full left-1/2 z-20 -translate-x-1/2 pb-2"
          onPointerEnter={isTouch ? undefined : open}
          onPointerLeave={isTouch ? undefined : scheduleClose}
        >
          <div className="flex items-center gap-2 rounded-md border border-border/60 bg-card px-3 py-2 shadow-sm">
            <input
              type="range"
              min={0}
              max={1}
              step={0.01}
              value={muted ? 0 : volume}
              onChange={(e) => {
                const v = parseFloat(e.target.value);
                setVolume(v);
                setVol(v);
                if (v > 0) setMuted(false);
              }}
              className="h-1 w-32 appearance-none rounded-full bg-muted accent-foreground"
              aria-label="Volume"
            />
            <span className="w-8 tabular-nums text-right text-[10px] text-muted-foreground">
              {Math.round((muted ? 0 : volume) * 100)}
            </span>
            {isTouch && (
              <button
                type="button"
                aria-label={muted ? 'Unmute' : 'Mute'}
                className="audioplayer-press grid h-7 w-7 place-items-center rounded text-muted-foreground hover:bg-accent"
                onClick={() => {
                  toggleMute();
                  setMuted(audio.muted);
                }}
              >
                {muted ? <VolumeX size={14} strokeWidth={1.75} /> : <Volume2 size={14} strokeWidth={1.75} />}
              </button>
            )}
          </div>
        </div>
      )}
    </div>
  );
}
