import { Row } from '@olly/modern-sk';
import { useTranslation } from 'react-i18next';
import { TrackContextMenu } from './TrackContextMenu';
import { AvailabilityBadge } from './AvailabilityBadge';
import { MetadataStatusBadge } from './MetadataStatusBadge';
import { Icon } from '../common/Icon';
import { PlayingIndicator } from '../common/PlayingIndicator';
import { formatDuration } from '../../lib/format';
import { useAppDispatch, useAppSelector } from '../../hooks/useAppDispatch';
import { useIsOffline } from '../../hooks/useConnectionStatus';
import { useStreamCached } from '../../hooks/useStreamCached';
import { playNow } from '../../store/slices/queue';
import type { Track } from '../../api/types';
import { getCoverUrl, getTrackCoverUrl } from '../../api/endpoints/streaming';

interface Props {
  track: Track;
  index?: number;
  showAlbum?: boolean;
  /** Hide cover art and show the track's album position instead — used on
   * the album detail page, where the album cover is already shown once in
   * the header and per-track art would be redundant. */
  hideArt?: boolean;
  onAddToPlaylist?: (track: Track) => void;
  onEditMetadata?: (track: Track) => void;
  onDelete?: (track: Track) => void;
}

export function TrackRow({
  track,
  index,
  showAlbum = false,
  hideArt = false,
  onAddToPlaylist,
  onEditMetadata,
  onDelete,
}: Props) {
  const { t } = useTranslation();
  const dispatch = useAppDispatch();
  const currentTrackId = useAppSelector((s) => s.player.currentTrackId);
  const isPlaying = useAppSelector((s) => s.player.isPlaying);
  const token = useAppSelector((s) => s.auth.accessToken);
  const isActive = currentTrackId === track.id;
  // Prefer an explicit album art URL; otherwise serve the track's own cover
  // (needs the token in the query string — `<img>` can't send a header).
  const artUrl =
    getCoverUrl(track.albumArtUrl) ??
    (token ? getTrackCoverUrl(track.id, token, track.hasCover) : undefined);

  // The backend reports `server`, but if it's unreachable and this track's
  // audio is already in the offline cache, show "Local" instead.
  const offline = useIsOffline();
  const cached = useStreamCached(offline ? track.id : undefined);
  const displayAvailability =
    track.availability === 'server' && offline && cached
      ? 'local'
      : track.availability;

  const handlePlayNow = () => {
    dispatch(
      playNow({
        trackId: track.id,
        title: track.title,
        artistName: track.artistName,
        albumTitle: track.albumTitle,
        durationMs: track.durationMs,
        albumArtUrl: track.albumArtUrl,
      }),
    );
  };

  return (
    <Row
      selected={isActive}
      style={{
        display: 'grid',
        gridTemplateColumns: hideArt
          ? '2.5rem 1fr auto auto'
          : '2rem 2.5rem 1fr auto auto',
        gap: '0.75rem',
        alignItems: 'center',
        padding: '0.375rem 0.75rem',
        cursor: 'default',
      }}
    >
      {!hideArt && (
        <span
          style={{
            fontSize: '0.75rem',
            color: 'var(--color-text-3)',
            textAlign: 'right',
          }}
        >
          {isActive && isPlaying ? '▶' : index !== undefined ? index + 1 : ''}
        </span>
      )}
      <div className="track-art">
        {hideArt ? (
          <div
            style={{
              width: 36,
              height: 36,
              display: 'flex',
              alignItems: 'center',
              justifyContent: 'center',
              fontSize: '1.0625rem',
              fontWeight: 600,
              color: isActive ? 'var(--color-accent)' : 'var(--color-text-3)',
            }}
          >
            {track.trackNumber ?? (index !== undefined ? index + 1 : '')}
          </div>
        ) : artUrl ? (
          <img
            src={artUrl}
            alt=""
            width={36}
            height={36}
            style={{ borderRadius: 4, objectFit: 'cover' }}
          />
        ) : (
          <div
            style={{
              width: 36,
              height: 36,
              borderRadius: 4,
              background: 'var(--color-surface-3)',
            }}
          />
        )}
        {isActive && (
          <div className="cover-playing">
            <PlayingIndicator animate={isPlaying} />
          </div>
        )}
        <button
          type="button"
          className="track-art-play"
          onClick={handlePlayNow}
          aria-label={t('track.menu.playNow')}
          title={t('track.menu.playNow')}
        >
          <Icon name="play" fill />
        </button>
      </div>
      <div style={{ minWidth: 0 }}>
        <div
          style={{
            fontWeight: isActive ? 600 : 400,
            color: isActive ? 'var(--color-accent)' : 'var(--color-text-1)',
            overflow: 'hidden',
            textOverflow: 'ellipsis',
            whiteSpace: 'nowrap',
          }}
        >
          {track.title}
        </div>
        <div
          style={{
            fontSize: '0.8125rem',
            color: 'var(--color-text-2)',
            overflow: 'hidden',
            textOverflow: 'ellipsis',
            whiteSpace: 'nowrap',
          }}
        >
          {track.artistName}
          {showAlbum && ` · ${track.albumTitle}`}
        </div>
      </div>
      <div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
        <MetadataStatusBadge
          status={track.metadataStatus}
          error={track.metadataError}
          iconOnly
        />
        <AvailabilityBadge availability={displayAvailability} iconOnly />
      </div>
      <div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
        <span
          style={{
            fontSize: '0.8125rem',
            color: 'var(--color-text-3)',
            minWidth: '3rem',
            textAlign: 'right',
          }}
        >
          {formatDuration(track.durationMs)}
        </span>
        <TrackContextMenu
          track={track}
          onAddToPlaylist={onAddToPlaylist}
          onEditMetadata={onEditMetadata}
          onDelete={onDelete}
        />
      </div>
    </Row>
  );
}
