// client/src/Room.jsx
import React, { useEffect, useMemo, useState } from 'react';
import { io } from 'socket.io-client';
import Player from './Player.jsx';
import Chat from './Chat.jsx';
import MemberList from './MemberList.jsx';
import { detectMediaTypeFromUrl, getThumb } from './utils.js';
import { useToasts } from './Toasts.jsx';

const socket = io('', { transports: ['websocket'] });

function DirectLinkModal({ open, onClose, onPick }) {
  const [url, setUrl] = useState('');
  const [type, setType] = useState('auto');
  useEffect(() => { if (!open) { setUrl(''); setType('auto'); } }, [open]);
  if (!open) return null;
  return (
    <div className="modal-backdrop" onClick={(e) => e.target === e.currentTarget && onClose()}>
      <div className="modal">
        <div className="section-title">Play a direct link</div>
        <div style={{ color:'var(--muted)', fontSize:13, marginBottom:8 }}>
          Paste a direct media URL (MP4, WEBM, MP3, M4A) or a YouTube URL/ID.
        </div>
        <input className="input" value={url} onChange={e => setUrl(e.target.value)}
          placeholder="https://example.com/video.mp4 or https://youtu.be/xxxx or 11-char ID" />
        <div style={{ display:'flex', gap:10, marginTop:10 }}>
          <select className="select" value={type} onChange={e => setType(e.target.value)}>
            <option value="auto">Auto-detect type</option>
            <option value="video">Force Video</option>
            <option value="audio">Force Audio</option>
            <option value="youtube">YouTube</option>
          </select>
          <button className="btn primary" onClick={() => onPick({ url, type })}>Set</button>
          <button className="btn" onClick={onClose}>Cancel</button>
        </div>
      </div>
    </div>
  );
}

function YouTubeModal({ open, onClose, onPick, ytError }) {
  const [idOrUrl, setIdOrUrl] = useState('');
  useEffect(() => { if (!open) setIdOrUrl(''); }, [open]);
  if (!open) return null;
  return (
    <div className="modal-backdrop" onClick={(e) => e.target === e.currentTarget && onClose()}>
      <div className="modal">
        <div className="section-title">Play YouTube (Vidfly)</div>
        <div style={{ color:'var(--muted)', fontSize:13, marginBottom:8 }}>
          Enter a YouTube URL or 11‑character ID. Playback auto-switches to proxy if CORS blocks it.
        </div>
        <input className="input" value={idOrUrl} onChange={e => setIdOrUrl(e.target.value)}
          placeholder="https://www.youtube.com/watch?v=XXXXXXXXXXX or XXXXXXXID" />
        <div style={{ display:'flex', gap:8, marginTop:10 }}>
          <button className="btn good" onClick={() => onPick(idOrUrl)}>Play</button>
          <button className="btn" onClick={onClose}>Close</button>
        </div>
        {ytError && (
          <div className="room-card" style={{ marginTop:12 }}>
            <div style={{ fontWeight:700, color:'var(--bad)' }}>YouTube failed</div>
            <div className="meta" style={{ marginTop:6 }}>{ytError.message}</div>
          </div>
        )}
      </div>
    </div>
  );
}

