import { useEffect, useState } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import { getArtist, getArtistInfo, getTopSongs, getSimilarSongs2, getAlbum, search, SubsonicArtist, SubsonicAlbum, SubsonicSong, SubsonicArtistInfo, buildCoverArtUrl, coverArtCacheKey, star, unstar } from '../api/subsonic';
import AlbumCard from '../components/AlbumCard';
import CachedImage from '../components/CachedImage';
import CoverLightbox from '../components/CoverLightbox';
import { ArrowLeft, Users, ExternalLink, Heart, Play, Shuffle, Radio, HardDriveDownload, Check } from 'lucide-react';
import { open } from '@tauri-apps/plugin-shell';
import { usePlayerStore, songToTrack } from '../store/playerStore';
import { useOfflineStore } from '../store/offlineStore';
import { useAuthStore } from '../store/authStore';
import { useTranslation } from 'react-i18next';
import { lastfmGetSimilarArtists, lastfmIsConfigured } from '../api/lastfm';
import LastfmIcon from '../components/LastfmIcon';

function formatDuration(seconds: number): string {
  const m = Math.floor(seconds / 60);
  const s = seconds % 60;
  return `${m}:${s.toString().padStart(2, '0')}`;
}

/** Strip dangerous tags/attributes from server-provided HTML */
function sanitizeHtml(html: string): string {
  const parser = new DOMParser();
  const doc = parser.parseFromString(html, 'text/html');
  doc.querySelectorAll('script, style, iframe, object, embed, form, input, button, select, base, meta, link').forEach(el => el.remove());
  doc.querySelectorAll('*').forEach(el => {
    Array.from(el.attributes).forEach(attr => {
      const name = attr.name.toLowerCase();
      const val = attr.value.toLowerCase().trim();
      if (name.startsWith('on') || (name === 'href' && (val.startsWith('javascript:') || val.startsWith('data:'))) || (name === 'src' && (val.startsWith('javascript:') || val.startsWith('data:')))) {
        el.removeAttribute(attr.name);
      }
    });
  });
  return doc.body.innerHTML;
}


