import type { BaseItemDto } from '../../api/types'
import MediaTechIcons from '../ui/MediaTechIcons'
import { RefreshCw, Loader2 } from '../../lib/icons'
import {
  pickPrimarySource,
  getAudioStreams,
  resolutionLabel,
  videoRangeLabel,
} from '../../lib/jellyfin-meta'

interface Props {
  techItem?: BaseItemDto | null
  tmdbVote?: number | null
  tmdbVoteCount?: number | null
  jellyfinCommunity?: number | null
  jellyfinCritic?: number | null
  /** IMDB rating from the Cinemeta keyless feed (string in the source). */
  imdbRating?: number | null
  showTmdbRatings?: boolean
  /** TV-show specific extras */
  seasonsCount?: number | null
  episodesCount?: number | null
  seriesStatus?: string | null
  /** Click handler for the "Rescan files" button shown when the
   *  techItem has a file but no probed streams. Omit to hide. */
  onRescan?: () => void
  isRescanning?: boolean
}

/**
 * Returns true when the techItem has at least one renderable media
 * detail. Mirrors the inner gate of MediaTechIcons so the parent can
 * decide whether to show the "Media" label at all rather than render
 * an empty section.
 */
function hasMediaSignal(item: BaseItemDto | null | undefined): boolean {
  if (!item) return false
  const source = pickPrimarySource(item)
  const audio = getAudioStreams(item)[0]
  const res = resolutionLabel(item)
  const range = videoRangeLabel(item)
  return !!(res || range || audio?.Codec || source?.Container)
}


/**
 * Right-side rail of the detail-page hero. Minimal, frameless. Tech icons
 * sit on top, then ratings, then at-a-glance stats - separated by hairline
 * dividers rather than card chrome.
 */
export default function HeroTechCard({
  techItem,
  tmdbVote,
  tmdbVoteCount,
  jellyfinCommunity,
  jellyfinCritic,
  imdbRating,
  showTmdbRatings = true,
  seasonsCount,
  episodesCount,
  seriesStatus,
  onRescan,
  isRescanning,
}: Props) {
  const showIcons = hasMediaSignal(techItem)
  // Rescan is a passive offer whenever a refresh handler is available -
  // not only when probe data is missing. Users want a way to re-probe
  // even when SOMETHING is shown, because the sample might be from one
  // good episode while others in the series are still missing data.
  const showRescan = !!onRescan
  const isProbeMissing = !showIcons
  const showMediaSection = showIcons || showRescan
  const showTmdb = showTmdbRatings && tmdbVote != null && tmdbVote > 0
  const showJfCommunity = jellyfinCommunity != null && jellyfinCommunity > 0
  const showCritic = jellyfinCritic != null && jellyfinCritic > 0
  const showImdb = imdbRating != null && imdbRating > 0
  const showRatings = showTmdb || showJfCommunity || showCritic || showImdb
  const showStats = seasonsCount != null || episodesCount != null || seriesStatus

  if (!showMediaSection && !showRatings && !showStats) return null

  return (
    <aside className="hidden lg:flex flex-col gap-5 w-[260px] shrink-0 self-end pb-1">
      {showMediaSection && (
        <div>
          <div className="flex items-center justify-between gap-2 mb-2.5">
            <Label>Media</Label>
            {showRescan && (
              <button
                onClick={onRescan}
                disabled={isRescanning}
                title={isProbeMissing
                  ? 'Stream info missing - click to ask Jellyfin to re-probe the file'
                  : 'Ask Jellyfin to re-probe the file (refreshes stream info)'}
                aria-label="Rescan media files"
                className="inline-flex items-center justify-center w-6 h-6 rounded text-text-3 hover:text-accent hover:bg-elevated/60 transition-colors duration-150 focus-ring disabled:opacity-60 disabled:cursor-progress"
              >
                {isRescanning ? (
                  <Loader2 size={12} className="animate-spin" />
                ) : (
                  <RefreshCw size={11} stroke={2} />
                )}
              </button>
            )}
          </div>
          {showIcons ? (
            <MediaTechIcons item={techItem} className="!gap-2" />
          ) : (
            <button
              onClick={onRescan}
              disabled={isRescanning}
              className="inline-flex items-center gap-1.5 h-8 px-3 rounded-md text-[11.5px] font-medium bg-elevated/60 text-text-2 border border-border hover:border-border-hover hover:text-text-1 transition-colors duration-150 focus-ring disabled:opacity-60 disabled:cursor-progress"
            >
              {isRescanning ? (
                <>
                  <Loader2 size={12} className="animate-spin" />
                  Rescanning...
                </>
              ) : (
                <>
                  <RefreshCw size={12} stroke={2} />
                  Rescan files
                </>
              )}
            </button>
          )}
          {!showIcons && (
            <p className="text-[10.5px] text-text-4 mt-2 leading-snug">
              Stream info missing. Click to ask Jellyfin to re-probe the file.
            </p>
          )}
        </div>
      )}

      {showMediaSection && (showRatings || showStats) && <Divider />}

      {showRatings && (
        <div className="space-y-1.5">
          <Label>Ratings</Label>
          {showTmdb && (
            <RatingRow
              source="TMDB"
              tone="amber"
              value={tmdbVote!.toFixed(1)}
              meta={tmdbVoteCount ? `${formatVotes(tmdbVoteCount)} votes` : undefined}
              tooltip="The Movie Database community score"
            />
          )}
          {showImdb && (
            <RatingRow
              source="IMDB"
              tone="yellow"
              value={imdbRating!.toFixed(1)}
              tooltip="IMDB rating (via Cinemeta)"
            />
          )}
          {showJfCommunity && (
            <RatingRow
              source="Jellyfin"
              tone="cool"
              value={jellyfinCommunity!.toFixed(1)}
              tooltip="Jellyfin community average"
            />
          )}
          {showCritic && (
            <RatingRow
              source="Critics"
              tone="emerald"
              value={`${Math.round(jellyfinCritic!)}%`}
              tooltip="Aggregate critic score"
            />
          )}
        </div>
      )}

      {showRatings && showStats && <Divider />}

      {showStats && (
        <div>
          <Label>At a glance</Label>
          <dl className="grid grid-cols-3 gap-x-4 gap-y-3 mt-2">
            {seasonsCount != null && <Stat label="Seasons" value={seasonsCount} />}
            {episodesCount != null && <Stat label="Episodes" value={episodesCount} />}
            {seriesStatus && (
              <Stat
                label="Status"
                value={seriesStatus === 'Returning Series' ? 'Airing' : seriesStatus}
                tone={
                  seriesStatus === 'Returning Series' ? 'success'
                  : seriesStatus === 'Canceled' ? 'error'
                  : 'default'
                }
              />
            )}
          </dl>
        </div>
      )}
    </aside>
  )
}

