import { useRef } from 'react'
import type { JudgeTrack, RoleGroup, Verdict } from '@/types'
import { WaveformPlayer } from '@/components/WaveformPlayer'
import { OrbitRail } from '@/components/OrbitRail'
import { mmss, fmtDb } from '@/lib/format'
import { VERDICTS, verdictMeta } from './verdict'

type Source = 'head' | 'full'

interface Props {
  track: JudgeTrack
  roleGroups: RoleGroup[]
  activeDb: number
  litFloorDb: number
  expanded: boolean
  source: Source
  verdict: Verdict
  comment: string
  currentTime: number
  onExpand: () => void
  onTime: (t: number) => void
  onVerdict: (v: Verdict) => void
  onComment: (c: string) => void
  onFinish: () => void
  autoPlay: boolean
}

export function TrackRow({
  track, roleGroups, activeDb, litFloorDb, expanded, source,
  verdict, comment, currentTime, onExpand, onTime, onVerdict, onComment,
  onFinish, autoPlay,
}: Props) {
  const vm = verdictMeta(verdict)
  // `orbits`/`samples` carry pydantic defaults, so the generated TS marks them
  // optional. Normalise once here instead of guarding at every use.
  const orbits = track.orbits ?? []
  const samples = track.samples ?? []
  const commentRef = useRef<HTMLTextAreaElement>(null)
  const stream = track.masters?.stream ?? Object.values(track.masters ?? {})[0]

  // The head is the track's first 16 s — verified bit-exact — so the orbit rail
  // indexes the SAME activity array either way; only the transport changes.
  const url = source === 'head' ? track.audio : (track.fullAudio ?? track.audio)
  const dur = source === 'head' ? track.durS : track.trackDurS

  return (
    <li
      className={`rounded-lg border transition-colors ${
        expanded ? 'border-hairline bg-raised' : 'border-transparent hover:bg-raised/60'
      }`}
    >
      {/* ── the row: readable without expanding ── */}
      <button
        onClick={onExpand}
        className="flex w-full items-center gap-3 px-3 py-2 text-left"
        aria-expanded={expanded}
      >
        <span
          className="w-6 shrink-0 text-center font-mono text-xs tnum"
          style={{ color: vm.color }}
          title={vm.label}
        >
          {vm.glyph}
        </span>
        <span className="w-6 shrink-0 font-mono text-xs text-ink-faint tnum">{track.n}</span>

        <span className="min-w-0 flex-1">
          <span className="block truncate text-sm font-medium">{track.title}</span>
          <span className="mt-0.5 flex flex-wrap items-center gap-x-2 gap-y-0.5 text-[11px] text-ink-faint">
            {track.section && <span>{track.section}</span>}
            {track.bpm ? <span className="tnum">{track.bpm} BPM</span> : null}
            <span className="tnum">{mmss(track.trackDurS, 0)}</span>
            {stream?.I != null && <span className="tnum">{fmtDb(stream.I, ' LUFS')}</span>}
            <span className="tnum">{orbits.length} orbits</span>
            {comment && !expanded && (
              <span className="truncate text-ink-muted italic">“{comment}”</span>
            )}
          </span>
        </span>
      </button>

      {/* ── expanded: the evidence + the call ── */}
      {expanded && (
        <div className="flex flex-col gap-3 border-t border-hairline px-3 pb-3 pt-3">
          <WaveformPlayer
            key={url}
            url={url}
            dur={dur}
            // Peaks describe the FULL track; the 16 s head is small enough to
            // decode on its own, and reusing full-track peaks for it would draw
            // the wrong picture.
            peaks={source === 'full' ? track.peaks : undefined}
            onTime={onTime}
            onFinish={onFinish}
            autoPlay={autoPlay}
          />

          <OrbitRail
            binS={track.binS}
            orbits={orbits}
            roleGroups={roleGroups}
            currentTime={currentTime}
            activeDb={activeDb}
            litFloorDb={litFloorDb}
          />

          {samples.length > 0 && (
            <p className="text-[11px] leading-relaxed text-ink-faint">
              <span className="text-ink-muted">banks</span>{' '}
              <span className="font-mono">{samples.join(' · ')}</span>
            </p>
          )}

          <div className="flex flex-wrap items-center gap-2">
            {VERDICTS.filter((v) => v.key !== 'pending').map((v) => {
              const on = verdict === v.key
              return (
                <button
                  key={v.key}
                  onClick={() => onVerdict(on ? 'pending' : v.key)}
                  className="flex items-center gap-1.5 rounded-md border px-3 py-1.5 text-xs
                             font-medium transition-colors"
                  style={{
                    borderColor: on ? v.color : 'var(--color-hairline)',
                    color: on ? v.color : 'var(--color-ink-muted)',
                    background: on ? `color-mix(in oklab, ${v.color} 14%, transparent)` : 'transparent',
                  }}
                  title={`${v.label}  (${v.hotkey})`}
                >
                  <span aria-hidden>{v.glyph}</span> {v.label}
                </button>
              )
            })}
            <span className="ml-auto font-mono text-[11px] text-ink-faint tnum">
              set {mmss(track.startS, 0)}–{mmss(track.endS, 0)}
            </span>
          </div>

          <textarea
            ref={commentRef}
            value={comment}
            onChange={(e) => onComment(e.target.value)}
            placeholder="What did you hear? (timecode, what's wrong, what to fix)"
            rows={2}
            className="w-full resize-y rounded-md border border-hairline bg-surface px-2.5 py-2
                       text-xs leading-relaxed placeholder:text-ink-faint/70
                       focus:border-ink-faint focus:outline-none"
          />
        </div>
      )}
    </li>
  )
}
