import { motion } from 'framer-motion'
import type { ButtonHTMLAttributes } from 'react'
import {
  ArrowLeft,
  AudioLines,
  Bookmark,
  Download,
  Info,
  List,
  ListDetails,
  Moon,
  PictureInPicture2,
  Search,
  Subtitles,
  Users,
} from '../../lib/icons'
import SpeedMenu from './SpeedMenu'
import QualityMenu, { type QualityOption } from './QualityMenu'
import TrackMenu from './TrackMenu'
import SubtitleStyleMenu from './SubtitleStyleMenu'
import PictureMenu from './PictureMenu'
import type { BaseItemDto } from '../../api/types'

interface TrackInfo {
  Index?: number
  Codec?: string | null
  Profile?: string | null
  Language?: string | null
  Title?: string | null
  Channels?: number | null
  ChannelLayout?: string | null
  IsDefault?: boolean | null
  IsForced?: boolean | null
  IsHearingImpaired?: boolean | null
  IsExternal?: boolean | null
  AudioSpatialFormat?: string | null
  Type?: string
}

interface Props {
  item: BaseItemDto | null | undefined
  playbackRate: number
  onPlaybackRateChange: (rate: number) => void
  qualityKey: string
  onQualitySelect: (q: QualityOption) => void
  onPictureInPicture: () => void
  audioTracks: TrackInfo[]
  audioIndex: number | null
  onAudioSelect: (i: number | null) => void
  subtitleTracks: TrackInfo[]
  subtitleIndex: number | null
  onSubtitleSelect: (i: number | null) => void
  hasSeries: boolean
  episodesOpen: boolean
  onToggleEpisodes: () => void
  hasChapters: boolean
  chaptersOpen: boolean
  onToggleChapters: () => void
  bookmarksOpen: boolean
  onToggleBookmarks: () => void
  subSearchOpen: boolean
  onToggleSubSearch: () => void
  syncPlayOpen: boolean
  onToggleSyncPlay: () => void
  syncPlayActive: boolean
  videoBrightness: number
  videoContrast: number
  videoSaturation: number
  onPictureChange: (key: 'brightness' | 'contrast' | 'saturation', value: number) => void
  onPictureReset: () => void
  streamInfoOpen: boolean
  onToggleStreamInfo: () => void
  onBack: () => void
  sleepRemainingSec?: number
  onDownload?: () => void
  isDownloaded?: boolean
}

