import type { ReactNode } from 'react';
import { Badge, Button } from '@olly/modern-sk';
import { useTranslation } from 'react-i18next';
import { Link, useNavigate } from 'react-router';
import { skipToken } from '@reduxjs/toolkit/query';
import { Icon } from '../common/Icon';
import { ArtTile } from '../common/ArtTile';
import { AvailabilityBadge } from './AvailabilityBadge';
import { MetadataStatusBadge } from './MetadataStatusBadge';
import { LoadingSkeleton } from '../common/LoadingSkeleton';
import { ErrorState } from '../common/ErrorState';
import { EmptyState } from '../common/EmptyState';
import { useAppDispatch, useAppSelector } from '../../hooks/useAppDispatch';
import { closeTrackInfo } from '../../store/slices/ui';
import { play } from '../../store/slices/player';
import { addToQueue } from '../../store/slices/queue';
import {
  useGetTrackQuery,
  useGetAlbumQuery,
} from '../../api/endpoints/library';
import { getTrackCoverUrl } from '../../api/endpoints/streaming';
import {
  formatDuration,
  formatFileSize,
  formatDateTime,
} from '../../lib/format';
import type { Track } from '../../api/types';

/**
 * Right-side "Get Info"-style drawer for a single track. Rendered after the
 * QueuePanel in AppShell so it sits to the *right* of the queue when both are
 * open. Open state lives in `ui.trackInfoId`; it reads the live Track (and its
 * album) from the RTKQ cache so enrichment updates stay in sync.
 */
export function TrackInfoDrawer() {
  const trackId = useAppSelector((s) => s.ui.trackInfoId);
  const isOpen = trackId !== null;

  return (
    <aside className={`tid${isOpen ? '' : ' closed'}`} aria-hidden={!isOpen}>
      <div className="tid-inner">
        {trackId ? <TrackInfoContent trackId={trackId} /> : null}
      </div>
    </aside>
  );
}

function TrackInfoContent({ trackId }: { trackId: string }) {
  const { t } = useTranslation();
  const dispatch = useAppDispatch();
  const navigate = useNavigate();
  const token = useAppSelector((s) => s.auth.accessToken);

  const {
    data: track,
    isLoading,
    isError,
    refetch,
  } = useGetTrackQuery(trackId);
  // Album record fills in fields the lean TrackOut omits (year especially).
  const { data: album } = useGetAlbumQuery(track?.albumId ?? skipToken);

  const close = () => dispatch(closeTrackInfo());

  return (
    <>
      <div className="tid-head">
        <h3>{t('trackInfo.title')}</h3>
        <div style={{ flex: 1 }} />
        <button
          type="button"
          className="iconbtn sm"
          onClick={close}
          title={t('trackInfo.close')}
        >
          <Icon name="x" />
        </button>
      </div>

      <div className="tid-scroll">
        {isLoading ? (
          <LoadingSkeleton rows={6} />
        ) : isError ? (
          <ErrorState onRetry={refetch} />
        ) : !track ? (
          <EmptyState title={t('trackInfo.notFound')} />
        ) : (
          <TrackInfoBody
            track={track}
            albumYear={album?.year}
            albumTrackCount={album?.trackCount}
            coverUrl={
              token
                ? getTrackCoverUrl(track.id, token, track.hasCover)
                : undefined
            }
            onPlay={() => dispatch(play(track.id))}
            onQueue={() =>
              dispatch(
                addToQueue({
                  trackId: track.id,
                  title: track.title,
                  artistName: track.artistName,
                  albumTitle: track.albumTitle,
                  durationMs: track.durationMs,
                  albumArtUrl: track.albumArtUrl,
                }),
              )
            }
            onEdit={() => {
              navigate(`/tracks/${track.id}/metadata`);
            }}
          />
        )}
      </div>
    </>
  );
}