export default function ArtistDetail() {
  const { t } = useTranslation();
  const { id } = useParams<{ id: string }>();
  const navigate = useNavigate();
  const [artist, setArtist] = useState<SubsonicArtist | null>(null);
  const [albums, setAlbums] = useState<SubsonicAlbum[]>([]);
  const [featuredAlbums, setFeaturedAlbums] = useState<SubsonicAlbum[]>([]);
  const [topSongs, setTopSongs] = useState<SubsonicSong[]>([]);
  const [info, setInfo] = useState<SubsonicArtistInfo | null>(null);
  const [loading, setLoading] = useState(true);
  const [radioLoading, setRadioLoading] = useState(false);
  const [playAllLoading, setPlayAllLoading] = useState(false);
  const [isStarred, setIsStarred] = useState(false);
  const [openedLink, setOpenedLink] = useState<string | null>(null);
  const [similarArtists, setSimilarArtists] = useState<SubsonicArtist[]>([]);
  const [similarLoading, setSimilarLoading] = useState(false);
  const [featuredLoading, setFeaturedLoading] = useState(false);
  const [lightboxOpen, setLightboxOpen] = useState(false);

  const playTrack = usePlayerStore(state => state.playTrack);
  const enqueue = usePlayerStore(state => state.enqueue);
  const clearQueue = usePlayerStore(state => state.clearQueue);
  const openContextMenu = usePlayerStore(state => state.openContextMenu);
  const currentTrack = usePlayerStore(state => state.currentTrack);
  const isPlaying = usePlayerStore(state => state.isPlaying);
  const { downloadArtist, bulkProgress } = useOfflineStore();
  const activeServerId = useAuthStore(s => s.activeServerId) ?? '';

  useEffect(() => {
    if (!id) return;
    setLoading(true);
    setFeaturedAlbums([]);
    getArtist(id).then(artistData => {
      setArtist(artistData.artist);
      setAlbums(artistData.albums);
      setIsStarred(!!artistData.artist.starred);
      return Promise.all([
        getArtistInfo(id).catch(() => null),
        getTopSongs(artistData.artist.name).catch(() => []),
      ]);
    }).then(([artistInfo, songsData]) => {
      if (artistInfo !== undefined) setInfo(artistInfo as SubsonicArtistInfo | null);
      if (songsData !== undefined) setTopSongs(songsData as SubsonicSong[]);
      setLoading(false);
    }).catch(err => {
      console.error(err);
      setLoading(false);
    });
  }, [id]);

  // "Also Featured On" — loaded in background after main content renders
  useEffect(() => {
    if (!id || !artist) return;
    const ownAlbumIds = new Set(albums.map(a => a.id));
    setFeaturedLoading(true);
    search(artist.name, { songCount: 500, artistCount: 0, albumCount: 0 })
      .catch(() => ({ songs: [], albums: [], artists: [] }))
      .then(searchResults => {
        const featuredSongs = (searchResults.songs ?? []).filter(
          song => song.artistId === id && !ownAlbumIds.has(song.albumId)
        );
        const albumMap = new Map<string, SubsonicAlbum>();
        featuredSongs.forEach(song => {
          if (!albumMap.has(song.albumId)) {
            albumMap.set(song.albumId, {
              id: song.albumId,
              name: song.album,
              artist: song.albumArtist ?? '',
              artistId: '',
              coverArt: song.coverArt,
              songCount: 1,
              duration: song.duration,
              year: song.year,
            });
          } else {
            const a = albumMap.get(song.albumId)!;
            a.songCount++;
            a.duration += song.duration;
          }
        });
        setFeaturedAlbums([...albumMap.values()]);
        setFeaturedLoading(false);
      });
  }, [artist?.id]);

  useEffect(() => {
    if (!artist || !lastfmIsConfigured()) return;
    setSimilarArtists([]);
    setSimilarLoading(true);
    lastfmGetSimilarArtists(artist.name).then(async names => {
      if (names.length === 0) { setSimilarLoading(false); return; }
      const results = await Promise.all(
        names.slice(0, 30).map(name =>
          search(name, { artistCount: 3, albumCount: 0, songCount: 0 }).catch(() => ({ artists: [], albums: [], songs: [] }))
        )
      );
      const seen = new Set<string>([artist.id]);
      const found: SubsonicArtist[] = [];
      for (let i = 0; i < results.length; i++) {
        const targetName = names[i].toLowerCase();
        const match = results[i].artists.find(a => a.name.toLowerCase() === targetName);
        if (match && !seen.has(match.id)) {
          seen.add(match.id);
          found.push(match);
        }
      }
      setSimilarArtists(found);
      setSimilarLoading(false);
    }).catch(() => setSimilarLoading(false));
  }, [artist?.id]);

  const openLink = (url: string, key: string) => {
    open(url);
    setOpenedLink(key);
    setTimeout(() => setOpenedLink(null), 2500);
  };

  const toggleStar = async () => {
    if (!artist) return;
    const currentlyStarred = isStarred;
    setIsStarred(!currentlyStarred);
    try {
      if (currentlyStarred) await unstar(artist.id, 'artist');
      else await star(artist.id, 'artist');
    } catch (e) {
      console.error('Failed to toggle star', e);
      setIsStarred(currentlyStarred);
    }
  };

  const fetchAllTracks = async () => {
    const results = await Promise.all(albums.map(a => getAlbum(a.id)));
    const sorted = [...results].sort((a, b) => (a.album.year ?? 0) - (b.album.year ?? 0));
    return sorted.flatMap(r => [...r.songs].sort((a, b) => (a.track ?? 0) - (b.track ?? 0))).map(songToTrack);
  };

  const handlePlayAll = async () => {
    if (albums.length === 0) return;
    setPlayAllLoading(true);
    try {
      const tracks = await fetchAllTracks();
      if (tracks.length > 0) playTrack(tracks[0], tracks);
    } finally {
      setPlayAllLoading(false);
    }
  };

  const handleShuffle = async () => {
    if (albums.length === 0) return;
    setPlayAllLoading(true);
    try {
      const tracks = await fetchAllTracks();
      if (tracks.length > 0) {
        const shuffled = [...tracks].sort(() => Math.random() - 0.5);
        playTrack(shuffled[0], shuffled);
      }
    } finally {
      setPlayAllLoading(false);
    }
  };

  const handleStartRadio = async () => {
    if (!artist) return;
    setRadioLoading(true);
    try {
      // Fire both fetches in parallel
      const topPromise = getTopSongs(artist.name);
      const similarPromise = getSimilarSongs2(artist.id, 50);

      // Start playing as soon as top songs arrive
      const top = await topPromise;
      if (top.length > 0) {
        const firstTrack = songToTrack(top[0]);
        playTrack(firstTrack, [firstTrack]);
        setRadioLoading(false);
        // Enqueue remaining tracks when similar songs arrive
        const similar = await similarPromise;
        const remaining = [...top.slice(1), ...similar].map(songToTrack);
        if (remaining.length > 0) enqueue(remaining);
      } else {
        // No top songs — fall back to similar
        const similar = await similarPromise;
        if (similar.length > 0) {
          const tracks = similar.map(songToTrack);
          playTrack(tracks[0], tracks);
        } else {
          alert(t('artistDetail.noRadio'));
        }
        setRadioLoading(false);
      }
    } catch (e) {
      console.error('Radio start failed', e);
      setRadioLoading(false);
    }
  };

  if (loading) {
    return (
      <div className="content-body" style={{ display: 'flex', justifyContent: 'center', padding: '4rem' }}>
        <div className="spinner" />
      </div>
    );
  }

  if (!artist) {
    return (
      <div className="content-body">
        <div style={{ textAlign: 'center', padding: '4rem', color: 'var(--text-muted)' }}>
          {t('artistDetail.notFound')}
        </div>
      </div>
    );
  }

  const coverId = artist.coverArt || artist.id;
  const wikiUrl = `https://en.wikipedia.org/wiki/${encodeURIComponent(artist.name)}`;

  return (
    <div className="content-body animate-fade-in">
      <button
        className="btn btn-ghost"
        onClick={() => navigate(-1)}
        style={{ marginBottom: '1.5rem', display: 'flex', alignItems: 'center', gap: '0.5rem' }}
      >
        <ArrowLeft size={16} /> <span>{t('artistDetail.back')}</span>
      </button>

      {lightboxOpen && (
        <CoverLightbox
          src={buildCoverArtUrl(coverId, 2000)}
          alt={artist.name}
          onClose={() => setLightboxOpen(false)}
        />
      )}

      <div className="artist-detail-header">
        <div className="artist-detail-avatar">
          {coverId ? (
            <button
              className="artist-detail-avatar-btn"
              onClick={() => setLightboxOpen(true)}
              aria-label={`${artist.name} Bild vergrößern`}
            >
              <CachedImage
                src={buildCoverArtUrl(coverId, 300)}
                cacheKey={coverArtCacheKey(coverId, 300)}
                alt={artist.name}
                style={{ width: '100%', height: '100%', objectFit: 'cover' }}
                onError={e => { (e.currentTarget as HTMLImageElement).style.display = 'none'; }}
              />
            </button>
          ) : (
            <Users size={64} color="var(--text-muted)" />
          )}
        </div>

        <div className="artist-detail-meta">
          <h1 className="page-title" style={{ fontSize: '3rem', marginBottom: '0.25rem' }}>
            {artist.name}
          </h1>
          <div style={{ color: 'var(--text-secondary)', fontSize: '1rem', marginBottom: '1rem' }}>
            {t('artistDetail.albumCount_other', { count: artist.albumCount ?? 0 })}
          </div>

          <div style={{ display: 'flex', gap: '8px', flexWrap: 'wrap' }}>
            {(info?.lastFmUrl || artist.name) && (
              <div className="artist-detail-links">
                {info?.lastFmUrl && (
                  <button className="artist-ext-link" onClick={() => openLink(info.lastFmUrl!, 'lastfm')}>
                    <LastfmIcon size={14} />
                    {openedLink === 'lastfm' ? t('artistDetail.openedInBrowser') : 'Last.fm'}
                  </button>
                )}
                <button className="artist-ext-link" onClick={() => openLink(wikiUrl, 'wiki')}>
                  <ExternalLink size={14} />
                  {openedLink === 'wiki' ? t('artistDetail.openedInBrowser') : 'Wikipedia'}
                </button>
              </div>
            )}

            <button
              className="artist-ext-link"
              onClick={toggleStar}
              data-tooltip={isStarred ? t('artistDetail.favoriteRemove') : t('artistDetail.favoriteAdd')}
              style={{ color: isStarred ? 'var(--accent)' : 'inherit', border: isStarred ? '1px solid var(--accent)' : undefined }}
            >
              <Heart size={14} fill={isStarred ? "currentColor" : "none"} />
              {t('artistDetail.favorite')}
            </button>
          </div>

          <div style={{ display: 'flex', gap: '8px', marginTop: '1.5rem', flexWrap: 'wrap' }}>
            {albums.length > 0 && (
              <>
                <button className="btn btn-primary" onClick={handlePlayAll} disabled={playAllLoading}>
                  {playAllLoading ? <div className="spinner" style={{ width: 16, height: 16, borderTopColor: 'currentColor' }} /> : <Play size={16} />}
                  {t('artistDetail.playAll')}
                </button>
                <button className="btn btn-surface" onClick={handleShuffle} disabled={playAllLoading}>
                  {playAllLoading ? <div className="spinner" style={{ width: 16, height: 16, borderTopColor: 'currentColor' }} /> : <Shuffle size={16} />}
                  {t('artistDetail.shuffle')}
                </button>
              </>
            )}
            <button className="btn btn-surface" onClick={handleStartRadio} disabled={radioLoading}>
              {radioLoading ? <div className="spinner" style={{ width: 16, height: 16, borderTopColor: 'currentColor' }} /> : <Radio size={16} />}
              {radioLoading ? t('artistDetail.loading') : t('artistDetail.radio')}
            </button>
            {albums.length > 0 && (() => {
              const progress = id ? bulkProgress[id] : undefined;
              const isDone = progress && progress.done === progress.total;
              const isDownloading = progress && !isDone;
              return (
                <button
                  className="btn btn-surface"
                  disabled={!!isDownloading}
                  onClick={() => { if (id && artist) downloadArtist(id, artist.name, activeServerId); }}
                  data-tooltip={isDownloading
                    ? t('artistDetail.offlineDownloading', { done: progress.done, total: progress.total })
                    : isDone ? t('artistDetail.offlineCached') : t('artistDetail.cacheOffline')}
                >
                  {isDownloading
                    ? <div className="spinner" style={{ width: 16, height: 16, borderTopColor: 'currentColor' }} />
                    : isDone ? <Check size={16} /> : <HardDriveDownload size={16} />}
                  {isDownloading
                    ? t('artistDetail.offlineDownloading', { done: progress.done, total: progress.total })
                    : isDone ? t('artistDetail.offlineCached') : t('artistDetail.cacheOffline')}
                </button>
              );
            })()}
          </div>
        </div>
      </div>

      {/* Biography — sanitized HTML from server */}
      {info?.biography && (
        <div className="artist-bio-section">
          <div
            className="artist-bio-text"
            dangerouslySetInnerHTML={{ __html: sanitizeHtml(info.biography) }}
          />
        </div>
      )}

      {/* Top Songs */}
      {topSongs.length > 0 && (
        <>
          <h2 className="section-title" style={{ marginTop: info?.biography ? '2rem' : '0', marginBottom: '1rem' }}>
            {t('artistDetail.topTracks')}
          </h2>
          <div className="tracklist" style={{ padding: 0, marginBottom: '2rem' }}>
            <div className="tracklist-header" style={{ gridTemplateColumns: '36px minmax(150px, 2fr) minmax(100px, 1fr) 60px' }}>
              <div style={{ textAlign: 'center' }}>#</div>
              <div>{t('artistDetail.trackTitle')}</div>
              <div>{t('artistDetail.trackAlbum')}</div>
              <div style={{ textAlign: 'right' }}>{t('artistDetail.trackDuration')}</div>
            </div>
             {topSongs.map((song, idx) => {
                   const track = songToTrack(song);
                   return (
                     <div
                       key={song.id}
                       className="track-row"
                       style={{ gridTemplateColumns: '36px minmax(150px, 2fr) minmax(100px, 1fr) 60px' }}
                       onClick={e => {
                         if ((e.target as HTMLElement).closest('button, a, input')) return;
                         playTrack(track, topSongs.map(songToTrack));
                       }}
                       onContextMenu={(e) => {
                         e.preventDefault();
                         openContextMenu(e.clientX, e.clientY, track, 'song');
                       }}
                     >
                <div className={`track-num${currentTrack?.id === song.id ? ' track-num-active' : ''}`} style={{ cursor: 'pointer' }} onClick={e => { e.stopPropagation(); playTrack(track, topSongs.map(songToTrack)); }}>
                  {currentTrack?.id === song.id && isPlaying && <span className="track-num-eq"><div className="eq-bars"><span className="eq-bar" /><span className="eq-bar" /><span className="eq-bar" /></div></span>}
                  <span className="track-num-play"><Play size={13} fill="currentColor" /></span>
                  <span className="track-num-number">{idx + 1}</span>
                </div>
                <div className="track-info" style={{ display: 'flex', alignItems: 'center', gap: '1rem' }}>
                  {song.coverArt && (
                    <CachedImage
                      src={buildCoverArtUrl(song.coverArt, 64)}
                      cacheKey={coverArtCacheKey(song.coverArt, 64)}
                      alt={song.album}
                      style={{ width: '32px', height: '32px', borderRadius: '4px', objectFit: 'cover', flexShrink: 0 }}
                      onError={(e) => { (e.currentTarget as HTMLImageElement).style.display = 'none'; }}
                    />
                  )}
                  <div style={{ display: 'flex', flexDirection: 'column', minWidth: 0 }}>
                    <div className="track-title">{song.title}</div>
                  </div>
                </div>
                <div className="track-album truncate" style={{ color: 'var(--text-secondary)', fontSize: '12px' }}>
                  {song.album}
                </div>
                <div className="track-duration" style={{ textAlign: 'right' }}>
                {formatDuration(song.duration)}
                 </div>
               </div>
               );
             })}
           </div>
         </>
       )}

      {/* Similar Artists (Last.fm) */}
      {lastfmIsConfigured() && (similarLoading || similarArtists.length > 0) && (
        <>
          <h2 className="section-title" style={{ marginTop: '2rem', marginBottom: '1rem' }}>
            {t('artistDetail.similarArtists')}
          </h2>
          {similarLoading ? (
            <div style={{ display: 'flex', alignItems: 'center', gap: '0.75rem', color: 'var(--text-muted)', fontSize: '0.875rem' }}>
              <div className="spinner" style={{ width: 16, height: 16, borderTopColor: 'currentColor' }} />
              {t('artistDetail.loading')}
            </div>
          ) : (
            <div style={{ display: 'flex', flexWrap: 'wrap', gap: '0.5rem' }}>
              {similarArtists.map(a => (
                <button
                  key={a.id}
                  className="artist-ext-link"
                  onClick={() => navigate(`/artist/${a.id}`)}
                >
                  {a.name}
                </button>
              ))}
            </div>
          )}
        </>
      )}

      {/* Albums */}
      <h2 className="section-title" style={{ marginTop: (info?.biography || topSongs.length > 0 || lastfmIsConfigured()) ? '2rem' : '0', marginBottom: '1rem' }}>
        {t('artistDetail.albumsBy', { name: artist.name })}
      </h2>

      {albums.length > 0 ? (
        <div className="album-grid-wrap">
          {albums.map(a => <AlbumCard key={a.id} album={a} />)}
        </div>
      ) : (
        <p style={{ color: 'var(--text-muted)' }}>{t('artistDetail.noAlbums')}</p>
      )}

      {/* Also Featured On */}
      {(featuredLoading || featuredAlbums.length > 0) && (
        <>
          <h2 className="section-title" style={{ marginTop: '2rem', marginBottom: '1rem' }}>
            {t('artistDetail.featuredOn')}
          </h2>
          {featuredLoading ? (
            <div className="album-grid-wrap">
              {[...Array(4)].map((_, i) => (
                <div key={i} style={{ flex: '0 0 clamp(140px, 15vw, 180px)', borderRadius: '8px', background: 'var(--bg-card)', aspectRatio: '1', opacity: 0.5 }} />
              ))}
            </div>
          ) : (
            <div className="album-grid-wrap" style={{ animation: 'fadeIn 0.3s ease' }}>
              {featuredAlbums.map(a => <AlbumCard key={a.id} album={a} />)}
            </div>
          )}
        </>
      )}
    </div>
  );
}
