import { useState, useRef, useMemo } from 'react';
import { Search, Play, Square, AudioLines } from 'lucide-react';
import { Widget } from 'widgets/Widget';
import { Input } from '@/components/ui/input';
import { categories, allSounds } from './catalog-data';
import type { SoundAsset } from './types';

type ActiveCategory = 'all' | string;

const formatName = (name: string) =>
  name
    .split('-')
    .map((w) => w.charAt(0).toUpperCase() + w.slice(1))
    .join(' ');

const getCategoryLabel = (sound: SoundAsset): string => {
  const cat = categories.find((c) => c.sounds.includes(sound));
  return cat?.label ?? '';
};

const SoundCard = ({
  sound,
  isPlaying,
  onPlay,
  onStop,
}: {
  sound: SoundAsset;
  isPlaying: boolean;
  onPlay: () => void;
  onStop: () => void;
}) => (
  <button
    type="button"
    onClick={isPlaying ? onStop : onPlay}
    className={`flex flex-col items-center gap-2 rounded-lg border px-3 py-4 text-center transition-all cursor-pointer ${
      isPlaying
        ? 'border-duck-teal bg-duck-teal/5'
        : 'border-duck-dark/10 hover:border-duck-dark/25 hover:bg-duck-dark/[0.02]'
    }`}
  >
    <div className="h-8 flex items-center justify-center text-duck-dark/30">
      {isPlaying ? <Square className="h-5 w-5 text-duck-teal fill-duck-teal" /> : <Play className="h-5 w-5" />}
    </div>
    <span className="text-sm font-medium text-duck-dark leading-tight">{formatName(sound.name)}</span>
    <span className="text-xs text-duck-dark/40">
      {getCategoryLabel(sound)} &middot; {sound.duration.toFixed(2)}s
    </span>
  </button>
);

export const Catalog = () => {
  const [search, setSearch] = useState('');
  const [activeCategory, setActiveCategory] = useState<ActiveCategory>('all');
  const [playingId, setPlayingId] = useState<string | null>(null);
  const audioRef = useRef<HTMLAudioElement | null>(null);

  const filtered = useMemo(() => {
    const source =
      activeCategory === 'all' ? allSounds : (categories.find((c) => c.id === activeCategory)?.sounds ?? []);
    if (!search) return source;
    const q = search.toLowerCase();
    return source.filter((s) => s.name.toLowerCase().includes(q));
  }, [search, activeCategory]);

  const play = (sound: SoundAsset) => {
    if (audioRef.current) {
      audioRef.current.pause();
      audioRef.current = null;
    }
    const audio = new Audio(sound.dataUri);
    audio.addEventListener('ended', () => setPlayingId(null));
    audio.play();
    audioRef.current = audio;
    setPlayingId(sound.name);
  };

  const stop = () => {
    if (audioRef.current) {
      audioRef.current.pause();
      audioRef.current = null;
    }
    setPlayingId(null);
  };

  const tabs = [
    { id: 'all' as const, label: 'All', count: allSounds.length },
    ...categories.map((c) => ({ id: c.id, label: c.label, count: c.sounds.length })),
  ];

  return (
    <Widget title="Sound Library">
      <div className="flex flex-col gap-4 px-4 pb-4">
        <div className="flex flex-col sm:flex-row items-start sm:items-center gap-3">
          <div className="relative w-full sm:w-56">
            <Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-duck-dark/40" />
            <Input
              placeholder="Search sounds..."
              value={search}
              onChange={(ev) => setSearch(ev.target.value)}
              className="pl-9"
            />
          </div>
          <div className="flex flex-wrap gap-1.5">
            {tabs.map((tab) => (
              <button
                key={tab.id}
                type="button"
                onClick={() => setActiveCategory(tab.id)}
                className={`px-2.5 py-1 rounded-full text-xs font-medium cursor-pointer transition-colors border ${
                  activeCategory === tab.id
                    ? 'border-duck-teal bg-duck-teal/10 text-duck-teal'
                    : 'border-duck-dark/15 text-duck-dark/50 hover:border-duck-dark/30'
                }`}
              >
                {tab.label} <span className="opacity-60">{tab.count}</span>
              </button>
            ))}
          </div>
          <span className="text-xs text-duck-dark/40 ml-auto hidden sm:block">{filtered.length} sounds</span>
        </div>

        {filtered.length === 0 && <p className="text-sm text-duck-dark/40 py-8 text-center">No sounds found.</p>}

        <div className="max-h-[400px] overflow-y-auto">
          <div className="grid grid-cols-2 sm:grid-cols-3 gap-2">
            {filtered.map((sound) => (
              <SoundCard
                key={sound.name}
                sound={sound}
                isPlaying={playingId === sound.name}
                onPlay={() => play(sound)}
                onStop={stop}
              />
            ))}
          </div>
        </div>

        <div className="flex items-center justify-between pt-1">
          <span className="text-[11px] text-duck-dark/70">
            CC0 licensed &middot; Original audio by{' '}
            <a
              href="https://kenney.nl/"
              target="_blank"
              rel="noopener noreferrer"
              className="underline hover:text-duck-dark"
            >
              Kenney
            </a>
          </span>
          <a
            href="https://www.soundcn.xyz/"
            target="_blank"
            rel="noopener noreferrer"
            className="flex items-center gap-2 hover:opacity-80 transition-opacity"
          >
            <span className="text-xs text-duck-dark/40">powered by</span>
            <AudioLines className="h-5 w-5" style={{ color: '#F5A32F' }} />
            <span className="text-sm font-bold text-duck-dark">soundcn</span>
          </a>
        </div>
      </div>
    </Widget>
  );
};
