import { useEffect, useState } from 'react'
import type { BaseItemDto } from '../../api/types'
import {
  pickPrimarySource,
  getAudioStreams,
  getSubtitleStreams,
  resolutionLabel,
  videoRangeLabel,
} from '../../lib/jellyfin-meta'

/**
 * Compact horizontal strip of "official-style" media tech badges.
 * Each badge tries to render an SVG from /icons/media-tech/<name>.svg
 * (drop your own per public/icons/media-tech/README.md) and falls back to
 * a clean typographic badge when the SVG is missing.
 */

interface Props {
  item: BaseItemDto | null | undefined
  size?: 'sm' | 'md'
  className?: string
}

const ICON_BASE = '/icons/media-tech'

export default function MediaTechIcons({ item, size = 'md', className = '' }: Props) {
  if (!item) return null
  const source = pickPrimarySource(item)
  const audio = getAudioStreams(item)[0]
  const subs = getSubtitleStreams(item)

  const res = resolutionLabel(item)
  const range = videoRangeLabel(item)

  const audioCodec = (audio?.Codec || '').toLowerCase()
  const audioProfile = (audio?.Profile || '').toLowerCase()
  const audioSpatial = (audio?.AudioSpatialFormat || '').toLowerCase()
  const channels = audio?.Channels || 0
  const channelLayout = (audio?.ChannelLayout || '').toLowerCase()

  const audio_ = pickAudioFormat(audioCodec, audioProfile, audioSpatial)
  const channel_ = pickChannelLabel(channels, channelLayout)
  const container = source?.Container?.toLowerCase()

  const anything = res || range || audio_ || channel_ || container || subs.length > 0
  if (!anything) return null

  return (
    <div className={`flex items-center gap-1.5 flex-wrap ${className}`}>
      {res && <ResolutionBadge res={res} size={size} />}
      {range && <RangeBadge range={range} size={size} />}
      {audio_ && <AudioBadge format={audio_} size={size} />}
      {channel_ && <ChannelBadge label={channel_} size={size} />}
      {container && <ContainerBadge label={container} size={size} />}
      {subs.length > 0 && <SubBadge count={subs.length} size={size} />}
    </div>
  )
}

/* ──────────────────────────────────────────────────────────── */
/*  Smart icon-or-fallback                                      */
/* ──────────────────────────────────────────────────────────── */

/**
 * Reads a local SVG once, parses its viewBox / dimensions to derive aspect
 * ratio, and caches the result. We then render the icon via CSS mask-image -
 * which paints the element's `background-color` clipped by the SVG silhouette,
 * giving a uniform white render regardless of the source SVG's fill colors.
 */
const svgInfoCache = new Map<string, { aspect: number } | 'missing'>()

function useSvgInfo(url: string): { aspect: number | null; missing: boolean } {
  const initial = svgInfoCache.get(url)
  const [aspect, setAspect] = useState<number | null>(
    initial && initial !== 'missing' ? initial.aspect : null,
  )
  const [missing, setMissing] = useState<boolean>(initial === 'missing')

  useEffect(() => {
    if (svgInfoCache.has(url)) return
    let cancelled = false

    fetch(url)
      .then(res => {
        if (!res.ok) throw new Error(`${res.status}`)
        const ct = res.headers.get('content-type') || ''
        if (!ct.includes('svg') && !ct.includes('xml')) throw new Error('not svg')
        return res.text()
      })
      .then(raw => {
        const a = parseAspect(raw)
        if (a == null) throw new Error('no dimensions')
        svgInfoCache.set(url, { aspect: a })
        if (!cancelled) setAspect(a)
      })
      .catch(() => {
        svgInfoCache.set(url, 'missing')
        if (!cancelled) setMissing(true)
      })

    return () => { cancelled = true }
  }, [url])

  return { aspect, missing }
}