function RequestsPanel({ isHost, requests, onAct }) {
  if (!isHost || !requests.length) return null;
  return (
    <div className="panel" style={{ marginTop:12 }}>
      <div className="section-title">Song requests</div>
      <div style={{ display:'grid', gap:8 }}>
        {requests.map((r) => (
          <div key={r.requestId} className="room-card" style={{ display:'flex', alignItems:'center', justifyContent:'space-between', gap:10 }}>
            <div style={{ display:'flex', alignItems:'center', gap:10, minWidth:0 }}>
              <div className="thumb" style={{ width:48, height:48, backgroundImage: r.preview?.thumb ? `url("${r.preview.thumb}")` : undefined }} />
              <div style={{ minWidth:0 }}>
                <div style={{ fontWeight:700, overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>
                  {r.requester} → {r.query}
                </div>
                <div className="meta" style={{ marginTop:4, overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>
                  {r.preview?.title || (r.preview ? 'Result found' : 'Searching…')}
                </div>
              </div>
            </div>
            <div style={{ display:'flex', gap:8 }}>
              <button className="btn good" onClick={() => onAct('accept', r)} disabled={!r.preview}>Accept</button>
              <button className="btn" onClick={() => onAct('queue', r)} disabled={!r.preview}>Add to queue</button>
              <button className="btn warn" onClick={() => onAct('reject', r)}>Reject</button>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

export default function Room({ roomId, name, asHost, roomName }) {
  const { push } = useToasts();

  const [isHost, setIsHost] = useState(false);
  const [state, setState] = useState({ track: null, isPlaying: false, anchor: 0, anchorAt: 0, queue: [] });
  const [members, setMembers] = useState([]);
  const [partyName, setPartyName] = useState(roomName || roomId);

  const [showDirect, setShowDirect] = useState(false);
  const [showYT, setShowYT] = useState(false);
  const [ytError, setYtError] = useState(null);

  const [requests, setRequests] = useState([]);

  useEffect(() => {
    socket.emit('join_room', { roomId, name, asHost, roomName }, (resp) => {
      setIsHost(resp.isHost);
      if (resp.state) setState(s => ({ ...s, ...resp.state }));
      if (resp.roomName) setPartyName(resp.roomName);
    });

    socket.on('set_track', ({ track }) => setState(s => ({ ...s, track })));
    socket.on('play', ({ anchor, anchorAt }) => setState(s => ({ ...s, isPlaying: true, anchor, anchorAt })));
    socket.on('pause', ({ anchor, anchorAt }) => setState(s => ({ ...s, isPlaying: false, anchor, anchorAt })));
    socket.on('seek', ({ anchor, anchorAt, isPlaying }) => setState(s => ({ ...s, anchor, anchorAt, isPlaying })));
    socket.on('host_changed', ({ hostId }) => setIsHost(socket.id === hostId));
    socket.on('members', ({ members, roomName }) => { setMembers(members || []); if (roomName) setPartyName(roomName); });
    socket.on('system', ({ text }) => { if (text) console.log(text); });
    socket.on('queue_update', ({ queue }) => setState(s => ({ ...s, queue: queue || [] })));

    // Host receives a request → attach a preview via JioSaavn search (best effort)
    socket.on('song_request', async (req) => {
      if (!isHost) return;
      const enriched = { ...req, preview: null };
      try {
        const res = await fetch(`/api/result?q=${encodeURIComponent(req.query)}`);
        const data = await res.json();
        const list = Array.isArray(data?.data) ? data.data : (data?.results || data?.songs || data?.list || data?.items || data || []);
        const first = list?.[0];
        if (first) {
          const url = first.media_url || first.downloadUrl || first.url || first.perma_url || first.streamUrl;
          if (url) enriched.preview = { url, title: first.title || req.query, meta: first, kind: detectMediaTypeFromUrl(url) || 'audio', thumb: getThumb(first) };
        }
      } catch {}
      setRequests(prev => [enriched, ...prev].slice(0, 20));
    });

    socket.emit('rename', { roomId, newName: name });

    return () => {
      socket.off('set_track'); socket.off('play'); socket.off('pause'); socket.off('seek');
      socket.off('host_changed'); socket.off('members'); socket.off('system'); socket.off('queue_update'); socket.off('song_request');
    };
  }, [roomId, name, asHost, roomName, isHost]);

  // Direct links
  const setTrackAndClose = (track) => {
    socket.emit('set_track', { roomId, track });
    setShowDirect(false);
    setShowYT(false);
  };

  const pickDirectUrl = async ({ url, type }) => {
    if (!url) return;
    const isYT = (type === 'youtube') || detectMediaTypeFromUrl(url) === 'youtube' || /^[A-Za-z0-9_-]{11}$/.test(url);
    if (isYT) {
      setShowDirect(false);
      setShowYT(true);
      return;
    }
    const mediaType = (type === 'auto' || !type) ? (detectMediaTypeFromUrl(url) || 'audio') : type;
    if (mediaType === 'unknown') {
      alert('Unknown media type. Choose Audio or Video.');
      return;
    }
    const track = { url, title: url, meta: { source: 'direct' }, kind: mediaType };
    setTrackAndClose(track);
  };

  // YouTube via Vidfly only
  const resolveYouTube = async (idOrUrl) => {
    setYtError(null);
    const resp = await fetch(`/api/yt/source?url=${encodeURIComponent(idOrUrl)}`);
    const data = await resp.json();
    if (!resp.ok) {
      const message = data?.error || 'Failed to resolve YouTube';
      throw new Error(message);
    }
    return data;
  };

  const onPickYouTube = async (idOrUrl) => {
    try {
      const data = await resolveYouTube(idOrUrl);
      const track = {
        url: data.url,
        title: data.title || idOrUrl,
        meta: { thumb: data.thumbnail, source: data.source || 'vidfly', yt: true },
        kind: data.kind || 'video',
        thumb: data.thumbnail
      };
      setTrackAndClose(track);
    } catch (e) {
      setYtError({ message: e.message });
    }
  };

  const Controls = useMemo(() => (
    isHost ? (
      <div style={{ display:'flex', flexWrap:'wrap', gap:8 }}>
        <button className="btn" onClick={() => setShowDirect(true)}>Direct link</button>
        <button className="btn" onClick={() => setShowYT(true)}>YouTube</button>
        <button className="btn good" onClick={() => socket.emit('play', { roomId })}>Play</button>
        <button className="btn" onClick={() => socket.emit('pause', { roomId })}>Pause</button>
        <button className="btn" onClick={() => {
          const toStr = prompt('Seek to seconds', '60');
          const to = Number(toStr);
          if (Number.isFinite(to)) socket.emit('seek', { roomId, to });
        }}>Seek</button>
      </div>
    ) : <div className="badge">Waiting for host controls…</div>
  ), [isHost, roomId]);

  const handleRequestAction = (action, req) => {
    if (action === 'reject') {
      setRequests(prev => prev.filter(r => r.requestId !== req.requestId));
      return;
    }
    if (!req.preview) return;
    const track = req.preview;
    socket.emit('song_request_action', { roomId, action: action === 'accept' ? 'accept' : 'queue', track });
    setRequests(prev => prev.filter(r => r.requestId !== req.requestId));
  };

  return (
    <div className="container">
      <div className="row">
        <div className="col" style={{ minWidth: 320 }}>
          <div className="player">
            <div className="player-header">
              <div style={{ display:'flex', alignItems:'center', gap:10 }}>
                <div className="badge">{partyName}</div>
                <div className="tag">{isHost ? 'Host' : 'Guest'}</div>
              </div>
              {Controls}
            </div>
            <div className="player-body">
              <Player socket={socket} roomId={roomId} state={state} isHost={isHost} />
            </div>
          </div>

          <div className="panel" style={{ marginTop: 12 }}>
            <div className="section-title">Chat</div>
            <Chat socket={socket} roomId={roomId} name={name} isHost={isHost} members={members} />
          </div>

          <RequestsPanel isHost={isHost} requests={requests} onAct={handleRequestAction} />
        </div>

        <div className="col" style={{ flex:'0 0 340px' }}>
          <div className="panel">
            <div className="section-title">Members</div>
            <MemberList members={members} />
          </div>

          <div className="panel" style={{ marginTop: 12 }}>
            <div className="section-title">Queue</div>
            {state.queue?.length ? (
              <div style={{ display:'grid', gap:8 }}>
                {state.queue.map((t, i) => (
                  <div key={i} className="room-card" style={{ display:'flex', alignItems:'center', gap:10 }}>
                    <div className="thumb" style={{ width:40, height:40, backgroundImage: t.thumb ? `url("${t.thumb}")` : undefined }} />
                    <div style={{ fontWeight:700, overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>{t.title || t.url}</div>
                  </div>
                ))}
              </div>
            ) : <div style={{ color:'var(--muted)' }}>No songs in queue</div>}
          </div>
        </div>
      </div>

      <DirectLinkModal open={showDirect} onClose={() => setShowDirect(false)} onPick={pickDirectUrl} />
      <YouTubeModal open={showYT} onClose={() => setShowYT(false)} onPick={onPickYouTube} ytError={ytError} />
    </div>
  );
}
