import { useState, useEffect, useRef } from 'react'
import { useSearchParams } from 'react-router-dom'
import { Compass, Sparkles, Loader2, ListMusic, Search, Users, Clock, Disc3, TrendingUp } from 'lucide-react'
import { useAuth } from '../lib/auth'
import { getPlaylists, generateRecommendations, toggleSaveRecommendation, dislikeRecommendation, type PlaylistResponse, type RecommendationItem } from '../lib/api'
import RecommendationCard from '../components/RecommendationCard'

const DISCOVERY_MODES = [
  { id: 'discover', label: 'Discover', icon: Compass, description: 'General recommendations' },
  { id: 'sonic_twin', label: 'Sonic Twin', icon: Users, description: 'Underground artists who sound like your favorites' },
  { id: 'era_bridge', label: 'Era Bridge', icon: Clock, description: 'Classic artists who inspired your favorites' },
  { id: 'deep_cuts', label: 'Deep Cuts', icon: Disc3, description: 'B-sides and rarities from artists you know' },
  { id: 'rising', label: 'Rising', icon: TrendingUp, description: 'Under 50K listeners who fit your profile' },
] as const

const ADVENTUROUSNESS_LABELS: Record<number, string> = {
  1: 'Safe',
  2: 'Familiar',
  3: 'Balanced',
  4: 'Exploring',
  5: 'Adventurous',
}