function parseAspect(svg: string): number | null {
  const vb = svg.match(/<svg[^>]*\sviewBox\s*=\s*"\s*([-\d.eE]+)\s+([-\d.eE]+)\s+([-\d.eE]+)\s+([-\d.eE]+)\s*"/i)
  if (vb) {
    const w = parseFloat(vb[3])
    const h = parseFloat(vb[4])
    if (w > 0 && h > 0) return w / h
  }
  const wAttr = svg.match(/<svg[^>]*\swidth\s*=\s*"([\d.]+)/i)
  const hAttr = svg.match(/<svg[^>]*\sheight\s*=\s*"([\d.]+)/i)
  if (wAttr && hAttr) {
    const w = parseFloat(wAttr[1])
    const h = parseFloat(hAttr[1])
    if (w > 0 && h > 0) return w / h
  }
  return null
}

function IconOrFallback({
  iconFile,
  fallback,
  size,
  alt,
}: {
  iconFile: string
  fallback: React.ReactNode
  size: 'sm' | 'md'
  alt: string
}) {
  const url = `${ICON_BASE}/${iconFile}`
  const { aspect, missing } = useSvgInfo(url)

  if (missing) return <>{fallback}</>

  const h = size === 'sm' ? 18 : 22
  const w = aspect ? Math.round(h * aspect) : h * 3
  // Cap absurdly wide logos so a single badge can't dominate the row
  const cappedWidth = Math.min(w, h * 6)

  return (
    <span
      role="img"
      aria-label={alt}
      title={alt}
      className="inline-block select-none align-middle"
      style={{
        height: h,
        width: cappedWidth,
        backgroundColor: 'white',
        WebkitMaskImage: `url(${url})`,
        maskImage: `url(${url})`,
        WebkitMaskRepeat: 'no-repeat',
        maskRepeat: 'no-repeat',
        WebkitMaskPosition: 'center',
        maskPosition: 'center',
        WebkitMaskSize: 'contain',
        maskSize: 'contain',
      }}
    />
  )
}

/* ──────────────────────────────────────────────────────────── */
/*  Resolution                                                  */
/* ──────────────────────────────────────────────────────────── */

function ResolutionBadge({ res, size }: { res: string; size: 'sm' | 'md' }) {
  const file =
    res === '4K' ? '4k-uhd.svg'
    : res === '1080p' ? 'hd-1080p.svg'
    : res === '720p' ? 'hd-720p.svg'
    : null

  if (file) {
    return <IconOrFallback iconFile={file} alt={res} size={size} fallback={<ResolutionTextBadge res={res} size={size} />} />
  }
  return <ResolutionTextBadge res={res} size={size} />
}

function ResolutionTextBadge({ res, size }: { res: string; size: 'sm' | 'md' }) {
  const h = size === 'sm' ? 'h-5' : 'h-6'
  const fs = size === 'sm' ? 'text-[9px]' : 'text-[10px]'
  if (res === '4K') {
    return (
      <span className={`${h} ${fs} inline-flex items-stretch overflow-hidden rounded-md ring-1 ring-white/10 shadow-sm font-bold uppercase tracking-[0.04em] select-none`}>
        <span className="px-1.5 grid place-items-center bg-white text-black">4K</span>
        <span className="px-1.5 grid place-items-center bg-black text-white tracking-[0.18em]">UHD</span>
      </span>
    )
  }
  if (res === '1080p') {
    return (
      <span className={`${h} ${fs} inline-flex items-stretch overflow-hidden rounded-md ring-1 ring-white/15 shadow-sm font-bold uppercase tracking-[0.04em] select-none`}>
        <span className="px-1.5 grid place-items-center bg-white text-black">HD</span>
        <span className="px-1.5 grid place-items-center bg-black text-white tracking-[0.18em]">1080P</span>
      </span>
    )
  }
  return (
    <span className={`${h} ${fs} inline-flex items-center px-2 rounded-md bg-black text-white/90 ring-1 ring-white/10 font-bold uppercase tracking-[0.12em] select-none`}>
      {res}
    </span>
  )
}

/* ──────────────────────────────────────────────────────────── */
/*  HDR / Dolby Vision                                          */
/* ──────────────────────────────────────────────────────────── */

function RangeBadge({ range, size }: { range: string; size: 'sm' | 'md' }) {
  const file =
    range === 'Dolby Vision' ? 'dolby-vision.svg'
    : range === 'HDR10+' ? 'hdr10-plus.svg'
    : range === 'HDR10' || range === 'HDR' ? 'hdr10.svg'
    : null

  if (file) {
    return <IconOrFallback iconFile={file} alt={range} size={size} fallback={<RangeTextBadge range={range} size={size} />} />
  }
  return <RangeTextBadge range={range} size={size} />
}

function RangeTextBadge({ range, size }: { range: string; size: 'sm' | 'md' }) {
  const h = size === 'sm' ? 'h-5' : 'h-6'
  const fs = size === 'sm' ? 'text-[9px]' : 'text-[10px]'
  if (range === 'Dolby Vision') {
    return (
      <span className={`${h} ${fs} inline-flex items-center px-2 rounded-md bg-black text-white ring-1 ring-white/15 shadow-sm font-bold uppercase tracking-[0.12em] select-none`}>
        Dolby Vision
      </span>
    )
  }
  if (range === 'HDR10+') {
    return (
      <span className={`${h} ${fs} inline-flex items-center px-2 rounded-md ring-1 ring-amber-300/30 shadow-sm font-bold uppercase tracking-[0.06em] select-none bg-gradient-to-b from-amber-400 to-amber-600 text-black`}>
        HDR10<sup className="ml-px text-[7px]">+</sup>
      </span>
    )
  }
  return (
    <span className={`${h} ${fs} inline-flex items-center px-2 rounded-md ring-1 ring-amber-300/30 shadow-sm font-bold uppercase tracking-[0.08em] select-none bg-gradient-to-b from-amber-400 to-amber-600 text-black`}>
      {range}
    </span>
  )
}

/* ──────────────────────────────────────────────────────────── */
/*  Audio                                                       */
/* ──────────────────────────────────────────────────────────── */

interface AudioFormat {
  iconFile: string | null
  label: string
  alt: string
  /** When set, the typographic fallback gets a tone treatment. */
  fallbackTone?: 'dolby' | 'dts' | 'lossless' | 'lossy'
}

function AudioBadge({ format, size }: { format: AudioFormat; size: 'sm' | 'md' }) {
  if (format.iconFile) {
    return (
      <IconOrFallback
        iconFile={format.iconFile}
        alt={format.alt}
        size={size}
        fallback={<AudioTextBadge format={format} size={size} />}
      />
    )
  }
  return <AudioTextBadge format={format} size={size} />
}

function AudioTextBadge({ format, size }: { format: AudioFormat; size: 'sm' | 'md' }) {
  const h = size === 'sm' ? 'h-5' : 'h-6'
  const fs = size === 'sm' ? 'text-[9px]' : 'text-[10px]'
  const toneCls =
    format.fallbackTone === 'dolby'
      ? 'bg-black text-white ring-white/15'
      : format.fallbackTone === 'dts'
        ? 'bg-gradient-to-b from-zinc-700 to-black text-white ring-white/15'
        : format.fallbackTone === 'lossless'
          ? 'bg-emerald-500/15 text-emerald-300 ring-emerald-500/30'
          : 'bg-white/8 text-white/85 ring-white/12'
  return (
    <span className={`${h} ${fs} ${toneCls} inline-flex items-center px-2 rounded-md ring-1 font-bold uppercase tracking-[0.06em] select-none`}>
      {format.label}
    </span>
  )
}

/* ──────────────────────────────────────────────────────────── */
/*  Channel / Container / Subs                                  */
/* ──────────────────────────────────────────────────────────── */

function ChannelBadge({ label, size }: { label: string; size: 'sm' | 'md' }) {
  const file =
    label === '5.1' ? '5-1.svg'
    : label === '7.1' ? '7-1.svg'
    : label === 'Stereo' ? 'stereo.svg'
    : label === 'Mono' ? 'mono.svg'
    : null

  if (file) {
    return <IconOrFallback iconFile={file} alt={label} size={size} fallback={<ChannelTextBadge label={label} size={size} />} />
  }
  return <ChannelTextBadge label={label} size={size} />
}

function ChannelTextBadge({ label, size }: { label: string; size: 'sm' | 'md' }) {
  const h = size === 'sm' ? 'h-5' : 'h-6'
  const fs = size === 'sm' ? 'text-[9px]' : 'text-[10px]'
  return (
    <span className={`${h} ${fs} inline-flex items-center px-2 rounded-md bg-white/8 text-white/90 ring-1 ring-white/12 font-bold uppercase tracking-[0.06em] tabular-nums select-none`}>
      {label}
    </span>
  )
}

function ContainerBadge({ label, size }: { label: string; size: 'sm' | 'md' }) {
  // Allow per-container icon files: mkv.svg, mp4.svg, webm.svg, etc.
  const file = `${label}.svg`
  const upper = label.toUpperCase()
  return (
    <IconOrFallback
      iconFile={file}
      alt={upper}
      size={size}
      fallback={<ContainerTextBadge label={upper} size={size} />}
    />
  )
}

function ContainerTextBadge({ label, size }: { label: string; size: 'sm' | 'md' }) {
  const h = size === 'sm' ? 'h-5' : 'h-6'
  const fs = size === 'sm' ? 'text-[9px]' : 'text-[10px]'
  return (
    <span className={`${h} ${fs} inline-flex items-center px-2 rounded-md bg-void text-text-2 ring-1 ring-border font-bold uppercase tracking-[0.08em] select-none`}>
      {label}
    </span>
  )
}

function SubBadge({ count, size }: { count: number; size: 'sm' | 'md' }) {
  return (
    <IconOrFallback
      iconFile="closed-captions.svg"
      alt={`Closed captions (${count} tracks)`}
      size={size}
      fallback={<SubTextBadge count={count} size={size} />}
    />
  )
}

function SubTextBadge({ count, size }: { count: number; size: 'sm' | 'md' }) {
  const h = size === 'sm' ? 'h-5' : 'h-6'
  const fs = size === 'sm' ? 'text-[9px]' : 'text-[10px]'
  return (
    <span
      className={`${h} ${fs} inline-flex items-center gap-1 px-2 rounded-md bg-white/5 text-white/75 ring-1 ring-white/10 font-bold uppercase tracking-[0.08em] tabular-nums select-none`}
      title={`${count} subtitle track${count === 1 ? '' : 's'}`}
    >
      CC
      <span className="text-white/55">×{count}</span>
    </span>
  )
}

/* ──────────────────────────────────────────────────────────── */
/*  Codec → format mapping                                      */
/* ──────────────────────────────────────────────────────────── */

function pickAudioFormat(codec: string, profile: string, spatial: string): AudioFormat | null {
  if (spatial.includes('dolbyatmos') || profile.includes('atmos')) {
    return { iconFile: 'dolby-atmos.svg', label: 'Atmos', alt: 'Dolby Atmos', fallbackTone: 'dolby' }
  }
  if (spatial.includes('dtsx') || profile.includes(':x')) {
    return { iconFile: 'dts-x.svg', label: 'DTS:X', alt: 'DTS:X', fallbackTone: 'dts' }
  }
  if (codec === 'eac3') return { iconFile: 'dolby-digital-plus.svg', label: 'Dolby Digital+', alt: 'Dolby Digital Plus', fallbackTone: 'dolby' }
  if (codec === 'truehd') return { iconFile: 'dolby-truehd.svg', label: 'TrueHD', alt: 'Dolby TrueHD', fallbackTone: 'dolby' }
  if (codec === 'ac3') return { iconFile: 'dolby-digital.svg', label: 'Dolby Digital', alt: 'Dolby Digital', fallbackTone: 'dolby' }

  if (codec === 'dts') {
    if (profile.includes('hd ma') || profile.includes('hd-ma')) {
      return { iconFile: 'dts-hd-ma.svg', label: 'DTS-HD MA', alt: 'DTS-HD Master Audio', fallbackTone: 'dts' }
    }
    if (profile.includes('hd hra') || profile.includes('hd-hra')) {
      return { iconFile: 'dts-hd-hra.svg', label: 'DTS-HD HRA', alt: 'DTS-HD HRA', fallbackTone: 'dts' }
    }
    return { iconFile: 'dts.svg', label: 'DTS', alt: 'DTS', fallbackTone: 'dts' }
  }

  if (codec === 'flac') return { iconFile: null, label: 'FLAC', alt: 'FLAC', fallbackTone: 'lossless' }
  if (codec === 'pcm' || codec.startsWith('pcm_')) return { iconFile: null, label: 'PCM', alt: 'PCM', fallbackTone: 'lossless' }
  if (codec === 'alac') return { iconFile: null, label: 'ALAC', alt: 'ALAC', fallbackTone: 'lossless' }
  if (codec === 'opus') return { iconFile: null, label: 'Opus', alt: 'Opus', fallbackTone: 'lossy' }
  if (codec === 'aac') return { iconFile: null, label: 'AAC', alt: 'AAC', fallbackTone: 'lossy' }
  if (codec === 'mp3') return { iconFile: null, label: 'MP3', alt: 'MP3', fallbackTone: 'lossy' }
  if (codec === 'vorbis') return { iconFile: null, label: 'Vorbis', alt: 'Vorbis', fallbackTone: 'lossy' }

  return null
}

function pickChannelLabel(channels: number, layout: string): string | null {
  if (layout.includes('7.1') || channels >= 8) return '7.1'
  if (layout.includes('5.1') || channels === 6) return '5.1'
  if (layout.includes('quad') || channels === 4) return '4.0'
  if (channels === 2) return 'Stereo'
  if (channels === 1) return 'Mono'
  return null
}
