import { useState, useEffect, useRef } from 'react';
import { 
  Search, BookOpen, Loader2, X, Sparkles, LayoutGrid, 
  CheckCircle, Moon, Sun, Info, Bookmark, ArrowLeft, Users
} from 'lucide-react';
import { api } from './api';
import { Loader } from './Loader';
import { BookCover } from './BookCover';
import { BookCard } from './BookCard';
import { DEMO_PERSONAS } from './data/personas';
import type { RecommendationResult, BookCluster } from './types';

function App() {
  const [query, setQuery] = useState('');
  const [results, setResults] = useState<RecommendationResult[]>([]);
  const [loading, setLoading] = useState(false);
  const [longLoading, setLongLoading] = useState(false); 
  const [hasSearched, setHasSearched] = useState(false);
  
  // Modal State
  const [selectedResult, setSelectedResult] = useState<RecommendationResult | null>(null);
  const [historyStack, setHistoryStack] = useState<RecommendationResult[]>([]);
  const [explanation, setExplanation] = useState<{ summary: string; details: Record<string, number> } | null>(null);
  const [explaining, setExplaining] = useState(false);
  const [showAbout, setShowAbout] = useState(false);
  const modalRef = useRef<HTMLDivElement>(null);
  
  // Related Books State
  const [relatedBooks, setRelatedBooks] = useState<RecommendationResult[]>([]);
  const [loadingRelated, setLoadingRelated] = useState(false);

  // Dynamic Clusters State
  const [clusters, setClusters] = useState<BookCluster[]>([]);
  const [loadingClusters, setLoadingClusters] = useState(true);

  // Toast State
  const [toast, setToast] = useState<{ message: string; visible: boolean } | null>(null);

  // Settings / Theme State
  const [darkMode, setDarkMode] = useState(false);
  
  // Personalization / History State
  const [readHistory, setReadHistory] = useState<string[]>(() => {
      try {
          return JSON.parse(localStorage.getItem('bookfinder_read_history') || '[]');
      } catch {
          return [];
      }
  });

  useEffect(() => {
    if (selectedResult && modalRef.current) {
      modalRef.current.scrollTop = 0;
    }
  }, [selectedResult]);

  useEffect(() => {
    const savedTheme = localStorage.getItem('bookfinder_theme_mode');
    if (savedTheme) {
        setDarkMode(savedTheme === 'dark');
    } else if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
        setDarkMode(true);
    }
  }, []);

  useEffect(() => {
    localStorage.setItem('bookfinder_theme_mode', darkMode ? 'dark' : 'light');
    if (darkMode) {
      document.documentElement.classList.add('dark');
    } else {
      document.documentElement.classList.remove('dark');
    }
  }, [darkMode]);

  useEffect(() => {
    localStorage.setItem('bookfinder_read_history', JSON.stringify(readHistory));
  }, [readHistory]);

  const toggleReadBook = (title: string) => {
      setReadHistory(prev => {
          if (prev.includes(title)) {
              showToast("Removed from library");
              return prev.filter(t => t !== title);
          } else {
              showToast("Added to library");
              return [...prev, title];
          }
      });
      triggerHaptic();
  };

  const handlePersonalize = async () => {
      if (readHistory.length === 0) {
          showToast("Mark some books as read first!");
          return;
      }
      triggerHaptic();
      setLoading(true);
      setHasSearched(true);
      setResults([]);
      setQuery("✨ Selected for you");
      
      try {
          const data = await api.recommendPersonalized(readHistory);
          setResults(data);
      } catch (err) {
          console.error(err);
          showToast("Failed to personalize. Try again.");
      } finally {
          setLoading(false);
      }
  };

  const handlePersonaSelect = (persona: typeof DEMO_PERSONAS[0]) => {
    triggerHaptic();
    setReadHistory(persona.history);
    showToast(`Switched to ${persona.name} mode`);
    
    setLoading(true);
    setHasSearched(true);
    setResults([]);
    setQuery(`👤 Demo: ${persona.name}`);
    
    api.recommendPersonalized(persona.history)
       .then(setResults)
       .catch(err => {
           console.error(err);
           showToast("Failed to load persona.");
       })
       .finally(() => setLoading(false));
  };

  const toggleTheme = async (e: React.MouseEvent) => {
    const isDark = !darkMode;
    if (!(document as any).startViewTransition) {
      setDarkMode(isDark);
      return;
    }
    const x = e.clientX;
    const y = e.clientY;
    const endRadius = Math.hypot(Math.max(x, window.innerWidth - x), Math.max(y, window.innerHeight - y));
    const transition = (document as any).startViewTransition(() => setDarkMode(isDark));
    await transition.ready;
    const clipPath = [`circle(0px at ${x}px ${y}px)`, `circle(${endRadius}px at ${x}px ${y}px)`];
    document.documentElement.animate(
      { clipPath: isDark ? clipPath : [...clipPath].reverse() },
      { duration: 500, easing: 'ease-in-out', pseudoElement: isDark ? '::view-transition-new(root)' : '::view-transition-old(root)' }
    );
  };

  const triggerHaptic = () => {
    if (typeof navigator !== 'undefined' && navigator.vibrate) {
      navigator.vibrate(10);
    }
  };

  useEffect(() => {
    const fetchClusters = async () => {
      try {
        const data = await api.getClusters();
        setClusters(data.slice(0, 6));
      } catch (err) {
        console.error("Failed to fetch clusters", err);
      } finally {
        setLoadingClusters(false);
      }
    };
    fetchClusters();
  }, []);

  const showToast = (message: string) => {
    setToast({ message, visible: true });
    setTimeout(() => setToast(null), 3000);
  };

  const handleSearch = async (e?: React.FormEvent) => {
    if (e) e.preventDefault();
    if (!query.trim()) return;
    triggerHaptic();
    setLoading(true);
    setLongLoading(false);
    setHasSearched(true);
    setResults([]); 
    const timer = setTimeout(() => setLongLoading(true), 3000);
    try {
      const data = await api.recommendByQuery(query);
      setResults(data);
    } catch (err) {
      console.error(err);
    } finally {
      clearTimeout(timer);
      setLoading(false);
      setLongLoading(false);
    }
  };

  const handleQuickSearch = (text: string) => {
    setQuery(text);
    triggerHaptic();
    setLoading(true);
    setLongLoading(false);
    setHasSearched(true);
    setResults([]);
    const timer = setTimeout(() => setLongLoading(true), 3000);
    api.recommendByQuery(text).then(setResults).catch(console.error).finally(() => {
        clearTimeout(timer);
        setLoading(false);
        setLongLoading(false);
    });
  };

  const handleFeedback = async (bookId: string, type: 'positive' | 'negative') => {
      triggerHaptic();
      try {
        await api.submitFeedback(query, bookId, type);
        showToast(type === 'positive' ? "Thanks! We'll show more like this." : "Thanks! We'll tune our results.");
      } catch (err) {
        console.error(err);
      }
  };

  const handleReadMore = async (result: RecommendationResult, isDrillingDown = false) => {
    triggerHaptic();
    if (isDrillingDown && selectedResult) {
        setHistoryStack(prev => [...prev, selectedResult]);
    } else if (!isDrillingDown) {
        setHistoryStack([]);
    }
    setSelectedResult(result);
    setExplaining(true);
    setExplanation(null);
    setRelatedBooks([]);
    setLoadingRelated(true);
    try {
      const [expl, related] = await Promise.allSettled([
        api.explainRecommendation(query || result.book.title, result.book, result.similarity_score),
        api.getRelatedBooks(result.book.title)
      ]);
      if (expl.status === 'fulfilled') setExplanation(expl.value);
      if (related.status === 'fulfilled') setRelatedBooks(related.value);
    } catch (err) {
      console.error("Failed to fetch details", err);
    } finally {
      setExplaining(false);
      setLoadingRelated(false);
    }
  };
  
  const handleBack = () => {
      triggerHaptic();
      if (historyStack.length > 0) {
          const prev = historyStack[historyStack.length - 1];
          setHistoryStack(curr => curr.slice(0, -1));
          setSelectedResult(prev);
          setRelatedBooks([]);
          setExplanation(null);
          setLoadingRelated(true);
          setExplaining(true);
          Promise.allSettled([
            api.explainRecommendation(query || prev.book.title, prev.book, prev.similarity_score),
            api.getRelatedBooks(prev.book.title)
          ]).then(([expl, related]) => {
             if (expl.status === 'fulfilled') setExplanation(expl.value);
             if (related.status === 'fulfilled') setRelatedBooks(related.value);
             setExplaining(false);
             setLoadingRelated(false);
          });
      }
  };

  const closeModal = () => {
    setSelectedResult(null);
    setHistoryStack([]);
    setExplanation(null);
    setRelatedBooks([]);
  };

  const handleClusterClick = (clusterName: string) => {
    triggerHaptic();
    setQuery(clusterName);
    setLoading(true);
    setHasSearched(true);
    setResults([]);
    api.recommendByQuery(clusterName).then(setResults).catch(console.error).finally(() => setLoading(false));
  };

  return (
    <div className={`min-h-screen font-sans selection:bg-indigo-500 selection:text-white transition-colors duration-300 ${darkMode ? 'bg-zinc-950 text-zinc-100' : 'bg-zinc-50 text-zinc-900'}`}>
      
      <div className="fixed inset-0 -z-10 bg-zinc-50 dark:bg-zinc-950 transition-colors duration-500" />
      <div className="fixed inset-0 -z-10 bg-noise opacity-[0.04] dark:opacity-[0.06] pointer-events-none mix-blend-overlay" />
      <div className="fixed inset-0 -z-10 bg-dot-pattern pointer-events-none" />
      <div className="fixed inset-0 -z-10 bg-gradient-to-br from-rose-100/40 via-white to-indigo-100/40 dark:from-indigo-950/30 dark:via-zinc-950 dark:to-purple-950/30 pointer-events-none" />

      {toast && (
        <div className="fixed bottom-6 right-6 bg-zinc-900 dark:bg-zinc-800 text-white px-4 py-3 rounded-xl shadow-2xl flex items-center gap-3 animate-slide-up z-[60] border border-zinc-800 dark:border-zinc-700">
          <CheckCircle className="w-5 h-5 text-green-400" />
          <span className="text-sm font-medium">{toast.message}</span>
        </div>
      )}

      <header className="sticky top-0 z-30 border-b border-zinc-200/50 dark:border-zinc-800/50 bg-white/70 dark:bg-zinc-950/70 backdrop-blur-xl">
        <div className="max-w-3xl mx-auto px-6 h-16 flex items-center justify-between">
                    <div className="flex items-center gap-3 group cursor-pointer" onClick={() => setActiveView('search')}>
                      <div className="relative">
                        <div className="absolute -inset-1 bg-indigo-500/20 rounded-full blur-sm group-hover:bg-indigo-500/30 transition-colors"></div>
                        <BookOpen className="w-8 h-8 text-indigo-600 dark:text-indigo-400 relative" />
                      </div>
                      <span className="text-zinc-900 dark:text-white font-serif text-xl tracking-normal">Serendipity</span>
                    </div>
          
          <div className="flex items-center gap-2">
             <button onClick={toggleTheme} className="p-2 rounded-full hover:bg-black/5 dark:hover:bg-white/10 transition-colors text-zinc-500 dark:text-zinc-400">
                {darkMode ? <Sun className="w-5 h-5" /> : <Moon className="w-5 h-5" />}
             </button>
             <button onClick={() => setShowAbout(true)} className="p-2 ml-2 rounded-full hover:bg-black/5 dark:hover:bg-white/10 transition-colors text-zinc-500 dark:text-zinc-400">
                <Info className="w-5 h-5" />
             </button>
          </div>
        </div>
      </header>

      <main className="max-w-3xl mx-auto px-6 pb-24 relative z-10">
        <div className={`transition-all duration-700 ease-out ${hasSearched ? 'py-10' : 'py-28'}`}>
          {!hasSearched && (
            <div className="text-center mb-10 animate-fade-in">
              <h1 className="text-5xl sm:text-7xl font-black tracking-tighter mb-6 text-zinc-900 dark:text-white font-serif">
                Find your next<br/>
                <span className="text-indigo-600 dark:text-indigo-500 italic">obsession.</span>
              </h1>
              <p className="text-lg max-w-md mx-auto text-zinc-500 dark:text-zinc-400 leading-relaxed font-medium">
                Describe the vibe, plot, or character you're looking for.
              </p>
            </div>
          )}
          
          <form onSubmit={handleSearch} className="relative max-w-xl mx-auto z-10">
            <input
              type="text"
              value={query}
              onChange={(e) => setQuery(e.target.value)}
              placeholder="e.g. A sci-fi thriller about AI consciousness..."
              className="relative w-full bg-white dark:bg-zinc-900 border-2 border-zinc-200 dark:border-zinc-800 focus:border-indigo-500 dark:focus:border-indigo-500 rounded-full py-4 pl-6 pr-24 text-lg outline-none transition-all placeholder:text-zinc-400 dark:placeholder:text-zinc-600 shadow-xl shadow-zinc-200/50 dark:shadow-black/50 text-zinc-900 dark:text-white"
              autoFocus
            />
            {query && (
              <button
                type="button"
                onClick={() => { setQuery(''); triggerHaptic(); setResults([]); }}
                className="absolute right-14 top-1/2 -translate-y-1/2 p-2 text-zinc-400 hover:text-zinc-600 dark:hover:text-zinc-200 transition-colors"
              >
                <X className="w-5 h-5" />
              </button>
            )}
            <button 
              type="submit"
              disabled={loading || !query.trim()}
              className="absolute right-2 top-2 p-2.5 bg-indigo-600 text-white rounded-full hover:bg-indigo-700 disabled:opacity-50 disabled:hover:bg-indigo-600 transition-all active:scale-90 shadow-lg shadow-indigo-500/30"
              onClick={triggerHaptic}
            >
              {loading ? <Loader2 className="w-5 h-5 animate-spin" /> : <Search className="w-5 h-5" />}
            </button>
          </form>
          
          {loading && longLoading && (
            <div className="text-center mt-4 animate-fade-in">
              <p className="text-sm font-medium text-indigo-600 dark:text-indigo-400 flex items-center justify-center gap-2">
                <Loader2 className="w-3 h-3 animate-spin" />
                Waking up... this might take a moment 😴
              </p>
            </div>
          )}

          {!hasSearched && !loading && (
            <div className="mt-8 flex flex-col items-center gap-6 animate-fade-in animation-delay-200">
                <div className="flex flex-wrap justify-center gap-3">
                {[
                    "Cyberpunk noir detective",
                    "Cozy cottagecore mystery",
                    "Space opera with politics",
                    "Psychological horror 1920s"
                ].map((prompt) => (
                    <button key={prompt} onClick={() => handleQuickSearch(prompt)} className="px-4 py-2 rounded-full text-sm font-medium bg-white dark:bg-zinc-900 border border-zinc-200 dark:border-zinc-800 text-zinc-600 dark:text-zinc-400 hover:border-indigo-400 dark:hover:border-indigo-500 hover:text-indigo-600 dark:hover:text-indigo-400 transition-all shadow-sm hover:shadow-md active:scale-95">
                    ✨ {prompt}
                    </button>
                ))}
                </div>

                {/* Demo Personas */}
                <div className="w-full max-w-2xl mt-4 p-6 bg-zinc-50/50 dark:bg-zinc-900/30 rounded-3xl border border-zinc-100 dark:border-zinc-800/50 backdrop-blur-sm">
                    <div className="flex items-center justify-center gap-2 text-xs uppercase tracking-widest font-bold mb-4 text-zinc-400 dark:text-zinc-600">
                        <Users className="w-4 h-4" />
                        Try a Demo Persona
                    </div>
                    <div className="grid grid-cols-2 sm:grid-cols-4 gap-3">
                        {DEMO_PERSONAS.map(persona => (
                            <button
                                key={persona.id}
                                onClick={() => handlePersonaSelect(persona)}
                                className="flex flex-col items-center gap-2 p-3 bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 hover:border-indigo-400 dark:hover:border-indigo-500 hover:shadow-lg transition-all active:scale-95 group"
                            >
                                <span className="text-2xl group-hover:scale-110 transition-transform">{persona.emoji}</span>
                                <div className="text-center">
                                    <div className="text-xs font-bold text-zinc-900 dark:text-zinc-100">{persona.name}</div>
                                    <div className="text-[10px] text-zinc-500 dark:text-zinc-500 leading-tight mt-1 line-clamp-2">{persona.description}</div>
                                </div>
                            </button>
                        ))}
                    </div>
                </div>

                {/* Personalization Trigger */}
                {readHistory.length > 0 && (
                    <button 
                        onClick={handlePersonalize}
                        className="mt-2 flex items-center gap-2 px-6 py-3 bg-gradient-to-r from-indigo-600 to-purple-600 text-white rounded-full font-bold text-sm shadow-xl shadow-indigo-500/20 hover:scale-105 active:scale-95 transition-all"
                    >
                        <Bookmark className="w-4 h-4 fill-white/20" />
                        Recommend based on my {readHistory.length} reads
                    </button>
                )}
            </div>
          )}

          {!hasSearched && (
            <div className="mt-20 animate-slide-up animation-delay-500">
              <div className="flex items-center justify-center gap-2 text-xs uppercase tracking-widest font-bold mb-8 text-zinc-400 dark:text-zinc-600">
                 <LayoutGrid className="w-4 h-4" />
                 Curated Collections
              </div>
              
              {loadingClusters ? (
                <div className="grid grid-cols-2 sm:grid-cols-3 gap-4">
                   {[1,2,3,4,5,6].map(i => (
                     <div key={i} className="h-32 bg-white dark:bg-zinc-900 rounded-2xl border border-zinc-200 dark:border-zinc-800 animate-pulse" />
                   ))}
                </div>
              ) : (
                <div className="grid grid-cols-2 sm:grid-cols-3 gap-4">
                  {clusters.map(cluster => (
                    <button 
                      key={cluster.id}
                      onClick={() => handleClusterClick(cluster.name)}
                      className="text-left p-4 bg-white dark:bg-zinc-900/50 hover:bg-zinc-50 dark:hover:bg-zinc-800 border border-zinc-200 dark:border-zinc-800 hover:border-indigo-300 dark:hover:border-indigo-500/50 transition-all rounded-2xl group active:scale-95 duration-200 shadow-sm hover:shadow-md"
                    >
                      <h3 className="font-bold text-zinc-800 dark:text-zinc-200 group-hover:text-indigo-600 dark:group-hover:text-indigo-400 truncate transition-colors">{cluster.name}</h3>
                      <p className="text-xs text-zinc-500 dark:text-zinc-500 mt-1 font-medium">{cluster.size} books</p>
                      
                      <div className="flex mt-4 -space-x-3 overflow-hidden px-1 pb-1">
                        {cluster.top_books.slice(0, 3).map((book, i) => (
                          <div key={book.id} className={`w-8 h-12 bg-zinc-200 dark:bg-zinc-800 rounded-sm shadow-md border border-white/50 dark:border-zinc-700 relative z-${3-i} transform transition-transform group-hover:-translate-y-1 duration-300 overflow-hidden`} style={{transitionDelay: `${i*50}ms`}}>
                             <BookCover src={book.cover_image_url} title={book.title} author={book.authors[0]} className="w-full h-full" />
                          </div>
                        ))}
                      </div>
                    </button>
                  ))}
                </div>
              )}
            </div>
          )}
        </div>

        <div className="space-y-6 min-h-[50vh]">
          {loading && results.length === 0 ? (
             <div className="animate-fade-in pt-10">
                <Loader />
             </div>
          ) : (
            results.map((result) => (
              <BookCard 
                key={result.book.id} 
                result={result} 
                isRead={readHistory.includes(result.book.title)}
                onToggleRead={toggleReadBook}
                onClick={() => handleReadMore(result)} 
                onFeedback={handleFeedback} 
              />
            ))
          )}
        </div>

        {hasSearched && results.length === 0 && !loading && (
          <div className="text-center text-zinc-400 dark:text-zinc-600 py-12">
            No books found matching that description.
          </div>
        )}
      </main>

      {selectedResult && (
        <div className="fixed inset-0 z-50 flex items-center justify-center p-4 sm:p-6">
          <div className="absolute inset-0 bg-zinc-900/60 dark:bg-black/80 backdrop-blur-sm transition-opacity" onClick={closeModal} />
          <div ref={modalRef} className="bg-white dark:bg-zinc-900 rounded-3xl shadow-2xl w-full max-w-2xl max-h-[90vh] overflow-y-auto relative animate-slide-up z-50 no-scrollbar border border-zinc-200 dark:border-zinc-800">
            <button onClick={() => { triggerHaptic(); closeModal(); }} className="absolute right-4 top-4 p-2 bg-white/80 dark:bg-black/50 backdrop-blur hover:bg-zinc-100 dark:hover:bg-zinc-800 text-zinc-500 dark:text-zinc-400 rounded-full transition-colors z-10 shadow-sm">
              <X className="w-5 h-5" />
            </button>
            {historyStack.length > 0 && (
                <button onClick={handleBack} className="absolute left-4 top-4 p-2 bg-white/80 dark:bg-black/50 backdrop-blur hover:bg-zinc-100 dark:hover:bg-zinc-800 text-zinc-500 dark:text-zinc-400 rounded-full transition-colors z-10 shadow-sm flex items-center gap-1 pr-3">
                    <ArrowLeft className="w-5 h-5" />
                    <span className="text-xs font-bold">Back</span>
                </button>
            )}
            <div className="grid sm:grid-cols-[220px_1fr] gap-0 sm:gap-8">
               <div className="bg-zinc-100 dark:bg-zinc-800 h-64 sm:h-auto sm:aspect-[2/3] relative overflow-hidden">
                  <BookCover src={selectedResult.book.cover_image_url} title={selectedResult.book.title} author={selectedResult.book.authors[0]} className="w-full h-full" />
                  <div className="absolute inset-0 bg-gradient-to-t from-black/60 to-transparent sm:hidden"></div>
                  <h2 className="absolute bottom-4 left-4 right-4 text-2xl font-bold font-serif text-white sm:hidden leading-tight shadow-black drop-shadow-md">{selectedResult.book.title}</h2>
               </div>
               <div className="p-6 sm:pl-0 sm:py-8 space-y-6">
                  <div className="hidden sm:block">
                    <h2 className="text-3xl sm:text-4xl font-bold font-serif leading-tight mb-2 text-zinc-900 dark:text-white">{selectedResult.book.title}</h2>
                    <p className="text-lg text-zinc-500 dark:text-zinc-400 font-medium">by {selectedResult.book.authors.join(', ')}</p>
                  </div>
                  <div className="prose prose-zinc dark:prose-invert prose-sm max-w-none leading-relaxed">
                    <p>{selectedResult.book.description}</p>
                  </div>
                  <div className="bg-indigo-50/50 dark:bg-indigo-900/20 rounded-2xl p-5 border border-indigo-100 dark:border-indigo-500/20">
                    <div className="flex items-center gap-2 mb-3 text-indigo-600 dark:text-indigo-400 font-bold text-xs uppercase tracking-widest">
                      <Sparkles className="w-4 h-4" />
                      Why this match?
                    </div>
                    {explaining ? (
                      <div className="flex items-center gap-2 text-indigo-400 dark:text-indigo-300 text-sm font-medium">
                        <Loader2 className="w-4 h-4 animate-spin" />
                        Reading your mind...
                      </div>
                    ) : explanation ? (
                      <div className="space-y-3">
                        <p className="text-sm text-zinc-800 dark:text-zinc-200 font-medium leading-relaxed">{explanation.summary}</p>
                        <div className="flex flex-wrap gap-2">
                          {Object.entries(explanation.details).map(([key, val]) => (
                            <span key={key} className="text-[10px] font-bold uppercase bg-white dark:bg-zinc-800 border border-indigo-100 dark:border-indigo-500/30 px-2 py-1 rounded-md text-indigo-600 dark:text-indigo-300 shadow-sm">
                              {key} {val}%
                            </span>
                          ))}
                        </div>
                      </div>
                    ) : (
                       <p className="text-sm text-red-400">Could not generate explanation.</p>
                    )}
                  </div>
                  <div className="pt-4 flex flex-col sm:flex-row gap-3">
                    <a href={`https://www.goodreads.com/search?q=${encodeURIComponent(selectedResult.book.title + ' ' + selectedResult.book.authors.join(', '))}`} target="_blank" rel="noopener noreferrer" className="inline-flex items-center gap-2 px-6 py-3 bg-white dark:bg-zinc-800 text-zinc-900 dark:text-white border border-zinc-200 dark:border-zinc-700 font-bold rounded-full hover:bg-zinc-50 dark:hover:bg-zinc-700 hover:scale-105 transition-all active:scale-95 flex-1 justify-center shadow-sm" onClick={triggerHaptic}>
                      <BookOpen className="w-4 h-4" />
                      Goodreads
                    </a>
                    <a href={`https://www.google.com/search?q=${encodeURIComponent(selectedResult.book.title + ' by ' + selectedResult.book.authors.join(', '))}`} target="_blank" rel="noopener noreferrer" className="inline-flex items-center gap-2 px-6 py-3 bg-zinc-900 dark:bg-indigo-600 text-white font-bold rounded-full hover:bg-black dark:hover:bg-indigo-700 hover:scale-105 transition-all active:scale-95 flex-1 justify-center shadow-xl shadow-zinc-900/20 dark:shadow-indigo-500/30" onClick={triggerHaptic}>
                      <Search className="w-4 h-4" />
                      Google
                    </a>
                  </div>
                  <div className="pt-8 border-t border-dashed border-zinc-200 dark:border-zinc-800">
                    <h3 className="text-xs font-bold text-zinc-400 dark:text-zinc-500 mb-4 uppercase tracking-widest">You might also like</h3>
                    {loadingRelated ? (
                        <div className="flex gap-4">
                            {[1, 2, 3].map(i => (
                                <div key={i} className="w-32 h-48 bg-zinc-100 dark:bg-zinc-800 rounded-xl animate-pulse" />
                            ))}
                        </div>
                    ) : (
                        <div className="grid grid-cols-2 sm:grid-cols-3 gap-4">
                            {relatedBooks.map(rel => (
                                <div key={rel.book.id} onClick={() => handleReadMore(rel)} className="group cursor-pointer active:scale-95 transition-transform">
                                    <div className="aspect-[2/3] bg-zinc-100 dark:bg-zinc-800 rounded-xl overflow-hidden mb-2 relative shadow-sm group-hover:shadow-md transition-all border border-zinc-100 dark:border-zinc-700">
                                        <BookCover src={rel.book.cover_image_url} title={rel.book.title} author={rel.book.authors[0]} className="w-full h-full group-hover:scale-105 transition-transform duration-500" />
                                    </div>
                                    <h4 className="text-xs font-bold leading-tight text-zinc-800 dark:text-zinc-200 group-hover:text-indigo-600 dark:group-hover:text-indigo-400 transition-colors line-clamp-1">{rel.book.title}</h4>
                                    <p className="text-[10px] text-zinc-400 dark:text-zinc-500 mt-0.5 truncate">{rel.book.authors[0]}</p>
                                </div>
                            ))}
                        </div>
                    )}
                  </div>
               </div>
            </div>
          </div>
        </div>
      )}

      {showAbout && (
        <div className="fixed inset-0 z-50 flex items-center justify-center p-4">
          <div className="absolute inset-0 bg-zinc-900/60 dark:bg-black/80 backdrop-blur-sm transition-opacity" onClick={() => setShowAbout(false)} />
          <div className="bg-white dark:bg-zinc-900 rounded-3xl shadow-2xl w-full max-w-lg max-h-[90vh] overflow-y-auto relative animate-slide-up z-50 no-scrollbar border border-zinc-200 dark:border-zinc-800">
            <button onClick={() => { triggerHaptic(); setShowAbout(false); }} className="absolute right-4 top-4 p-2 bg-white/80 dark:bg-black/50 backdrop-blur hover:bg-zinc-100 dark:hover:bg-zinc-800 text-zinc-500 dark:text-zinc-400 rounded-full transition-colors z-10 shadow-sm">
              <X className="w-5 h-5" />
            </button>
            <div className="p-6 sm:p-8 space-y-6">
              <h3 className="text-2xl font-bold text-zinc-900 dark:text-white">About Serendipity</h3>
              <div className="space-y-4 text-zinc-600 dark:text-zinc-300 leading-relaxed">
                <p>
                  Serendipity is an intelligent book discovery interface powered by the <strong>DeepShelf Engine</strong>.
                </p>
                <p>
                  Unlike traditional keyword search, DeepShelf uses semantic vector embeddings to understand the <em>meaning</em> and <em>feeling</em> of your request. It connects you with books that match your specific wavelength, even if they don't share a single keyword.
                </p>
              </div>
              <div className="space-y-3">
                <h4 className="text-lg font-bold text-zinc-800 dark:text-zinc-200">How it works:</h4>
                <ul className="list-disc list-inside text-zinc-600 dark:text-zinc-300 space-y-1">
                  <li><strong>Semantic Search:</strong> Understands the meaning and context of your queries.</li>
                  <li><strong>Vector Embeddings:</strong> DeepShelf maps books and queries into a high-dimensional vector space.</li>
                  <li><strong>Neural Retrieval:</strong> Finds the nearest neighbors to your thought in the library of 100,000+ books.</li>
                </ul>
              </div>
              <p className="text-zinc-600 dark:text-zinc-300 leading-relaxed">
                Describe your ideal read and let Serendipity uncover your next literary obsession!
              </p>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

export default App;