function Label({ children }: { children: React.ReactNode }) {
  return (
    <p className="text-[10px] uppercase tracking-[0.18em] font-semibold text-text-3 mb-2.5 leading-none">
      {children}
    </p>
  )
}

function Divider() {
  return <span className="h-px bg-border" />
}

function RatingRow({
  source,
  tone,
  value,
  meta,
  tooltip,
}: {
  source: string
  tone: 'amber' | 'cool' | 'emerald' | 'yellow'
  value: string
  meta?: string
  tooltip: string
}) {
  const dotCls =
    tone === 'amber' ? 'bg-accent'
    : tone === 'cool' ? 'bg-cool'
    : tone === 'yellow' ? 'bg-yellow-400'
    : 'bg-emerald-400'
  const valCls =
    tone === 'amber' ? 'text-accent'
    : tone === 'cool' ? 'text-cool'
    : tone === 'yellow' ? 'text-yellow-300'
    : 'text-emerald-300'

  return (
    <div className="flex items-baseline gap-2.5" title={tooltip}>
      <span className={`w-1.5 h-1.5 rounded-full self-center shrink-0 ${dotCls}`} />
      <span className="text-[12.5px] text-text-2 font-medium">{source}</span>
      {meta && <span className="text-[10.5px] text-text-4 truncate">{meta}</span>}
      <span className={`ml-auto text-[18px] font-bold tabular-nums tracking-tight font-display ${valCls}`}>
        {value}
      </span>
    </div>
  )
}

function Stat({
  label,
  value,
  tone = 'default',
}: {
  label: string
  value: string | number
  tone?: 'default' | 'success' | 'error'
}) {
  const valCls =
    tone === 'success' ? 'text-success'
    : tone === 'error' ? 'text-error'
    : 'text-text-1'
  return (
    <div className="min-w-0">
      <p className="text-[9.5px] uppercase tracking-[0.14em] font-semibold text-text-3 mb-0.5 leading-none truncate">
        {label}
      </p>
      <p className={`text-[18px] font-bold tabular-nums tracking-tight font-display truncate ${valCls}`}>
        {value}
      </p>
    </div>
  )
}

function formatVotes(n: number): string {
  if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`
  if (n >= 1_000) return `${(n / 1_000).toFixed(n >= 10_000 ? 0 : 1)}k`
  return n.toString()
}