export default function PlayerTopBar({
  item,
  playbackRate,
  onPlaybackRateChange,
  qualityKey,
  onQualitySelect,
  onPictureInPicture,
  audioTracks,
  audioIndex,
  onAudioSelect,
  subtitleTracks,
  subtitleIndex,
  onSubtitleSelect,
  hasSeries,
  episodesOpen,
  onToggleEpisodes,
  hasChapters,
  chaptersOpen,
  onToggleChapters,
  bookmarksOpen,
  onToggleBookmarks,
  subSearchOpen,
  onToggleSubSearch,
  syncPlayOpen,
  onToggleSyncPlay,
  syncPlayActive,
  videoBrightness,
  videoContrast,
  videoSaturation,
  onPictureChange,
  onPictureReset,
  streamInfoOpen,
  onToggleStreamInfo,
  onBack,
  sleepRemainingSec,
  onDownload,
  isDownloaded,
}: Props) {
  return (
    <motion.div
      initial={{ y: -10, opacity: 0 }}
      animate={{ y: 0, opacity: 1 }}
      exit={{ y: -10, opacity: 0 }}
      transition={{ duration: 0.25, ease: [0.16, 1, 0.3, 1] }}
      data-player-top-bar
      className="bg-gradient-to-b from-black/75 via-black/30 to-transparent pt-5 pb-12 px-7 flex items-start justify-between pointer-events-auto"
    >
      <button
        onClick={onBack}
        className="group flex items-center gap-3 text-white/85 hover:text-white transition-colors focus-ring rounded-md p-1 -m-1"
      >
        <span className="w-9 h-9 rounded-full bg-black/40 backdrop-blur grid place-items-center group-hover:bg-black/60 transition-colors">
          <ArrowLeft size={17} strokeWidth={2.25} />
        </span>
        <span className="hidden sm:flex flex-col items-start leading-tight">
          <span className="text-[10px] uppercase tracking-[0.14em] text-white/55 font-semibold">
            Now playing
          </span>
          <span className="text-[14px] font-medium tracking-tight">{item?.Name || 'Untitled'}</span>
        </span>
      </button>

      <div className="flex items-center gap-1.5">
        <SpeedMenu speed={playbackRate} onChange={onPlaybackRateChange} />
        <QualityMenu selectedKey={qualityKey} onSelect={onQualitySelect} />
        {onDownload && (
          <ChromeButton
            onClick={onDownload}
            aria-label={isDownloaded ? 'Downloaded' : 'Download'}
            title={isDownloaded ? 'Downloaded' : 'Download'}
            className={isDownloaded ? 'text-accent' : ''}
          >
            <Download size={16} />
          </ChromeButton>
        )}
        {sleepRemainingSec != null && sleepRemainingSec > 0 && (
          <span
            className="hidden sm:inline-flex items-center gap-1 h-7 px-2 rounded-full bg-black/40 backdrop-blur text-[10.5px] text-white/70 font-mono tabular-nums"
            title="Sleep timer active"
          >
            <Moon size={12} />
            {formatSleep(sleepRemainingSec)}
          </span>
        )}
        <ChromeButton onClick={onPictureInPicture} aria-label="Picture in picture">
          <PictureInPicture2 size={17} />
        </ChromeButton>
        <TrackMenu
          trigger={<AudioLines size={17} />}
          title="Audio"
          tracks={audioTracks}
          selectedIndex={audioIndex ?? (audioTracks.find(t => t.IsDefault)?.Index ?? null)}
          onSelect={onAudioSelect}
          variant="audio"
        />
        <TrackMenu
          trigger={<Subtitles size={17} />}
          title="Subtitles"
          tracks={subtitleTracks}
          selectedIndex={subtitleIndex}
          onSelect={onSubtitleSelect}
          variant="subtitle"
        />
        <SubtitleStyleMenu />
        {subtitleIndex != null && (
          <ChromeButton
            onClick={onToggleSubSearch}
            aria-label="Search subtitles"
            aria-pressed={subSearchOpen}
            className={subSearchOpen ? 'bg-white/15 text-white' : ''}
          >
            <Search size={17} />
          </ChromeButton>
        )}
        {hasSeries && (
          <ChromeButton
            onClick={onToggleEpisodes}
            aria-label="Episodes"
            aria-pressed={episodesOpen}
            className={episodesOpen ? 'bg-white/15 text-white' : ''}
          >
            <ListDetails size={17} />
          </ChromeButton>
        )}
        {hasChapters && (
          <ChromeButton
            onClick={onToggleChapters}
            aria-label="Chapters"
            aria-pressed={chaptersOpen}
            className={chaptersOpen ? 'bg-white/15 text-white' : ''}
          >
            <List size={17} />
          </ChromeButton>
        )}
        <ChromeButton
          onClick={onToggleBookmarks}
          aria-label="Bookmarks"
          aria-pressed={bookmarksOpen}
          className={bookmarksOpen ? 'bg-white/15 text-white' : ''}
        >
          <Bookmark size={17} />
        </ChromeButton>
        <ChromeButton
          onClick={onToggleSyncPlay}
          aria-label="Watch party"
          aria-pressed={syncPlayOpen}
          className={syncPlayOpen || syncPlayActive ? 'bg-white/15 text-white' : ''}
        >
          <span className="relative">
            <Users size={17} />
            {syncPlayActive && (
              <span className="absolute -top-0.5 -right-0.5 w-1.5 h-1.5 rounded-full bg-accent" />
            )}
          </span>
        </ChromeButton>
        <PictureMenu
          brightness={videoBrightness}
          contrast={videoContrast}
          saturation={videoSaturation}
          onChange={onPictureChange}
          onReset={onPictureReset}
        />
        <ChromeButton
          onClick={onToggleStreamInfo}
          aria-label="Stream info"
          aria-pressed={streamInfoOpen}
          className={streamInfoOpen ? 'bg-white/15 text-white' : ''}
        >
          <Info size={17} />
        </ChromeButton>
      </div>
    </motion.div>
  )
}

function ChromeButton({
  children,
  className = '',
  ...props
}: ButtonHTMLAttributes<HTMLButtonElement>) {
  return (
    <button
      {...props}
      className={`w-9 h-9 rounded-full bg-black/40 hover:bg-black/60 backdrop-blur grid place-items-center text-white/85 hover:text-white transition-colors focus-ring ${className}`}
    >
      {children}
    </button>
  )
}

function formatSleep(sec: number): string {
  const m = Math.floor(sec / 60)
  const s = sec % 60
  if (m >= 60) return `${Math.floor(m / 60)}:${String(m % 60).padStart(2, '0')}`
  return `${m}:${String(s).padStart(2, '0')}`
}