export default function Discover() {
  const { user } = useAuth()
  const [searchParams] = useSearchParams()
  const [playlists, setPlaylists] = useState<PlaylistResponse[]>([])
  const [selectedPlaylist, setSelectedPlaylist] = useState<string>('')
  const [query, setQuery] = useState('')
  const [results, setResults] = useState<RecommendationItem[]>([])
  const [remaining, setRemaining] = useState<number | null>(null)
  const [discovering, setDiscovering] = useState(false)
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState('')
  const [bandcampMode, setBandcampMode] = useState(false)
  const [savingIds, setSavingIds] = useState<Set<string>>(new Set())
  const [dislikingIds, setDislikingIds] = useState<Set<string>>(new Set())
  const [mode, setMode] = useState('discover')
  const [adventurousness, setAdventurousness] = useState(3)
  const [excludeGenres, setExcludeGenres] = useState('')
  const [count, setCount] = useState(5)
  const resultsRef = useRef<HTMLDivElement>(null)

  useEffect(() => {
    const load = async () => {
      try {
        const data = await getPlaylists()
        setPlaylists(data)
        const preselected = searchParams.get('playlist')
        if (preselected && data.some((p) => p.id === preselected)) {
          setSelectedPlaylist(preselected)
        }
      } catch {
        // silent
      } finally {
        setLoading(false)
      }
    }
    load()
  }, [searchParams])

  const handleDiscover = async () => {
    if (!selectedPlaylist && !query.trim()) return
    setDiscovering(true)
    setError('')
    setResults([])

    try {
      const response = await generateRecommendations(
        selectedPlaylist || undefined,
        query.trim() || undefined,
        bandcampMode,
        mode,
        adventurousness,
        excludeGenres.trim() || undefined,
        count,
      )
      const recs = response.recommendations || []
      setResults(recs)
      setRemaining(response.remaining_this_week ?? null)
      // Scroll to results after render
      if (recs.length > 0) {
        setTimeout(() => resultsRef.current?.scrollIntoView({ behavior: 'smooth' }), 100)
      }
    } catch (err: any) {
      setError(
        err.response?.data?.detail || 'Failed to generate recommendations. Please try again.'
      )
    } finally {
      setDiscovering(false)
    }
  }

  const handleToggleSave = async (id: string) => {
    const sid = String(id)
    setSavingIds((prev) => new Set(prev).add(sid))
    try {
      const { saved } = await toggleSaveRecommendation(sid)
      setResults((prev) =>
        prev.map((r) => (String(r.id) === sid ? { ...r, saved } : r))
      )
    } catch {
      // silent
    } finally {
      setSavingIds((prev) => {
        const next = new Set(prev)
        next.delete(sid)
        return next
      })
    }
  }

  const handleDislike = async (id: string) => {
    const sid = String(id)
    setDislikingIds((prev) => new Set(prev).add(sid))
    try {
      const { disliked } = await dislikeRecommendation(sid)
      setResults((prev) =>
        prev.map((r) => (String(r.id) === sid ? { ...r, disliked } : r))
      )
    } catch {
      // silent
    } finally {
      setDislikingIds((prev) => {
        const next = new Set(prev)
        next.delete(sid)
        return next
      })
    }
  }

  if (loading) {
    return (
      <div className="flex items-center justify-center py-20">
        <Loader2 className="w-8 h-8 text-purple animate-spin" />
      </div>
    )
  }

  return (
    <div className="space-y-6">
      <div>
        <h1 className="text-2xl sm:text-3xl font-bold text-charcoal flex items-center gap-3">
          <Compass className="w-8 h-8 text-purple" />
          Discover
        </h1>
        <p className="text-charcoal-muted mt-1">
          Find new music based on your taste or a specific vibe
        </p>
      </div>

      {/* Discovery Modes */}
      <div className="flex flex-wrap gap-2">
        {DISCOVERY_MODES.map(({ id, label, icon: Icon, description }) => (
          <button
            key={id}
            onClick={() => setMode(id)}
            className={`inline-flex items-center gap-1.5 px-3 py-2 sm:px-4 sm:py-2.5 rounded-full text-xs sm:text-sm font-medium transition-all cursor-pointer border ${
              mode === id
                ? 'bg-purple text-white border-purple shadow-md shadow-purple/20'
                : 'bg-white text-charcoal-muted border-purple-100 hover:border-purple/30 hover:text-charcoal'
            }`}
            title={description}
          >
            <Icon className="w-4 h-4" />
            {label}
          </button>
        ))}
      </div>

      {/* Discovery Form */}
      <div className="bg-white rounded-2xl border border-purple-100 p-4 sm:p-6 space-y-4 sm:space-y-5">
        {/* Playlist Selector */}
        <div>
          <label className="block text-sm font-medium text-charcoal mb-2">
            <ListMusic className="w-4 h-4 inline mr-1.5" />
            Based on a playlist
          </label>
          <select
            value={selectedPlaylist}
            onChange={(e) => setSelectedPlaylist(e.target.value)}
            className="w-full px-4 py-3 bg-cream/50 border border-purple-100 rounded-xl text-charcoal focus:outline-none focus:ring-2 focus:ring-purple/30 focus:border-purple transition-colors text-sm appearance-none cursor-pointer"
          >
            <option value="">Select a playlist (optional)</option>
            {playlists.map((p) => (
              <option key={p.id} value={p.id}>
                {p.name} ({p.track_count} tracks)
              </option>
            ))}
          </select>
        </div>

        {/* Custom Query */}
        <div>
          <label className="block text-sm font-medium text-charcoal mb-2">
            <Search className="w-4 h-4 inline mr-1.5" />
            Or describe what you want
          </label>
          <textarea
            value={query}
            onChange={(e) => setQuery(e.target.value)}
            placeholder='e.g., "Upbeat indie rock with jangly guitars", "Dreamy synth-pop for late night drives", or just type artists/songs like "Radiohead, Tame Impala"'
            rows={3}
            className="w-full px-4 py-3 bg-cream/50 border border-purple-100 rounded-xl text-charcoal placeholder:text-charcoal-muted/40 focus:outline-none focus:ring-2 focus:ring-purple/30 focus:border-purple transition-colors text-sm resize-none"
          />
        </div>

        {/* Discovery Dial */}
        <div>
          <label className="block text-sm font-medium text-charcoal mb-3">
            Discovery dial
            <span className="ml-2 text-charcoal-muted font-normal">
              — {ADVENTUROUSNESS_LABELS[adventurousness]}
            </span>
          </label>
          <div className="relative">
            <input
              type="range"
              min={1}
              max={5}
              step={1}
              value={adventurousness}
              onChange={(e) => setAdventurousness(Number(e.target.value))}
              className="w-full h-2 bg-purple-100 rounded-full appearance-none cursor-pointer accent-purple"
            />
            <div className="flex justify-between mt-1.5 px-0.5">
              <span className="text-xs text-charcoal-muted">Safe</span>
              <span className="text-xs text-charcoal-muted">Balanced</span>
              <span className="text-xs text-charcoal-muted">Adventurous</span>
            </div>
          </div>
        </div>

        {/* Recommendation Count */}
        <div>
          <label className="block text-sm font-medium text-charcoal mb-3">
            How many recommendations
          </label>
          <div className="flex gap-2">
            {[5, 10, 15, 20].map((n) => (
              <button
                key={n}
                onClick={() => setCount(n)}
                className={`px-4 py-2 rounded-full text-sm font-medium transition-all cursor-pointer border ${
                  count === n
                    ? 'bg-purple text-white border-purple shadow-md shadow-purple/20'
                    : 'bg-white text-charcoal-muted border-purple-100 hover:border-purple/30 hover:text-charcoal'
                }`}
              >
                {n}
              </button>
            ))}
          </div>
        </div>

        {/* Block Genres */}
        <div>
          <label className="block text-sm font-medium text-charcoal mb-2">
            Exclude genres / moods
          </label>
          <input
            type="text"
            value={excludeGenres}
            onChange={(e) => setExcludeGenres(e.target.value)}
            placeholder="country, sad songs, metal"
            className="w-full px-4 py-3 bg-cream/50 border border-purple-100 rounded-xl text-charcoal placeholder:text-charcoal-muted/40 focus:outline-none focus:ring-2 focus:ring-purple/30 focus:border-purple transition-colors text-sm"
          />
        </div>


        {/* Remaining count */}
        {!user?.is_pro && (
          <p className="text-xs text-charcoal-muted flex items-center gap-1">
            <Sparkles className="w-3 h-3 text-amber-500" />
            {remaining !== null ? remaining : user?.daily_recommendations_remaining ?? 5} discoveries remaining this week
          </p>
        )}

        {error && (
          <div className="p-3 bg-red-50 border border-red-200 rounded-lg text-sm text-red-600">
            {error}
          </div>
        )}

        <button
          onClick={handleDiscover}
          disabled={discovering || (!selectedPlaylist && !query.trim())}
          className="w-full py-3.5 bg-gradient-to-r from-purple to-purple-dark text-white font-semibold rounded-xl hover:shadow-lg hover:shadow-purple/25 transition-all disabled:opacity-50 cursor-pointer border-none text-sm flex items-center justify-center gap-2"
        >
          {discovering ? (
            <>
              <Loader2 className="w-5 h-5 animate-spin" />
              Discovering new music...
            </>
          ) : (
            <>
              <Sparkles className="w-5 h-5" />
              Discover Music
            </>
          )}
        </button>
      </div>

      {/* Results */}
      {results.length > 0 && (
        <div ref={resultsRef}>
          <h2 className="text-lg font-semibold text-charcoal mb-4">
            Your Recommendations ({results.length})
          </h2>
          <div className="space-y-3">
            {results.map((rec) => (
              <RecommendationCard
                key={rec.id}
                recommendation={rec}
                onToggleSave={handleToggleSave}
                onDislike={handleDislike}
                saving={savingIds.has(String(rec.id))}
                disliking={dislikingIds.has(String(rec.id))}
              />
            ))}
          </div>
        </div>
      )}

      {!discovering && results.length === 0 && !error && (selectedPlaylist || query.trim()) && (
        <p className="text-charcoal-muted text-sm text-center py-4">
          Click "Discover Music" to get recommendations
        </p>
      )}
    </div>
  )
}
