import { useCallback, useEffect, useRef, useState, type ReactNode } from 'react';
import { ArrowLeft, ChevronLeft, ChevronRight, Info, ScanSearch, Stethoscope, TriangleAlert } from 'lucide-react';
import { Button, Card, Dialog, IconButton, Spinner, Tag } from '../components';
import {
  ApiError,
  getArtist,
  getLibraryBrowseItems,
  getMediaItemInfo,
  getMovie,
  getSeason,
  getShow,
  messageFromLibraryBrowseError,
  messageFromMediaDetailError,
  scanShow,
  type ArtistDetail,
  type LibraryBrowseItem,
  type LibraryBrowseMediaType,
  type MediaItemInfo,
  type MovieDetail,
  type SeasonDetail,
  type ShowDetail
} from '../api';
import { AddToMenu } from '../media/addTo';
import { MediaPosterCard } from '../media/MediaPosterCard';
import { mediaDetailPath, parseDurationSeconds } from '../media/mediaKinds';
import { navigateToPath } from '../routing';

const CHILD_PAGE_SIZE = 60;

// Media source kinds whose libraries support the single-show rescan endpoint.
const REMOTE_SOURCE_KINDS = new Set(['Plex', 'Jellyfin', 'Emby']);

// Builds a minimal LibraryBrowseItem for a detail page's own subject so it can feed the shared
// Add-to menu/dialogs, which only read id/mediaType/title off each item (see toAddItemsRequest /
// AddToScheduleDialog). The remaining fields are inert here.
function detailBrowseItem(mediaType: LibraryBrowseMediaType, id: number, title: string): LibraryBrowseItem {
  return { artwork: '', id, mediaType, title } as unknown as LibraryBrowseItem;
}

function troubleshootPath(mediaItemId: number): string {
  return `/app/troubleshooting/playback?mediaItem=${mediaItemId}`;
}

type DetailState<T> =
  | { status: 'loading' }
  | { status: 'notfound' }
  | { status: 'error'; error: string }
  | { status: 'success'; data: T };

function useDetail<T>(load: () => Promise<T>): DetailState<T> {
  const [state, setState] = useState<DetailState<T>>({ status: 'loading' });
  const activeRef = useRef(true);

  useEffect(() => {
    activeRef.current = true;
    load()
      .then((data) => {
        if (activeRef.current) {
          setState({ data, status: 'success' });
        }
      })
      .catch((error: unknown) => {
        if (!activeRef.current) {
          return;
        }
        if (error instanceof ApiError && error.status === 404) {
          setState({ status: 'notfound' });
        } else {
          setState({ error: messageFromMediaDetailError(error), status: 'error' });
        }
      });
    return () => {
      activeRef.current = false;
    };
  }, [load]);

  return state;
}

function backToBrowse(kindSlug: string) {
  navigateToPath(`/app/media?kind=${kindSlug}`);
}

function ChipRow({ label, values }: { label: string; values: string[] | null | undefined }) {
  if (!values || values.length === 0) {
    return null;
  }
  return (
    <div className="ctv-detail-chiprow">
      <span className="ctv-detail-chiplabel">{label}</span>
      <div className="ctv-detail-chips">
        {values.map((value) => (
          <Tag key={`${label}-${value}`}>{value}</Tag>
        ))}
      </div>
    </div>
  );
}

function ActorsRow({ actors }: { actors: MovieDetail['actors'] }) {
  if (!actors || actors.length === 0) {
    return null;
  }
  return (
    <div className="ctv-detail-section">
      <h3 className="ctv-detail-heading">Cast</h3>
      <div className="ctv-detail-actors">
        {actors.map((actor) => (
          <div className="ctv-detail-actor" key={actor.id}>
            {actor.thumb ? (
              <img alt="" className="ctv-detail-actor-thumb" loading="lazy" src={actor.thumb} />
            ) : (
              <div className="ctv-detail-actor-thumb ctv-detail-actor-thumb-empty" />
            )}
            <div className="ctv-detail-actor-name" title={actor.name}>
              {actor.name}
            </div>
            {actor.role ? (
              <div className="ctv-detail-actor-role" title={actor.role}>
                {actor.role}
              </div>
            ) : null}
          </div>
        ))}
      </div>
    </div>
  );
}

