import { useEffect, useMemo, useState } from 'react'
import { Download, Anchor } from 'lucide-react'
import type { Note, PlayerData, Variant } from '@/types'
import { TakePanel } from '@/components/TakePanel'

const NOTES_KEY = 'pac_judge_notes'

function useNotes() {
  const [notes, setNotes] = useState<Note[]>(() => {
    try {
      return JSON.parse(localStorage.getItem(NOTES_KEY) || '[]')
    } catch {
      return []
    }
  })
  useEffect(() => {
    localStorage.setItem(NOTES_KEY, JSON.stringify(notes))
  }, [notes])
  const add = (takeId: string, t: number, text: string) =>
    setNotes((ns) =>
      [...ns, { id: `${takeId}-${Math.round(t * 1000)}-${ns.length}`, takeId, t, text }].sort(
        (a, b) => a.t - b.t,
      ),
    )
  return { notes, add }
}

export default function App() {
  const [data, setData] = useState<PlayerData | null>(null)
  const [variant, setVariant] = useState<Variant>('stream')
  const { notes, add } = useNotes()

  useEffect(() => {
    fetch('/punkachien.json')
      .then((r) => r.json())
      .then(setData)
      .catch(() => setData(null))
  }, [])

  const exportNotes = () => {
    const blob = new Blob([JSON.stringify(notes, null, 2)], { type: 'application/json' })
    const a = document.createElement('a')
    a.href = URL.createObjectURL(blob)
    a.download = 'punkachien_judge_notes.json'
    a.click()
    URL.revokeObjectURL(a.href)
  }

  const matchNote = useMemo(
    () =>
      variant === 'stream'
        ? 'A/B is loudness-matched — both takes at the −14 LUFS streaming target.'
        : 'A/B is loudness-matched — both takes at the club target (≈ −11.4 LUFS; true −9 needs a limiter stage).',
    [variant],
  )

  if (!data) {
    return (
      <div className="grid min-h-svh place-items-center text-ink-muted">
        <p className="animate-pulse text-sm">loading the bridge…</p>
      </div>
    )
  }

  return (
    <div className="mx-auto flex min-h-svh max-w-6xl flex-col gap-6 px-4 py-5">
      <header className="flex flex-wrap items-end justify-between gap-3 border-b border-hairline pb-4">
        <div>
          <p className="flex items-center gap-1.5 text-[11px] uppercase tracking-widest text-ink-faint">
            <Anchor size={12} /> L&apos;Armada · judge
          </p>
          <h1 className="text-2xl font-semibold tracking-tight">
            {data.track} <span className="text-ink-muted">— A/B</span>
          </h1>
          <p className="mt-0.5 text-xs text-ink-faint">{data.calibration}</p>
        </div>

        <div className="flex items-center gap-3">
          <div className="flex rounded-md border border-hairline p-0.5 text-xs">
            {(['stream', 'club'] as Variant[]).map((v) => (
              <button
                key={v}
                onClick={() => setVariant(v)}
                className={`rounded px-3 py-1 capitalize transition-colors ${
                  variant === v ? 'bg-ink text-surface' : 'text-ink-muted hover:text-ink'
                }`}
              >
                {v}
              </button>
            ))}
          </div>
          <button
            onClick={exportNotes}
            disabled={!notes.length}
            className="flex items-center gap-1.5 rounded-md bg-raised px-3 py-1.5 text-xs
                       font-medium hover:bg-overlay disabled:opacity-30"
          >
            <Download size={13} /> Export notes
          </button>
        </div>
      </header>

      <p className="-mt-2 text-xs text-ink-muted">{matchNote}</p>

      <div className="grid flex-1 gap-4 lg:grid-cols-2">
        {data.takes.map((take) => (
          <TakePanel
            key={take.id}
            take={take}
            variant={variant}
            roleGroups={data.roleGroups}
            activeDb={data.activeDb}
            calibration={data.calibration}
            notes={notes.filter((n) => n.takeId === take.id)}
            onAddNote={(t, text) => add(take.id, t, text)}
          />
        ))}
      </div>

      <footer className="border-t border-hairline pt-3 text-[11px] text-ink-faint">
        Independent transports — each take is its own performance. Space toggles the focused
        player. Notes persist locally; export feeds the ear-archive.
      </footer>
    </div>
  )
}
