import React, { useEffect, useMemo, useRef, useState } from 'react';
import { detectMediaTypeFromUrl, getThumb, safeTitle } from './utils.js';
import { useToasts } from './Toasts.jsx';
import { log } from './logger.js';

export default function Player({ socket, roomId, state, isHost }) {
  const { push } = useToasts();
  const audioRef = useRef(null);
  const videoRef = useRef(null);

  const [err, setErr] = useState(null);
  const [useProxy, setUseProxy] = useState(false);
  const busyRef = useRef(false);
  const lastAppliedRef = useRef({ url: null });

  const mediaType = useMemo(() => {
    if (!state?.track?.url) return 'none';
    if (state?.track?.kind) return state.track.kind;
    return detectMediaTypeFromUrl(state.track.url) || 'audio';
  }, [state?.track?.url, state?.track?.kind]);

  const logicalTime = () => {
    if (!state) return 0;
    const { anchor = 0, anchorAt = 0, isPlaying = false } = state;
    if (!isPlaying) return anchor;
    const elapsed = (Date.now() - anchorAt) / 1000;
    return Math.max(0, anchor + elapsed);
  };

  const currentSrc = useMemo(() => {
    if (!state?.track?.url) return '';
    return useProxy ? `/api/proxy?url=${encodeURIComponent(state.track.url)}` : state.track.url;
  }, [state?.track?.url, useProxy]);

  const applyMediaState = async (el) => {
    if (!el || !state?.track?.url) return;
    if (busyRef.current) return;
    busyRef.current = true;
    try {
      const marker = `${state.track.url}|${useProxy ? 'px' : 'dir'}`;
      if (lastAppliedRef.current.url !== marker) {
        el.src = currentSrc;
        el.load();
        lastAppliedRef.current.url = marker;
      }
      const target = logicalTime();
      if (Number.isFinite(target)) {
        try { el.currentTime = Math.max(0, target); } catch {}
      }
      if (state.isPlaying) {
        await el.play().catch(() => {});
      } else {
        el.pause();
      }
      setErr(null);
    } catch (e) {
      log.error('Playback error', e);
      setErr(e?.message || 'Playback failed');
      push(`Playback failed: ${e?.message || 'Unknown error'}`, 'bad', 4500);
    } finally {
      busyRef.current = false;
    }
  };

  useEffect(() => {
    setUseProxy(false);
    lastAppliedRef.current.url = null;
    const el = mediaType === 'video' ? videoRef.current : audioRef.current;
    if (el) applyMediaState(el);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [state?.track?.url, mediaType]);

  useEffect(() => {
    const el = mediaType === 'video' ? videoRef.current : audioRef.current;
    if (!el) return;
    const target = logicalTime();
    const delta = target - el.currentTime;
    if (Math.abs(delta) > 0.35) {
      try { el.currentTime = Math.max(0, target); } catch {}
    }
    if (state.isPlaying && el.paused) {
      el.play().catch(() => {});
    } else if (!state.isPlaying && !el.paused) {
      el.pause();
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [state.isPlaying, state.anchor, state.anchorAt]);

  useEffect(() => {
    const onEnded = () => { if (isHost) socket.emit('ended', { roomId }); };
    const a = audioRef.current, v = videoRef.current;
    a?.addEventListener('ended', onEnded);
    v?.addEventListener('ended', onEnded);
    return () => {
      a?.removeEventListener('ended', onEnded);
      v?.removeEventListener('ended', onEnded);
    };
  }, [socket, roomId, isHost]);

  const onMediaError = () => {
    if (!useProxy) {
      setUseProxy(true);
      lastAppliedRef.current.url = null;
      const el = mediaType === 'video' ? videoRef.current : audioRef.current;
      if (el) applyMediaState(el);
    } else {
      setErr('Playback failed (even via proxy)');
    }
  };

  const title = state?.track ? safeTitle(state.track) : 'No track selected';
  const thumb = state?.track?.thumb || getThumb(state?.track?.meta);

  return (
    <div style={{ position:'relative' }}>
      <div
        className="hero-thumb"
        style={{ backgroundImage: thumb ? `url("${thumb}")` : undefined }}
        aria-hidden
      />
      <div className="ambient"></div>

      <div className="now-playing" style={{ marginBottom: 10, position:'relative' }}>
        <div className="thumb" style={{ width:72, height:72, backgroundImage: thumb ? `url("${thumb}")` : undefined }} />
        <div style={{ minWidth:0, flex:1 }}>
          <div style={{ fontWeight:700, overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>{title}</div>
          <div style={{ fontSize:12, color:'var(--muted)', overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>
            {state?.track?.meta?.artists?.join?.(', ') || state?.track?.meta?.artist || state?.track?.meta?.album || state?.track?.kind?.toUpperCase()}
          </div>
        </div>
        {!isHost && <div className="tag">Listener</div>}
      </div>

      {mediaType === 'video' ? (
        <video
          ref={videoRef}
          src={currentSrc}
          onError={onMediaError}
          controls={isHost}
          playsInline
          style={{ width:'100%', maxHeight: '56vh', background:'#000' }}
          crossOrigin="anonymous"
        />
      ) : mediaType === 'audio' ? (
        <audio
          ref={audioRef}
          src={currentSrc}
          onError={onMediaError}
          controls={isHost}
          style={{ width:'100%' }}
          crossOrigin="anonymous"
        />
      ) : (
        <div style={{ color:'var(--muted)', padding:'12px 0' }}>No track selected</div>
      )}

      {useProxy && (
        <div style={{ marginTop:8, fontSize:12, color:'var(--muted)' }}>
          Using proxy due to CORS on the original media URL.
        </div>
      )}
      {err && <div style={{ marginTop:8, color:'var(--bad)' }}>{err}</div>}
    </div>
  );
}