function DetailShell({
  fanart,
  poster,
  title,
  subtitle,
  plot,
  warning,
  actions,
  chips,
  children
}: {
  fanart?: string | null;
  poster?: string | null;
  title: string;
  subtitle?: string | null;
  plot?: string | null;
  warning?: ReactNode;
  actions?: ReactNode;
  chips?: ReactNode;
  children?: ReactNode;
}) {
  return (
    <div className="ctv-detail">
      {fanart ? (
        <div className="ctv-detail-fanart" style={{ backgroundImage: `url(${JSON.stringify(fanart)})` }} />
      ) : null}
      <div className="ctv-detail-head">
        {poster ? (
          <img alt="" className="ctv-detail-poster" src={poster} />
        ) : (
          <div className="ctv-detail-poster ctv-detail-poster-empty" />
        )}
        <div className="ctv-detail-headinfo">
          <h2 className="ctv-detail-title">{title}</h2>
          {subtitle ? <div className="ctv-detail-subtitle">{subtitle}</div> : null}
          {plot ? <p className="ctv-detail-plot">{plot}</p> : null}
          {warning}
          {actions ? <div className="ctv-detail-actions">{actions}</div> : null}
        </div>
      </div>
      {chips ? <Card>{chips}</Card> : null}
      {children}
    </div>
  );
}

function StateWarning({ state, path }: { state: string | null | undefined; path?: string | null }) {
  if (state === 'FileNotFound') {
    return (
      <div className="ctv-channels-error" role="alert">
        <TriangleAlert aria-hidden="true" size={15} />
        <span>File not found{path ? `: ${path}` : ''}</span>
      </div>
    );
  }
  if (state === 'Unavailable') {
    return (
      <div className="ctv-channels-error" role="alert">
        <TriangleAlert aria-hidden="true" size={15} />
        <span>Unavailable{path ? `: ${path}` : ''}</span>
      </div>
    );
  }
  return null;
}

