/**
 * One sample: what it is, what it sounds like, and two ways to hear it.
 *
 * The two buttons are not the same test and the difference is the point of the page.
 * **Once** plays the file untouched, which is how you hear its attack and its tail.
 * **Loop** loops it seamlessly at rate 1, which is the only way to hear the seam the
 * cutter actually produced — and the seam is the single thing that decides whether a
 * loop is usable, because it is the sound the audience hears every bar.
 *
 * **+** puts it in the rack, where it stops being a file and becomes a voice in a
 * groove at the deck's tempo.
 */
import { Play, Repeat, Square, Plus, Check } from 'lucide-react'
import { Waveform } from './Waveform'
import { familyColor, fmtBpm, TIER_COLOR, type Sample } from './types'
import { barErrorMs } from './engine'

type Props = {
  s: Sample
  kit: string
  playing: 'once' | 'loop' | null
  head: number | null
  inRack: boolean
  focused: boolean
  onPlay: (mode: 'once' | 'loop') => void
  onStop: () => void
  onRack: () => void
  onFocus: () => void
}

const TAG_AXES = ['instrument', 'texture', 'mood'] as const

/** Where in the source track, so two loops off the same stem are tellable apart. */
const mmss = (s: number) => `${Math.floor(s / 60)}:${String(Math.floor(s % 60)).padStart(2, '0')}`

export function SampleRow({ s, playing, head, inRack, focused, onPlay, onStop, onRack, onFocus }: Props) {
  const col = familyColor(s.family)
  const bars = s.bars ?? 0
  const err = s.bars && s.bpm && s.dur_s ? barErrorMs(s.dur_s, s.bars, s.bpm) : 0
  // top tag per axis, at all — a wall of CLAP labels is not information
  const tags = TAG_AXES.map((a) => s.tags?.[a]?.[0]).filter(Boolean) as [string, number][]

  return (
    <div
      onMouseDown={onFocus}
      className={`grid grid-cols-[2.2rem_14rem_3.2rem_1fr_5.5rem_4.6rem] items-center gap-2
                  px-2 py-1 border-b border-hairline/60 cursor-default
                  ${focused ? 'bg-overlay' : 'hover:bg-raised'}`}
    >
      {/* the index you type. `# n 3` is the whole reason the kit is addressable */}
      <div className="tnum font-mono text-[13px] text-ink-muted text-right pr-1">{s.n}</div>

      <div className="min-w-0" title={s.file}>
        <div className="truncate text-[13px] leading-tight" style={{ color: col }}>
          {s.stem_role ?? s.name}
        </div>
        <div className="truncate text-[11px] text-ink-faint leading-tight">
          {bars > 0
            ? <>{bars} bar{bars > 1 ? 's' : ''} · {s.bpm != null ? fmtBpm(s.bpm) : '?'} bpm
                {s.start_s != null && <> · @{mmss(s.start_s)}</>}
                {Math.abs(err) > 1 && <span className="text-wip"> · {err > 0 ? '+' : ''}{err.toFixed(0)}ms off</span>}</>
            : <>{s.dur_s ? `${s.dur_s.toFixed(2)}s chop` : `${s.ch}ch ${(s.sr / 1000).toFixed(1)}k`}
                {s.start_s != null && <> · @{mmss(s.start_s)}</>}</>}
        </div>
      </div>

      <div className="flex items-center gap-1">
        {s.tier && (
          <span className="tnum font-mono text-[11px] px-1 rounded-sm"
                style={{ color: TIER_COLOR[s.tier], border: `1px solid ${TIER_COLOR[s.tier]}55` }}
                title={s.grade ? `grade ${s.grade.toFixed(3)}` : undefined}>
            {s.tier}
          </span>
        )}
        {s.flags.length > 0 && (
          <span className="text-[11px] text-wip" title={s.flags.join(', ')}>!</span>
        )}
      </div>

      {/* Tags UNDER the waveform, not over it. Absolutely positioned they covered the
          first ~15% of every envelope — which is the downbeat, the one part of a loop
          you actually need to see. */}
      <div className="min-w-0">
        <Waveform env={s.env} color={col} head={head} bars={bars} height={26} />
        <div className="flex gap-1.5 h-[11px] overflow-hidden">
          {tags.map(([t, p]) => (
            <span key={t} className="text-[10px] leading-[11px] text-ink-faint/70 truncate"
                  title={`${t} (${(p * 100).toFixed(0)}%)`}>{t}</span>
          ))}
        </div>
      </div>

      <div className="tnum font-mono text-[11px] text-ink-faint text-right">
        {s.peak_dbfs.toFixed(1)} / {s.rms_dbfs.toFixed(0)}
      </div>

      <div className="flex items-center justify-end gap-0.5">
        <button title="play once, untouched"
                onClick={() => (playing === 'once' ? onStop() : onPlay('once'))}
                className={`p-1 rounded-sm hover:bg-overlay ${playing === 'once' ? 'text-magenta' : 'text-ink-muted'}`}>
          {playing === 'once' ? <Square size={13} /> : <Play size={13} />}
        </button>
        <button title="loop it — the only way to hear the seam"
                onClick={() => (playing === 'loop' ? onStop() : onPlay('loop'))}
                className={`p-1 rounded-sm hover:bg-overlay ${playing === 'loop' ? 'text-magenta' : 'text-ink-muted'}`}>
          <Repeat size={13} />
        </button>
        <button title={inRack ? 'in the rack' : 'add to the rack'} onClick={onRack}
                className={`p-1 rounded-sm hover:bg-overlay ${inRack ? 'text-ready' : 'text-ink-muted'}`}>
          {inRack ? <Check size={13} /> : <Plus size={13} />}
        </button>
      </div>
    </div>
  )
}
