import { useState, useEffect, useRef, useCallback } from 'react';
import Globe from 'globe.gl';

// ── Types ──
interface RadioPlace {
  id: string;
  geo: [number, number];
  title: string;
  country: string;
  size: number;
}

interface RadioChannel {
  id: string;
  title: string;
}

interface NowPlaying {
  stationId: string;
  stationName: string;
  placeName: string;
  country: string;
  startedAt: string;
  channelName: string;
}

interface GuildInfo {
  id: string;
  name: string;
  voiceChannels: { id: string; name: string; members: number }[];
}

interface SearchHit {
  id: string;
  type: string;
  title: string;
  subtitle: string;
  url: string;
}

interface Favorite {
  stationId: string;
  stationName: string;
  placeName: string;
  country: string;
  placeId: string;
}

// ── Component ──
export default function RadioTab({ data }: { data: any }) {
  const containerRef = useRef<HTMLDivElement>(null);
  const globeRef = useRef<any>(null);

  const [places, setPlaces] = useState<RadioPlace[]>([]);
  const [selectedPlace, setSelectedPlace] = useState<RadioPlace | null>(null);
  const [stations, setStations] = useState<RadioChannel[]>([]);
  const [stationsLoading, setStationsLoading] = useState(false);
  const [nowPlaying, setNowPlaying] = useState<Record<string, NowPlaying>>({});
  const [guilds, setGuilds] = useState<GuildInfo[]>([]);
  const [selectedGuild, setSelectedGuild] = useState('');
  const [selectedChannel, setSelectedChannel] = useState('');
  const [searchQuery, setSearchQuery] = useState('');
  const [searchResults, setSearchResults] = useState<SearchHit[]>([]);
  const [searchOpen, setSearchOpen] = useState(false);
  const [favorites, setFavorites] = useState<Favorite[]>([]);
  const [showFavorites, setShowFavorites] = useState(false);
  const [playingLoading, setPlayingLoading] = useState(false);
  const searchTimeout = useRef<ReturnType<typeof setTimeout>>();

  // ── Fetch initial data ──
  useEffect(() => {
    fetch('/api/radio/places').then(r => r.json()).then(setPlaces).catch(console.error);

    fetch('/api/radio/guilds')
      .then(r => r.json())
      .then((g: GuildInfo[]) => {
        setGuilds(g);
        if (g.length > 0) {
          setSelectedGuild(g[0].id);
          const ch = g[0].voiceChannels.find(c => c.members > 0) ?? g[0].voiceChannels[0];
          if (ch) setSelectedChannel(ch.id);
        }
      })
      .catch(console.error);

    fetch('/api/radio/favorites').then(r => r.json()).then(setFavorites).catch(console.error);
  }, []);

  // ── Handle SSE data ──
  useEffect(() => {
    if (data?.playing) setNowPlaying(data.playing);
    if (data?.favorites) setFavorites(data.favorites);
  }, [data]);

  // ── Point click handler (stable ref) ──
  const handlePointClickRef = useRef<(point: any) => void>();
  handlePointClickRef.current = (point: any) => {
    setSelectedPlace(point);
    setShowFavorites(false);
    setStationsLoading(true);
    setStations([]);
    if (globeRef.current) {
      globeRef.current.pointOfView({ lat: point.geo[0], lng: point.geo[1], altitude: 0.4 }, 800);
    }
    fetch(`/api/radio/place/${point.id}/channels`)
      .then(r => r.json())
      .then((ch: RadioChannel[]) => { setStations(ch); setStationsLoading(false); })
      .catch(() => setStationsLoading(false));
  };

  // ── Initialize globe ──
  useEffect(() => {
    if (!containerRef.current || places.length === 0) return;

    if (globeRef.current) {
      globeRef.current.pointsData(places);
      return;
    }

    const globe = Globe()(containerRef.current)
      .globeImageUrl('//unpkg.com/three-globe/example/img/earth-night.jpg')
      .backgroundColor('rgba(0,0,0,0)')
      .atmosphereColor('rgba(230, 126, 34, 0.25)')
      .atmosphereAltitude(0.12)
      .pointsData(places)
      .pointLat((d: any) => d.geo[0])
      .pointLng((d: any) => d.geo[1])
      .pointColor(() => 'rgba(230, 126, 34, 0.85)')
      .pointRadius((d: any) => Math.max(0.12, Math.min(0.45, 0.06 + (d.size ?? 1) * 0.005)))
      .pointAltitude(0.003)
      .pointLabel((d: any) =>
        `<div style="font-family:system-ui;font-size:13px;color:#fff;background:rgba(30,31,34,0.92);padding:6px 10px;border-radius:6px;border:1px solid rgba(230,126,34,0.3);pointer-events:none">` +
        `<b>${d.title}</b><br/><span style="color:#949ba4;font-size:11px">${d.country}</span></div>`
      )
      .onPointClick((d: any) => handlePointClickRef.current?.(d))
      .width(containerRef.current.clientWidth)
      .height(containerRef.current.clientHeight);

    // Start-Position: Europa
    globe.pointOfView({ lat: 48, lng: 10, altitude: 2.0 });

    // Auto-Rotation
    const controls = globe.controls() as any;
    if (controls) {
      controls.autoRotate = true;
      controls.autoRotateSpeed = 0.3;
    }

    globeRef.current = globe;

    const onResize = () => {
      if (containerRef.current && globeRef.current) {
        globeRef.current
          .width(containerRef.current.clientWidth)
          .height(containerRef.current.clientHeight);
      }
    };
    window.addEventListener('resize', onResize);

    return () => {
      window.removeEventListener('resize', onResize);
    };
  }, [places]);

  // ── Play handler ──
  const handlePlay = useCallback(async (
    stationId: string, stationName: string,
    overridePlaceName?: string, overrideCountry?: string,
  ) => {
    if (!selectedGuild || !selectedChannel) return;
    setPlayingLoading(true);
    try {
      const res = await fetch('/api/radio/play', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          guildId: selectedGuild,
          voiceChannelId: selectedChannel,
          stationId,
          stationName,
          placeName: overridePlaceName ?? selectedPlace?.title ?? '',
          country: overrideCountry ?? selectedPlace?.country ?? '',
        }),
      });
      const result = await res.json();
      if (result.ok) {
        setNowPlaying(prev => ({
          ...prev,
          [selectedGuild]: {
            stationId, stationName,
            placeName: overridePlaceName ?? selectedPlace?.title ?? '',
            country: overrideCountry ?? selectedPlace?.country ?? '',
            startedAt: new Date().toISOString(),
            channelName: guilds.find(g => g.id === selectedGuild)
              ?.voiceChannels.find(c => c.id === selectedChannel)?.name ?? '',
          },
        }));
        // Stoppe Auto-Rotation beim Abspielen
        const controls = globeRef.current?.controls() as any;
        if (controls) controls.autoRotate = false;
      }
    } catch (e) { console.error(e); }
    setPlayingLoading(false);
  }, [selectedGuild, selectedChannel, selectedPlace, guilds]);

  // ── Stop handler ──
  const handleStop = useCallback(async () => {
    if (!selectedGuild) return;
    await fetch('/api/radio/stop', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ guildId: selectedGuild }),
    });
    setNowPlaying(prev => {
      const next = { ...prev };
      delete next[selectedGuild];
      return next;
    });
  }, [selectedGuild]);

  // ── Search handler ──
  const handleSearch = useCallback((q: string) => {
    setSearchQuery(q);
    if (searchTimeout.current) clearTimeout(searchTimeout.current);
    if (!q.trim()) { setSearchResults([]); setSearchOpen(false); return; }
    searchTimeout.current = setTimeout(async () => {
      try {
        const res = await fetch(`/api/radio/search?q=${encodeURIComponent(q)}`);
        const results: SearchHit[] = await res.json();
        setSearchResults(results);
        setSearchOpen(true);
      } catch { setSearchResults([]); }
    }, 350);
  }, []);

  // ── Search result click ──
  const handleSearchResultClick = useCallback((hit: SearchHit) => {
    setSearchOpen(false);
    setSearchQuery('');
    setSearchResults([]);

    if (hit.type === 'channel') {
      const channelId = hit.url.match(/\/listen\/([^/]+)/)?.[1];
      if (channelId) {
        handlePlay(channelId, hit.title, hit.subtitle, '');
      }
    } else if (hit.type === 'place') {
      const placeId = hit.url.match(/\/visit\/[^/]+\/([^/]+)/)?.[1];
      const place = places.find(p => p.id === placeId);
      if (place) handlePointClickRef.current?.(place);
    }
  }, [places, handlePlay]);

  // ── Favorite toggle ──
  const toggleFavorite = useCallback(async (stationId: string, stationName: string) => {
    try {
      const res = await fetch('/api/radio/favorites', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          stationId, stationName,
          placeName: selectedPlace?.title ?? '',
          country: selectedPlace?.country ?? '',
          placeId: selectedPlace?.id ?? '',
        }),
      });
      const result = await res.json();
      if (result.favorites) setFavorites(result.favorites);
    } catch {}
  }, [selectedPlace]);

  const isFavorite = (stationId: string) => favorites.some(f => f.stationId === stationId);
  const currentPlaying = selectedGuild ? nowPlaying[selectedGuild] : null;
  const currentGuild = guilds.find(g => g.id === selectedGuild);

  return (
    <div className="radio-container">

      {/* ── Globe ── */}
      <div className="radio-globe" ref={containerRef} />

      {/* ── Search ── */}
      <div className="radio-search">
        <div className="radio-search-wrap">
          <span className="radio-search-icon">{'\u{1F50D}'}</span>
          <input
            className="radio-search-input"
            type="text"
            placeholder="Sender oder Stadt suchen..."
            value={searchQuery}
            onChange={e => handleSearch(e.target.value)}
            onFocus={() => { if (searchResults.length) setSearchOpen(true); }}
          />
          {searchQuery && (
            <button className="radio-search-clear" onClick={() => { setSearchQuery(''); setSearchResults([]); setSearchOpen(false); }}>{'\u2715'}</button>
          )}
        </div>
        {searchOpen && searchResults.length > 0 && (
          <div className="radio-search-results">
            {searchResults.slice(0, 12).map(hit => (
              <button key={hit.id + hit.url} className="radio-search-result" onClick={() => handleSearchResultClick(hit)}>
                <span className="radio-search-result-icon">
                  {hit.type === 'channel' ? '\u{1F4FB}' : hit.type === 'place' ? '\u{1F4CD}' : '\u{1F30D}'}
                </span>
                <div className="radio-search-result-text">
                  <span className="radio-search-result-title">{hit.title}</span>
                  <span className="radio-search-result-sub">{hit.subtitle}</span>
                </div>
              </button>
            ))}
          </div>
        )}
      </div>

      {/* ── Favorites toggle ── */}
      <button
        className={`radio-fab ${showFavorites ? 'active' : ''}`}
        onClick={() => { setShowFavorites(!showFavorites); if (!showFavorites) setSelectedPlace(null); }}
        title="Favoriten"
      >
        {'\u2B50'}{favorites.length > 0 && <span className="radio-fab-badge">{favorites.length}</span>}
      </button>

      {/* ── Side Panel: Favorites ── */}
      {showFavorites && (
        <div className="radio-panel open">
          <div className="radio-panel-header">
            <h3>{'\u2B50'} Favoriten</h3>
            <button className="radio-panel-close" onClick={() => setShowFavorites(false)}>{'\u2715'}</button>
          </div>
          <div className="radio-panel-body">
            {favorites.length === 0 ? (
              <div className="radio-panel-empty">Noch keine Favoriten</div>
            ) : (
              favorites.map(fav => (
                <div key={fav.stationId} className={`radio-station ${currentPlaying?.stationId === fav.stationId ? 'playing' : ''}`}>
                  <div className="radio-station-info">
                    <span className="radio-station-name">{fav.stationName}</span>
                    <span className="radio-station-loc">{fav.placeName}, {fav.country}</span>
                  </div>
                  <div className="radio-station-btns">
                    <button
                      className="radio-btn-play"
                      onClick={() => handlePlay(fav.stationId, fav.stationName, fav.placeName, fav.country)}
                      disabled={!selectedChannel || playingLoading}
                    >{'\u25B6'}</button>
                    <button className="radio-btn-fav active" onClick={() => toggleFavorite(fav.stationId, fav.stationName)}>{'\u2605'}</button>
                  </div>
                </div>
              ))
            )}
          </div>
        </div>
      )}

      {/* ── Side Panel: Stations at place ── */}
      {selectedPlace && !showFavorites && (
        <div className="radio-panel open">
          <div className="radio-panel-header">
            <div>
              <h3>{selectedPlace.title}</h3>
              <span className="radio-panel-sub">{selectedPlace.country}</span>
            </div>
            <button className="radio-panel-close" onClick={() => setSelectedPlace(null)}>{'\u2715'}</button>
          </div>
          <div className="radio-panel-body">
            {stationsLoading ? (
              <div className="radio-panel-loading">
                <div className="radio-spinner" />
                Sender werden geladen...
              </div>
            ) : stations.length === 0 ? (
              <div className="radio-panel-empty">Keine Sender gefunden</div>
            ) : (
              stations.map(s => (
                <div key={s.id} className={`radio-station ${currentPlaying?.stationId === s.id ? 'playing' : ''}`}>
                  <div className="radio-station-info">
                    <span className="radio-station-name">{s.title}</span>
                    {currentPlaying?.stationId === s.id && (
                      <span className="radio-station-live">
                        <span className="radio-eq"><span /><span /><span /></span>
                        Live
                      </span>
                    )}
                  </div>
                  <div className="radio-station-btns">
                    {currentPlaying?.stationId === s.id ? (
                      <button className="radio-btn-stop" onClick={handleStop}>{'\u23F9'}</button>
                    ) : (
                      <button
                        className="radio-btn-play"
                        onClick={() => handlePlay(s.id, s.title)}
                        disabled={!selectedChannel || playingLoading}
                      >{'\u25B6'}</button>
                    )}
                    <button
                      className={`radio-btn-fav ${isFavorite(s.id) ? 'active' : ''}`}
                      onClick={() => toggleFavorite(s.id, s.title)}
                    >{isFavorite(s.id) ? '\u2605' : '\u2606'}</button>
                  </div>
                </div>
              ))
            )}
          </div>
        </div>
      )}

      {/* ── Bottom Bar ── */}
      <div className={`radio-bar ${currentPlaying ? 'has-playing' : ''}`}>
        <div className="radio-bar-channel">
          {guilds.length > 1 && (
            <select className="radio-sel" value={selectedGuild} onChange={e => {
              setSelectedGuild(e.target.value);
              const g = guilds.find(x => x.id === e.target.value);
              const ch = g?.voiceChannels.find(c => c.members > 0) ?? g?.voiceChannels[0];
              setSelectedChannel(ch?.id ?? '');
            }}>
              {guilds.map(g => <option key={g.id} value={g.id}>{g.name}</option>)}
            </select>
          )}
          <select className="radio-sel" value={selectedChannel} onChange={e => setSelectedChannel(e.target.value)}>
            <option value="">Voice Channel...</option>
            {currentGuild?.voiceChannels.map(c => (
              <option key={c.id} value={c.id}>{'\u{1F50A}'} {c.name}{c.members > 0 ? ` (${c.members})` : ''}</option>
            ))}
          </select>
        </div>

        {currentPlaying && (
          <div className="radio-np">
            <div className="radio-eq radio-eq-np"><span /><span /><span /></div>
            <div className="radio-np-info">
              <span className="radio-np-name">{currentPlaying.stationName}</span>
              <span className="radio-np-loc">{currentPlaying.placeName}{currentPlaying.country ? `, ${currentPlaying.country}` : ''}</span>
            </div>
            <span className="radio-np-ch">{'\u{1F50A}'} {currentPlaying.channelName}</span>
            <button className="radio-btn-stop" onClick={handleStop}>{'\u23F9'} Stop</button>
          </div>
        )}
      </div>

      {/* ── Places counter ── */}
      <div className="radio-counter">
        {'\u{1F4FB}'} {places.length.toLocaleString('de-DE')} Sender weltweit
      </div>
    </div>
  );
}