// A paged grid of a parent's children (seasons of a show, episodes of a season, an artist's music
// videos) fetched via the browse parentId drill-in.
function ChildGrid({
  heading,
  mediaType,
  parentId,
  renderActions
}: {
  heading: string;
  mediaType: LibraryBrowseMediaType;
  parentId: number;
  renderActions?: (item: LibraryBrowseItem) => ReactNode;
}) {
  const [items, setItems] = useState<LibraryBrowseItem[]>([]);
  const [totalCount, setTotalCount] = useState(0);
  const [pageNum, setPageNum] = useState(0);
  const [status, setStatus] = useState<'loading' | 'error' | 'success'>('loading');
  const [error, setError] = useState<string | null>(null);
  const [anchorId, setAnchorId] = useState<string | null>(() => window.location.hash.slice(1) || null);
  const activeRef = useRef(true);
  const seqRef = useRef(0);
  // The anchor value we last actually scrolled to, so a refetch/pagination that recreates
  // `items` (but leaves the hash unchanged) doesn't hijack the user's scroll position.
  const scrolledAnchorRef = useRef<string | null>(null);

  useEffect(() => {
    activeRef.current = true;
    return () => {
      activeRef.current = false;
    };
  }, []);

  // Deep-link support (#220): a season detail's episode grid can be opened with an
  // `#episode-{id}` hash (from search/browse cards, or Blazor-parity links). The SPA's own
  // in-app navigation (routing.ts navigateToPath) uses `history.pushState` + a synthetic
  // `popstate` dispatch rather than a real hash change — real browser hash navigation
  // (address bar, back/forward across a hash-only change) fires `hashchange` instead — so both
  // events must be handled to catch in-grid episode card clicks (same season pathname, new
  // fragment) as well as deep links that remount this screen.
  useEffect(() => {
    const onHashNav = () => setAnchorId(window.location.hash.slice(1) || null);
    window.addEventListener('hashchange', onHashNav);
    window.addEventListener('popstate', onHashNav);
    return () => {
      window.removeEventListener('hashchange', onHashNav);
      window.removeEventListener('popstate', onHashNav);
    };
  }, []);

  useEffect(() => {
    if (status !== 'success' || mediaType !== 'Episode' || !anchorId) {
      return;
    }
    // One-shot per anchor value: only scroll the first time we see this anchor resolve
    // successfully, so a later refetch/pagination (which recreates `items`) doesn't re-jump the
    // page back to it. Known limitation shared with the Blazor fragment link this replaces: the
    // anchor only resolves against the currently-loaded page (CHILD_PAGE_SIZE) — a target beyond
    // page 1 won't be found (and so won't scroll) until that page is loaded.
    if (scrolledAnchorRef.current === anchorId) {
      return;
    }
    const target = document.getElementById(anchorId);
    if (!target) {
      return;
    }
    target.scrollIntoView({ behavior: 'smooth', block: 'center' });
    scrolledAnchorRef.current = anchorId;
  }, [status, mediaType, anchorId, items]);

  const load = useCallback(() => {
    const id = ++seqRef.current;
    getLibraryBrowseItems({ mediaType, pageNum, pageSize: CHILD_PAGE_SIZE, parentId })
      .then((paged) => {
        if (activeRef.current && id === seqRef.current) {
          setItems(paged.page ?? []);
          setTotalCount(paged.totalCount ?? 0);
          setStatus('success');
        }
      })
      .catch((caught: unknown) => {
        if (activeRef.current && id === seqRef.current) {
          setError(messageFromLibraryBrowseError(caught));
          setStatus('error');
        }
      });
  }, [mediaType, pageNum, parentId]);

  useEffect(() => {
    load();
  }, [load]);

  const totalPages = Math.max(1, Math.ceil(totalCount / CHILD_PAGE_SIZE));

  return (
    <div className="ctv-detail-section">
      <h3 className="ctv-detail-heading">{heading}</h3>
      {status === 'loading' ? (
        <div className="ctv-collections-loading" role="status">
          <Spinner size={18} />
          <span>Loading…</span>
        </div>
      ) : status === 'error' ? (
        <div className="ctv-channels-error" role="alert">
          <TriangleAlert aria-hidden="true" size={15} />
          <span>{error}</span>
          <span className="ctv-channels-spacer" />
          <Button
            onClick={() => {
              setStatus('loading');
              load();
            }}
            size="sm"
            variant="secondary"
          >
            Retry
          </Button>
        </div>
      ) : items.length === 0 ? (
        <Card>
          <div className="ctv-collections-empty">Nothing here yet.</div>
        </Card>
      ) : (
        <>
          <div className="ctv-media-grid">
            {items.map((item) => {
              const detailPath = mediaDetailPath(item);
              const cardId = item.mediaType === 'Episode' ? `episode-${item.id}` : undefined;
              return (
                <MediaPosterCard
                  actions={renderActions?.(item)}
                  highlighted={cardId != null && cardId === anchorId}
                  id={cardId}
                  item={item}
                  key={`${item.mediaType}-${item.id}`}
                  onOpen={detailPath ? () => navigateToPath(detailPath) : undefined}
                />
              );
            })}
          </div>
          {totalPages > 1 ? (
            <div className="ctv-channels-footer" style={{ marginTop: 'var(--space-6, 12px)' }}>
              <span>{totalCount}</span>
              <span className="ctv-channels-spacer" />
              <IconButton
                disabled={pageNum === 0}
                onClick={() => setPageNum((current) => Math.max(0, current - 1))}
                size="sm"
                title="Previous page"
              >
                <ChevronLeft aria-hidden="true" size={15} />
              </IconButton>
              <span>
                Page <code>{pageNum + 1}</code> of <code>{totalPages}</code>
              </span>
              <IconButton
                disabled={pageNum + 1 >= totalPages}
                onClick={() => setPageNum((current) => current + 1)}
                size="sm"
                title="Next page"
              >
                <ChevronRight aria-hidden="true" size={15} />
              </IconButton>
            </div>
          ) : null}
        </>
      )}
    </div>
  );
}

function formatTicks(value: string | null | undefined): string {
  const seconds = parseDurationSeconds(value);
  if (seconds == null) {
    return '—';
  }
  const whole = Math.floor(seconds);
  const hours = Math.floor(whole / 3600);
  const minutes = Math.floor((whole % 3600) / 60);
  const secs = whole % 60;
  const pad = (n: number) => String(n).padStart(2, '0');
  return hours > 0 ? `${hours}:${pad(minutes)}:${pad(secs)}` : `${minutes}:${pad(secs)}`;
}

// The technical media-info dialog (streams + chapters), backed by GET /api/v1/media-items/{id}/info.
// The fetching body is a separate component mounted only while the dialog is open, so its effect
// only ever calls setState asynchronously (no synchronous setState in an effect body).
export function MediaInfoDialog({
  mediaItemId,
  open,
  onClose
}: {
  mediaItemId: number;
  open: boolean;
  onClose: () => void;
}) {
  return (
    <Dialog onClose={onClose} open={open} title="Media Info" width={720}>
      {open ? <MediaInfoBody mediaItemId={mediaItemId} /> : null}
    </Dialog>
  );
}