function TrackInfoBody({
  track,
  albumYear,
  albumTrackCount,
  coverUrl,
  onPlay,
  onQueue,
  onEdit,
}: {
  track: Track;
  albumYear?: number;
  albumTrackCount?: number;
  coverUrl?: string;
  onPlay: () => void;
  onQueue: () => void;
  onEdit: () => void;
}) {
  const { t } = useTranslation();
  const seedLabel = track.albumTitle || track.title;
  const year = track.year ?? albumYear;

  return (
    <>
      <div className="tid-cover">
        {coverUrl ? (
          <img src={coverUrl} alt={track.albumTitle} />
        ) : (
          <ArtTile seed={seedLabel} size={256} label={seedLabel} radius={12} />
        )}
      </div>

      <h2 className="tid-title">{track.title}</h2>
      <Link className="tid-sub" to={`/artists/${track.artistId}`}>
        {track.artistName}
      </Link>
      {track.albumId && (
        <Link className="tid-sub tid-album" to={`/albums/${track.albumId}`}>
          <Icon name="vinyl-record" />
          {track.albumTitle}
        </Link>
      )}

      <div className="tid-actions">
        <Button variant="primary" size="sm" onClick={onPlay}>
          <Icon name="play" fill /> {t('trackInfo.play')}
        </Button>
        <Button variant="ghost" size="sm" onClick={onQueue}>
          <Icon name="queue" /> {t('trackInfo.addToQueue')}
        </Button>
        <Button variant="ghost" size="sm" onClick={onEdit}>
          {t('trackInfo.editMetadata')}
        </Button>
      </div>

      <InfoSection title={t('trackInfo.sections.status')}>
        <div className="tid-status">
          <AvailabilityBadge availability={track.availability} />
          <MetadataStatusBadge
            status={track.metadataStatus}
            error={track.metadataError}
            hideWhenEnriched={false}
          />
          {track.liked && (
            <Badge variant="lime" dot>
              {t('trackInfo.liked')}
            </Badge>
          )}
        </div>
        {track.metadataStatus === 'failed' && track.metadataError && (
          <p className="tid-error">{track.metadataError}</p>
        )}
      </InfoSection>

      <InfoSection title={t('trackInfo.sections.general')}>
        <InfoRow
          label={t('trackInfo.fields.artist')}
          value={track.artistName}
        />
        <InfoRow
          label={t('trackInfo.fields.album')}
          value={track.albumTitle || undefined}
        />
        <InfoRow
          label={t('trackInfo.fields.trackNumber')}
          value={
            track.trackNumber !== undefined
              ? albumTrackCount
                ? t('trackInfo.trackOf', {
                    n: track.trackNumber,
                    total: albumTrackCount,
                  })
                : String(track.trackNumber)
              : undefined
          }
        />
        <InfoRow
          label={t('trackInfo.fields.disc')}
          value={
            track.discNumber !== undefined
              ? String(track.discNumber)
              : undefined
          }
        />
        <InfoRow
          label={t('trackInfo.fields.year')}
          value={year !== undefined ? String(year) : undefined}
        />
        <InfoRow label={t('trackInfo.fields.genre')} value={track.genre} />
        <InfoRow
          label={t('trackInfo.fields.duration')}
          value={formatDuration(track.durationMs)}
        />
      </InfoSection>

      <InfoSection title={t('trackInfo.sections.file')}>
        <InfoRow
          label={t('trackInfo.fields.format')}
          value={track.format?.toUpperCase()}
        />
        <InfoRow
          label={t('trackInfo.fields.bitrate')}
          value={
            track.bitrate !== undefined
              ? t('trackInfo.kbps', { n: track.bitrate })
              : undefined
          }
        />
        <InfoRow
          label={t('trackInfo.fields.size')}
          value={
            track.fileSize !== undefined
              ? formatFileSize(track.fileSize)
              : undefined
          }
        />
        <InfoRow
          label={t('trackInfo.fields.source')}
          value={track.source}
          mono
        />
        <InfoRow
          label={t('trackInfo.fields.added')}
          value={formatDateTime(track.createdAt)}
        />
        <InfoRow
          label={t('trackInfo.fields.enriched')}
          value={formatDateTime(track.enrichedAt)}
        />
      </InfoSection>

      <InfoSection title={t('trackInfo.sections.identifiers')}>
        <InfoRow label={t('trackInfo.fields.trackId')} value={track.id} mono />
        <InfoRow
          label={t('trackInfo.fields.albumId')}
          value={track.albumId || undefined}
          mono
        />
        <InfoRow
          label={t('trackInfo.fields.artistId')}
          value={track.artistId}
          mono
        />
      </InfoSection>
    </>
  );
}

function InfoSection({
  title,
  children,
}: {
  title: string;
  children: ReactNode;
}) {
  return (
    <section className="tid-section">
      <span className="msk-label tid-section-label">{title}</span>
      {children}
    </section>
  );
}

/** A label/value row; renders nothing when the value is empty (Finder-style). */
function InfoRow({
  label,
  value,
  mono,
}: {
  label: string;
  value?: string;
  mono?: boolean;
}) {
  if (!value) return null;
  return (
    <div className="tid-row">
      <span className="tid-row-k">{label}</span>
      <span className={`tid-row-v${mono ? ' mono' : ''}`}>{value}</span>
    </div>
  );
}