function MediaInfoBody({ mediaItemId }: { mediaItemId: number }) {
  const [info, setInfo] = useState<MediaItemInfo | null>(null);
  const [status, setStatus] = useState<'loading' | 'error' | 'success'>('loading');
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    let active = true;
    getMediaItemInfo(mediaItemId)
      .then((result) => {
        if (active) {
          setInfo(result);
          setStatus('success');
        }
      })
      .catch((caught: unknown) => {
        if (active) {
          setError(messageFromMediaDetailError(caught, 'Unable to load media info'));
          setStatus('error');
        }
      });
    return () => {
      active = false;
    };
  }, [mediaItemId]);

  return (
    <>
      {status === 'loading' ? (
        <div className="ctv-collections-loading" role="status">
          <Spinner size={18} />
          <span>Loading media info…</span>
        </div>
      ) : status === 'error' ? (
        <div className="ctv-channels-error" role="alert">
          <TriangleAlert aria-hidden="true" size={15} />
          <span>{error}</span>
        </div>
      ) : info ? (
        <div className="ctv-detail-info">
          <dl className="ctv-detail-infogrid">
            <dt>Kind</dt>
            <dd>{info.kind}</dd>
            <dt>Library</dt>
            <dd>{info.libraryName}</dd>
            <dt>Duration</dt>
            <dd>{formatTicks(info.duration)}</dd>
            <dt>Resolution</dt>
            <dd>
              {info.width}×{info.height}
            </dd>
            {info.displayAspectRatio ? (
              <>
                <dt>Aspect Ratio</dt>
                <dd>{info.displayAspectRatio}</dd>
              </>
            ) : null}
          </dl>
          {info.streams && info.streams.length > 0 ? (
            <div className="ctv-detail-info-block">
              <h4 className="ctv-detail-heading">Streams</h4>
              <div className="ctv-channels-table-scroll">
                <table className="ctv-channels-table">
                  <thead>
                    <tr>
                      <th>#</th>
                      <th>Kind</th>
                      <th>Codec</th>
                      <th>Language</th>
                      <th>Title</th>
                    </tr>
                  </thead>
                  <tbody>
                    {info.streams.map((stream, index) => (
                      <tr key={`${stream.kind}-${stream.index ?? index}`}>
                        <td>{stream.index ?? '—'}</td>
                        <td>{stream.kind}</td>
                        <td>{stream.codec ?? '—'}</td>
                        <td>{stream.language ?? '—'}</td>
                        <td>{stream.title ?? '—'}</td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
            </div>
          ) : null}
          {info.chapters && info.chapters.length > 0 ? (
            <div className="ctv-detail-info-block">
              <h4 className="ctv-detail-heading">Chapters</h4>
              <div className="ctv-channels-table-scroll">
                <table className="ctv-channels-table">
                  <thead>
                    <tr>
                      <th>Title</th>
                      <th>Start</th>
                      <th>End</th>
                    </tr>
                  </thead>
                  <tbody>
                    {info.chapters.map((chapter, index) => (
                      <tr key={`chapter-${index}`}>
                        <td>{chapter.title || `Chapter ${index + 1}`}</td>
                        <td>{formatTicks(chapter.startTime)}</td>
                        <td>{formatTicks(chapter.endTime)}</td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
            </div>
          ) : null}
        </div>
      ) : null}
    </>
  );
}

function NotFound({ kindSlug, label }: { kindSlug: string; label: string }) {
  return (
    <div className="ctv-detail">
      <Button onClick={() => backToBrowse(kindSlug)} size="sm" startIcon={<ArrowLeft size={14} />} variant="ghost">
        Back
      </Button>
      <Card>
        <div className="ctv-collections-empty">{label} not found.</div>
      </Card>
    </div>
  );
}

function ErrorState({ message, kindSlug }: { message: string; kindSlug: string }) {
  return (
    <div className="ctv-detail">
      <Button onClick={() => backToBrowse(kindSlug)} size="sm" startIcon={<ArrowLeft size={14} />} variant="ghost">
        Back
      </Button>
      <div className="ctv-channels-error" role="alert">
        <TriangleAlert aria-hidden="true" size={15} />
        <span>{message}</span>
      </div>
    </div>
  );
}

function Loading() {
  return (
    <div className="ctv-collections-loading" role="status">
      <Spinner size={18} />
      <span>Loading…</span>
    </div>
  );
}

export function MovieDetailScreen({ id }: { id: number }) {
  const state = useDetail<MovieDetail>(useCallback(() => getMovie(id), [id]));
  const [infoOpen, setInfoOpen] = useState(false);

  if (state.status === 'loading') {
    return <Loading />;
  }
  if (state.status === 'notfound') {
    return <NotFound kindSlug="movies" label="Movie" />;
  }
  if (state.status === 'error') {
    return <ErrorState kindSlug="movies" message={state.error} />;
  }

  const movie = state.data;
  const displayPath = movie.state === 'FileNotFound' ? movie.path : movie.localPath || movie.path;

  return (
    <>
      <Button onClick={() => backToBrowse('movies')} size="sm" startIcon={<ArrowLeft size={14} />} variant="ghost">
        Back
      </Button>
      <DetailShell
        actions={
          <>
            <Button onClick={() => setInfoOpen(true)} size="sm" startIcon={<Info size={14} />} variant="secondary">
              Media Info
            </Button>
            <Button
              onClick={() => navigateToPath(troubleshootPath(id))}
              size="sm"
              startIcon={<Stethoscope size={14} />}
              variant="secondary"
            >
              Troubleshoot Playback
            </Button>
            <AddToMenu items={[detailBrowseItem('Movie', id, movie.title)]} />
          </>
        }
        chips={
          <div className="ctv-detail-chipstack">
            <ChipRow label="Genres" values={movie.genres} />
            <ChipRow label="Tags" values={movie.tags} />
            <ChipRow label="Studios" values={movie.studios} />
            <ChipRow label="Content Ratings" values={movie.contentRatings} />
            <ChipRow label="Languages" values={movie.languages} />
            <ChipRow label="Directors" values={movie.directors} />
            <ChipRow label="Writers" values={movie.writers} />
          </div>
        }
        fanart={movie.fanArt}
        plot={movie.plot}
        poster={movie.poster}
        subtitle={movie.year}
        title={movie.title}
        warning={<StateWarning path={displayPath} state={movie.state} />}
      >
        <ActorsRow actors={movie.actors} />
        {displayPath ? <div className="ctv-detail-path">{displayPath}</div> : null}
      </DetailShell>
      <MediaInfoDialog mediaItemId={id} onClose={() => setInfoOpen(false)} open={infoOpen} />
    </>
  );
}

function ShowScanControls({ show }: { show: ShowDetail }) {
  const [scanning, setScanning] = useState<false | 'quick' | 'deep'>(false);
  const [message, setMessage] = useState<{ kind: 'ok' | 'error'; text: string } | null>(null);
  const activeRef = useRef(true);

  useEffect(() => {
    activeRef.current = true;
    return () => {
      activeRef.current = false;
    };
  }, []);

  const runScan = (deepScan: boolean) => {
    setScanning(deepScan ? 'deep' : 'quick');
    setMessage(null);
    scanShow(show.libraryId, { deepScan, showId: show.id })
      .then(() => {
        if (activeRef.current) {
          setScanning(false);
          setMessage({ kind: 'ok', text: 'Scan queued' });
        }
      })
      .catch((error: unknown) => {
        if (activeRef.current) {
          setScanning(false);
          setMessage({ kind: 'error', text: messageFromMediaDetailError(error, 'Unable to queue scan') });
        }
      });
  };

  return (
    <>
      <Button
        disabled={scanning !== false}
        loading={scanning === 'quick'}
        onClick={() => runScan(false)}
        size="sm"
        startIcon={<ScanSearch size={14} />}
        variant="secondary"
      >
        Quick scan
      </Button>
      <Button
        disabled={scanning !== false}
        loading={scanning === 'deep'}
        onClick={() => runScan(true)}
        size="sm"
        startIcon={<ScanSearch size={14} />}
        variant="secondary"
      >
        Deep scan
      </Button>
      {message ? (
        <span className={message.kind === 'error' ? 'ctv-field-error' : 'ctv-channels-selected'} role={message.kind === 'error' ? 'alert' : 'status'}>
          {message.text}
        </span>
      ) : null}
    </>
  );
}

export function ShowDetailScreen({ id }: { id: number }) {
  const state = useDetail<ShowDetail>(useCallback(() => getShow(id), [id]));

  if (state.status === 'loading') {
    return <Loading />;
  }
  if (state.status === 'notfound') {
    return <NotFound kindSlug="shows" label="Show" />;
  }
  if (state.status === 'error') {
    return <ErrorState kindSlug="shows" message={state.error} />;
  }

  const show = state.data;
  const canScanShow = REMOTE_SOURCE_KINDS.has(show.mediaSourceKind);

  return (
    <>
      <Button onClick={() => backToBrowse('shows')} size="sm" startIcon={<ArrowLeft size={14} />} variant="ghost">
        Back
      </Button>
      <DetailShell
        actions={
          <>
            <AddToMenu items={[detailBrowseItem('TelevisionShow', id, show.title)]} />
            {canScanShow ? <ShowScanControls show={show} /> : null}
          </>
        }
        chips={
          <div className="ctv-detail-chipstack">
            <ChipRow label="Genres" values={show.genres} />
            <ChipRow label="Tags" values={show.tags} />
            <ChipRow label="Studios" values={show.studios} />
            <ChipRow label="Networks" values={show.networks} />
            <ChipRow label="Content Ratings" values={show.contentRatings} />
            <ChipRow label="Languages" values={show.languages} />
          </div>
        }
        fanart={show.fanArt}
        plot={show.plot}
        poster={show.poster}
        subtitle={show.year}
        title={show.title}
      >
        <ActorsRow actors={show.actors} />
        <ChildGrid
          heading="Seasons"
          mediaType="TelevisionSeason"
          parentId={id}
          renderActions={(item) => <AddToMenu compact items={[item]} />}
        />
      </DetailShell>
    </>
  );
}

export function SeasonDetailScreen({ id }: { id: number }) {
  const state = useDetail<SeasonDetail>(useCallback(() => getSeason(id), [id]));
  const [infoItemId, setInfoItemId] = useState<number | null>(null);

  if (state.status === 'loading') {
    return <Loading />;
  }
  if (state.status === 'notfound') {
    return <NotFound kindSlug="shows" label="Season" />;
  }
  if (state.status === 'error') {
    return <ErrorState kindSlug="shows" message={state.error} />;
  }

  const season = state.data;
  const seasonTitle = `${season.title} — ${season.name}`;

  return (
    <>
      <Button
        onClick={() => navigateToPath(`/app/media/shows/${season.showId}`)}
        size="sm"
        startIcon={<ArrowLeft size={14} />}
        variant="ghost"
      >
        Back to show
      </Button>
      <DetailShell
        actions={<AddToMenu items={[detailBrowseItem('TelevisionSeason', id, seasonTitle)]} />}
        fanart={season.fanArt}
        poster={season.poster}
        subtitle={season.year}
        title={seasonTitle}
      >
        <ChildGrid
          heading="Episodes"
          mediaType="Episode"
          parentId={id}
          renderActions={(item) => (
            <>
              <AddToMenu compact items={[item]} />
              <IconButton onClick={() => setInfoItemId(item.id)} size="sm" title="Media Info">
                <Info aria-hidden="true" size={14} />
              </IconButton>
              <IconButton onClick={() => navigateToPath(troubleshootPath(item.id))} size="sm" title="Troubleshoot Playback">
                <Stethoscope aria-hidden="true" size={14} />
              </IconButton>
            </>
          )}
        />
      </DetailShell>
      <MediaInfoDialog
        mediaItemId={infoItemId ?? 0}
        onClose={() => setInfoItemId(null)}
        open={infoItemId !== null}
      />
    </>
  );
}

export function ArtistDetailScreen({ id }: { id: number }) {
  const state = useDetail<ArtistDetail>(useCallback(() => getArtist(id), [id]));

  if (state.status === 'loading') {
    return <Loading />;
  }
  if (state.status === 'notfound') {
    return <NotFound kindSlug="artists" label="Artist" />;
  }
  if (state.status === 'error') {
    return <ErrorState kindSlug="artists" message={state.error} />;
  }

  const artist = state.data;

  return (
    <>
      <Button onClick={() => backToBrowse('artists')} size="sm" startIcon={<ArrowLeft size={14} />} variant="ghost">
        Back
      </Button>
      <DetailShell
        actions={<AddToMenu items={[detailBrowseItem('Artist', id, artist.name)]} />}
        chips={
          <div className="ctv-detail-chipstack">
            <ChipRow label="Genres" values={artist.genres} />
            <ChipRow label="Styles" values={artist.styles} />
            <ChipRow label="Moods" values={artist.moods} />
            <ChipRow label="Languages" values={artist.languages} />
          </div>
        }
        fanart={artist.fanArt}
        plot={artist.biography}
        poster={artist.thumbnail}
        subtitle={artist.disambiguation}
        title={artist.name}
      >
        <ChildGrid
          heading="Music Videos"
          mediaType="MusicVideo"
          parentId={id}
          renderActions={(item) => <AddToMenu compact items={[item]} />}
        />
      </DetailShell>
    </>
  );
}
