/**
 * @license
 * SPDX-License-Identifier: Apache-2.0
 */

import React, { useState, useMemo } from 'react';
import { motion, AnimatePresence } from 'motion/react';
import { X } from 'lucide-react';

// Components
import { Sidebar } from './components/Sidebar';
import { NotebooksView } from './components/NotebooksView';
import { AgentsView } from './components/AgentsView';
import { SettingsView } from './components/SettingsView';
import { TrashView } from './components/TrashView';
import { BrainstormView } from './components/BrainstormView/BrainstormView';
import { InsightsView } from './components/InsightsView';
import { TemporalView } from './components/TemporalView';
import { AISidebar } from './components/AISidebar';
import { SlashMenu } from './components/SlashMenu';
import { LandingPage } from './components/LandingPage';
import { LandingPageV2 } from './components/LandingPageV2';
import { LandingPageV3 } from './components/LandingPageV3';
import { AuthPage } from './components/AuthPage';
import { SearchModal } from './components/SearchModal';
import { ClipperSimulator } from './components/ClipperSimulator';
import { GraphKnowledgeMap } from './components/GraphKnowledgeMap';
import { RevisionView } from './components/RevisionView';

// Data & Services
import { CARNETS, ALL_NOTES } from './constants';
import { generateFlashcardsForNote } from './services/geminiService';
import { NavigationView, SettingsTab, AITab, AITone, Carnet, Note, BrainstormIdea, NoteAccessLog, Flashcard } from './types';

export default function App() {
  const [showLanding, setShowLanding] = useState(() => {
    // Check if user has already "entered" the app once in this session
    return !sessionStorage.getItem('momento-entered');
  });
  const [landingVersion, setLandingVersion] = useState<'v1' | 'v2' | 'v3'>('v1');
  const [showAuth, setShowAuth] = useState(false);
  const [authMode, setAuthMode] = useState<'login' | 'register'>('login');
  const [isAuthenticated, setIsAuthenticated] = useState(false);
  const [activeView, setActiveView] = useState<NavigationView>('notebooks');
  const [activeSettingsTab, setActiveSettingsTab] = useState<SettingsTab>('general');
  const [selectedAgentId, setSelectedAgentId] = useState<string | null>(null);
  const [isDarkMode, setIsDarkMode] = useState(false);
  const [carnets, setCarnets] = useState<Carnet[]>(CARNETS);
  const [notes, setNotes] = useState<Note[]>(ALL_NOTES);
  const [accessLogs, setAccessLogs] = useState<NoteAccessLog[]>([
    // Note n1: 14-day cycle
    { noteId: 'n1', accessedAt: new Date(Date.now() - 70 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
    { noteId: 'n1', accessedAt: new Date(Date.now() - 56 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
    { noteId: 'n1', accessedAt: new Date(Date.now() - 42 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
    { noteId: 'n1', accessedAt: new Date(Date.now() - 28 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
    { noteId: 'n1', accessedAt: new Date(Date.now() - 14 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
    { noteId: 'n1', accessedAt: new Date(Date.now() - 1 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
    
    // Note n2: 7-day cycle
    { noteId: 'n2', accessedAt: new Date(Date.now() - 35 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
    { noteId: 'n2', accessedAt: new Date(Date.now() - 28 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
    { noteId: 'n2', accessedAt: new Date(Date.now() - 21 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
    { noteId: 'n2', accessedAt: new Date(Date.now() - 14 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
    { noteId: 'n2', accessedAt: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
    { noteId: 'n2', accessedAt: new Date(Date.now() - 2 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },

    // Note n3: 3-day cycle (frequent check)
    { noteId: 'n3', accessedAt: new Date(Date.now() - 12 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
    { noteId: 'n3', accessedAt: new Date(Date.now() - 9 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
    { noteId: 'n3', accessedAt: new Date(Date.now() - 6 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
    { noteId: 'n3', accessedAt: new Date(Date.now() - 3 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
    { noteId: 'n3', accessedAt: new Date(Date.now() - 1 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
  ]);

  const logNoteAccess = (noteId: string, action: 'view' | 'edit' | 'search_hit' = 'view') => {
    const newLog: NoteAccessLog = {
      noteId,
      accessedAt: new Date().toISOString(),
      action
    };
    setAccessLogs(prev => [...prev, newLog]);
  };

  const [activeCarnetId, setActiveCarnetId] = useState('4');
  const [activeNoteId, setActiveNoteId] = useState<string | null>(null);
  const [brainstormSeed, setBrainstormSeed] = useState<string | null>(null);
  const [accentColor, setAccentColor] = useState(() => {
    return localStorage.getItem('momento-accent-color') || '#A47148';
  });

  // Flashcards state with beautiful architectural starter deck
  const [flashcards, setFlashcards] = useState<Flashcard[]>(() => {
    const stored = localStorage.getItem('momento-flashcards');
    if (stored) {
      try {
        return JSON.parse(stored);
      } catch (e) {
        console.error("Failed to parse stored flashcards:", e);
      }
    }
    // Beautiful default seeds for 'n1' (Grid Systems & Geometry)
    const SEEDS: Flashcard[] = [
      {
        id: 'f1',
        noteId: 'n1',
        question: 'Quel est l’intérêt primordial des trames géométriques en conception spatiale ?',
        answer: 'Elles structurent l’espace bâti en créant un sens d\'ordre, de rythme, et d\'harmonie de proportions esthétiques dans l\'environnement, facilitant la lisibilité de la structure.',
        intervalDays: 1,
        nextReviewDate: new Date().toISOString(), // Due today
        easeFactor: 2.5,
        mastered: false
      },
      {
        id: 'f2',
        noteId: 'n1',
        question: 'En quoi l’approche dynamique paramétrique déforme-t-elle les grilles de construction traditionnelles ?',
        answer: 'Par l\'utilisation d\'algorithmes mathématiques de déformation réactifs à des ensembles de données environnementales pour créer des géométries fluides mais structurellement ordonnées.',
        intervalDays: 3,
        nextReviewDate: new Date(Date.now() + 1000 * 60 * 60 * 24 * 3).toISOString(), // Due soon
        easeFactor: 2.5,
        mastered: true
      },
      {
        id: 'f3',
        noteId: 'n1',
        question: 'Quelle est la particularité de l’intégration de la lumière comme matériau d’espace ?',
        answer: 'La soustraction du superflu permet aux reflets et à la diffraction lumineuse de créer des profondeurs visuelles changeantes sans surcharger l\'aménagement matériel.',
        intervalDays: 1,
        nextReviewDate: new Date().toISOString(), // Due today
        easeFactor: 2.4,
        mastered: false
      }
    ];
    return SEEDS;
  });

  const [isGeneratingFlashcards, setIsGeneratingFlashcards] = useState(false);
  const [activeReviewDeckId, setActiveReviewDeckId] = useState<string | null>(null);
  const [toast, setToast] = useState<{ show: boolean; message: string }>({ show: false, message: '' });

  React.useEffect(() => {
    document.documentElement.style.setProperty('--color-accent', accentColor);
    localStorage.setItem('momento-accent-color', accentColor);
  }, [accentColor]);

  const handleBrainstormNote = (note: Note) => {
    setActiveView('brainstorm');
    // We'll use a small delay or a ref to pass this to BrainstormView if needed, 
    // but better to just share state or use a CustomEvent
    window.dispatchEvent(new CustomEvent('start-brainstorm', { 
      detail: { seed: note.title, sourceNoteId: note.id } 
    }));
  };

  const handleGenerateFlashcards = async (noteId: string) => {
    const targetNote = notes.find(n => n.id === noteId);
    if (!targetNote) return;

    setIsGeneratingFlashcards(true);
    try {
      const rawContent = targetNote.content || "";
      const generated = await generateFlashcardsForNote(targetNote.title, rawContent);
      
      if (generated && generated.length > 0) {
        const mappedCards: Flashcard[] = generated.map((c, i) => ({
          id: `f-${noteId}-${Date.now()}-${i}`,
          noteId,
          question: c.question,
          answer: c.answer,
          intervalDays: 1,
          nextReviewDate: new Date().toISOString(),
          easeFactor: 2.5,
          mastered: false
        }));

        const updatedSet = [...flashcards.filter(fc => fc.noteId !== noteId), ...mappedCards];
        setFlashcards(updatedSet);
        localStorage.setItem('momento-flashcards', JSON.stringify(updatedSet));

        setToast({
          show: true,
          message: `${mappedCards.length} flashcards créées avec succès pour "${targetNote.title}".`
        });
        setTimeout(() => setToast(t => ({ ...t, show: false })), 4000);
      } else {
        setToast({
          show: true,
          message: "Impossible d'extraire des flashcards exploitables à partir du texte existant."
        });
        setTimeout(() => setToast(t => ({ ...t, show: false })), 4000);
      }
    } catch (err) {
      console.error("AI flashcards expansion failed:", err);
      setToast({
        show: true,
        message: "Une erreur est survenue lors de la génération avec Gemini."
      });
      setTimeout(() => setToast(t => ({ ...t, show: false })), 4000);
    } finally {
      setIsGeneratingFlashcards(false);
    }
  };

  React.useEffect(() => {
    if (activeNoteId) {
      logNoteAccess(activeNoteId);
    }
  }, [activeNoteId]);

  React.useEffect(() => {
    // Check for session in URL
    const params = new URLSearchParams(window.location.search);
    const session = params.get('session');
    if (session) {
      setActiveView('brainstorm');
      // We pass it via a global property or custom event since BrainstormView will fetch sessions
      (window as any).initialSessionId = session;
    }

    const handleSwitchView = (e: any) => {
      if (e.detail) {
        setActiveView(e.detail as NavigationView);
      }
    };

    const handleGlobalShortcut = (e: KeyboardEvent) => {
      // Trigger advanced search with Ctrl+F or Cmd+F or Ctrl+P or Cmd+P
      if ((e.ctrlKey || e.metaKey) && (e.key === 'f' || e.key === 'p')) {
        e.preventDefault();
        setIsSearchOpen(true);
      }
    };

    const handleToggleClipper = () => {
      setIsClipperSimulatorOpen(prev => !prev);
    };

    window.addEventListener('switch-view', handleSwitchView);
    window.addEventListener('keydown', handleGlobalShortcut);
    window.addEventListener('toggle-clipper-simulator', handleToggleClipper);
    return () => {
      window.removeEventListener('switch-view', handleSwitchView);
      window.removeEventListener('keydown', handleGlobalShortcut);
      window.removeEventListener('toggle-clipper-simulator', handleToggleClipper);
    };
  }, []);
  const [isSearchOpen, setIsSearchOpen] = useState(false);
  const [isClipperSimulatorOpen, setIsClipperSimulatorOpen] = useState(false);
  const [clipperToast, setClipperToast] = useState<{ id: string; title: string; noteId: string } | null>(null);
  const [selectedTagIds, setSelectedTagIds] = useState<string[]>([]);
  const [isAISidebarOpen, setIsAISidebarOpen] = useState(false);
  const [isSidebarOpen, setIsSidebarOpen] = useState(false);
  const [aiTab, setAiTab] = useState<AITab>('discussion');
  const [selectedTone, setSelectedTone] = useState<AITone>('Professional');
  
  // Modal States
  const [showNewCarnetModal, setShowNewCarnetModal] = useState<{ isOpen: boolean; parentId?: string; isRenaming?: boolean; carnetId?: string }>({ isOpen: false });
  const [showNewNoteModal, setShowNewNoteModal] = useState(false);
  const [slashMenu, setSlashMenu] = useState<{ isOpen: boolean; top: number; left: number } | null>(null);
  
  // Form States
  const [newCarnetName, setNewCarnetName] = useState('');
  const [newNoteTitle, setNewNoteTitle] = useState('');
  const [newNoteContent, setNewNoteContent] = useState('');

  const handleEditorKeyDown = (e: React.KeyboardEvent) => {
    if (e.key === '/') {
      const selection = window.getSelection();
      if (selection && selection.rangeCount > 0) {
        const range = selection.getRangeAt(0);
        const rect = range.getBoundingClientRect();
        setSlashMenu({
          isOpen: true,
          top: rect.bottom + window.scrollY,
          left: rect.left + window.scrollX
        });
      }
    }
  };

  React.useEffect(() => {
    if (clipperToast) {
      const timer = setTimeout(() => {
        setClipperToast(null);
      }, 4000);
      return () => clearTimeout(timer);
    }
  }, [clipperToast]);

  const handleOpenClippedNote = (noteId: string) => {
    setActiveNoteId(noteId);
    const found = notes.find(n => n.id === noteId);
    if (found) {
      setActiveCarnetId(found.carnetId);
    }
    setActiveView('notebooks');
  };

  const togglePin = (noteId: string) => {
    setNotes(notes.map(n => n.id === noteId ? { ...n, isPinned: !n.isPinned } : n));
  };

  const filteredNotes = useMemo(() => {
    let result = notes.filter(n => n.carnetId === activeCarnetId && !n.isDeleted);
    
    if (selectedTagIds.length > 0) {
      result = result.filter(note => 
        selectedTagIds.every(tagId => note.tags?.some(tag => tag.id === tagId))
      );
    }

    return [...result].sort((a, b) => {
      if (a.isPinned && !b.isPinned) return -1;
      if (!a.isPinned && b.isPinned) return 1;
      return 0;
    });
  }, [activeCarnetId, notes]);

  const activeNote = useMemo(() => 
    notes.find(n => n.id === activeNoteId),
  [activeNoteId, notes]);

  const activeCarnet = useMemo(() => 
    carnets.find(c => c.id === activeCarnetId),
  [activeCarnetId, carnets]);

  const handleAddCarnet = (e: React.FormEvent) => {
    e.preventDefault();
    if (!newCarnetName.trim()) return;
    
    if (showNewCarnetModal.isRenaming && showNewCarnetModal.carnetId) {
      setCarnets(carnets.map(c => c.id === showNewCarnetModal.carnetId ? { ...c, name: newCarnetName, initial: newCarnetName.charAt(0).toUpperCase() } : c));
      setShowNewCarnetModal({ isOpen: false });
      setNewCarnetName('');
      return;
    }

    const newCarnet: Carnet = {
      id: Date.now().toString(),
      name: newCarnetName,
      initial: newCarnetName.charAt(0).toUpperCase(),
      type: 'Project',
      parentId: showNewCarnetModal.parentId
    };
    
    setCarnets([...carnets, newCarnet]);
    setNewCarnetName('');
    setShowNewCarnetModal({ isOpen: false });
    setActiveCarnetId(newCarnet.id);
  };

  const handleDeleteCarnet = (id: string) => {
    if (window.confirm('Déplacer ce carnet et ses sous-carnets vers la corbeille ?')) {
      const idsToDelete = new Set<string>([id]);
      
      const addChildren = (parentId: string) => {
        carnets.forEach(c => {
          if (c.parentId === parentId) {
            idsToDelete.add(c.id);
            addChildren(c.id);
          }
        });
      };
      addChildren(id);
      
      const deletedAt = new Date().toISOString();
      setCarnets(carnets.map(c => idsToDelete.has(c.id) ? { ...c, isDeleted: true, deletedAt } : c));
      setNotes(notes.map(n => idsToDelete.has(n.carnetId) ? { ...n, isDeleted: true, deletedAt } : n));
      
      if (idsToDelete.has(activeCarnetId)) {
        setActiveCarnetId('1');
      }
    }
  };

  const handleDeleteNote = (id: string) => {
    const deletedAt = new Date().toISOString();
    setNotes(notes.map(n => n.id === id ? { ...n, isDeleted: true, deletedAt } : n));
    if (activeNoteId === id) setActiveNoteId(null);
  };

  const handleRestoreCarnet = (id: string) => {
    setCarnets(carnets.map(c => c.id === id ? { ...c, isDeleted: false, deletedAt: undefined } : c));
    // Optionally restore linked notes too? User might expect that.
    setNotes(notes.map(n => n.carnetId === id ? { ...n, isDeleted: false, deletedAt: undefined } : n));
  };

  const handleRestoreNote = (id: string) => {
    setNotes(notes.map(n => n.id === id ? { ...n, isDeleted: false, deletedAt: undefined } : n));
  };

  const handlePermanentDeleteNote = (id: string) => {
    setNotes(notes.filter(n => n.id !== id));
  };

  const handlePermanentDeleteCarnet = (id: string) => {
    const idsToDelete = new Set<string>([id]);
    const addChildren = (parentId: string) => {
      carnets.forEach(c => {
        if (c.parentId === parentId) {
          idsToDelete.add(c.id);
          addChildren(c.id);
        }
      });
    };
    addChildren(id);
    setCarnets(carnets.filter(c => !idsToDelete.has(c.id)));
    setNotes(notes.filter(n => !idsToDelete.has(n.carnetId)));
  };

  const handleAddNote = (e: React.FormEvent) => {
    e.preventDefault();
    if (!newNoteTitle.trim() || !newNoteContent.trim()) return;

    const newNote: Note = {
      id: `n-${Date.now()}`,
      carnetId: activeCarnetId,
      title: newNoteTitle,
      date: new Intl.DateTimeFormat('en-US', { month: 'short', day: 'numeric', year: 'numeric' }).format(new Date()),
      content: newNoteContent,
      imageUrl: 'https://images.unsplash.com/photo-1487958449943-2429e8be8625?auto=format&fit=crop&q=80&w=800&h=600',
      tags: []
    };

    setNotes([newNote, ...notes]);
    setNewNoteTitle('');
    setNewNoteContent('');
    setShowNewNoteModal(false);
    setActiveNoteId(newNote.id);
  };

  const handleConvertIdeaToNote = (idea: BrainstormIdea) => {
    const newNote: Note = {
      id: `n-gen-${Date.now()}`,
      carnetId: activeCarnetId,
      title: idea.title,
      date: new Intl.DateTimeFormat('en-US', { month: 'short', day: 'numeric', year: 'numeric' }).format(new Date()),
      content: `${idea.description}\n\n---\n**Connection to seed:** ${idea.connectionToSeed}\n**Novelty Score:** ${idea.noveltyScore}/10`,
      imageUrl: 'https://images.unsplash.com/photo-1497366216548-37526070297c?auto=format&fit=crop&q=80&w=800&h=600',
      tags: [{ id: 't-ai', label: 'AI Generated', type: 'ai' }]
    };

    setNotes([newNote, ...notes]);
    setActiveView('notebooks');
    setActiveNoteId(newNote.id);
  };

  const handleUpdateNote = (updatedNote: Note) => {
    setNotes(prevNotes => {
      const existing = prevNotes.find(n => n.id === updatedNote.id);
      if (existing && updatedNote.isVersioningEnabled !== false) {
        const hasContentChanged = existing.content !== updatedNote.content;
        const hasTitleChanged = existing.title !== updatedNote.title;
        
        if (hasContentChanged || hasTitleChanged) {
          const history = existing.versionHistory || [];
          const lastSnapshot = history[0];
          const isIdentical = lastSnapshot && lastSnapshot.content === existing.content && lastSnapshot.title === existing.title;
          
          if (!isIdentical) {
            const newSnapshot = {
              id: 'v-' + Date.now(),
              title: existing.title,
              content: existing.content,
              timestamp: new Date().toLocaleDateString('fr-FR', { day: 'numeric', month: 'short', year: 'numeric' }) + ' • ' + new Date().toLocaleTimeString('fr-FR', { hour: '2-digit', minute: '2-digit' }),
              size: existing.content.length
            };
            const updatedWithHistory = {
              ...updatedNote,
              versionHistory: [newSnapshot, ...history]
            };
            return prevNotes.map(n => n.id === updatedNote.id ? updatedWithHistory : n);
          }
        }
      }
      return prevNotes.map(n => n.id === updatedNote.id ? updatedNote : n);
    });
  };

  // WebSocket Integration for Living Blocks
  const [wsConnected, setWsConnected] = React.useState(true);
  const [simulatedOffline, setSimulatedOffline] = React.useState(false);
  const socketRef = React.useRef<WebSocket | null>(null);

  const initWebSocket = () => {
    if (simulatedOffline) return;
    try {
      const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
      const socket = new WebSocket(`${protocol}//${window.location.host}`);
      socketRef.current = socket;

      socket.onopen = () => {
        setWsConnected(true);
        socket.send(JSON.stringify({
          type: 'join',
          sessionId: 'global-momento-session',
          user: { id: 'u-1', name: 'Utilisateur Actuel' }
        }));
      };

      socket.onmessage = (event) => {
        try {
          const data = JSON.parse(event.data);
          if (data.type === 'living_block_update') {
            const { sourceNoteId, blockIndex, newText } = data;
            setNotes(prevNotes => 
              prevNotes.map(note => {
                if (note.id === sourceNoteId) {
                  const paragraphs = note.content.split('\n');
                  if (paragraphs[blockIndex] !== undefined) {
                    paragraphs[blockIndex] = newText;
                    return { ...note, content: paragraphs.join('\n') };
                  }
                }
                return note;
              })
            );
            window.dispatchEvent(new CustomEvent('living-block-pulse', {
              detail: { sourceNoteId, blockIndex }
            }));
          }
        } catch (err) {
          console.error("Error parsing message", err);
        }
      };

      socket.onclose = () => {
        setWsConnected(false);
        setTimeout(() => {
          if (socketRef.current === socket && !simulatedOffline) {
            initWebSocket();
          }
        }, 4000);
      };

      socket.onerror = () => {
        setWsConnected(false);
      };
    } catch (e) {
      console.error(e);
      setWsConnected(false);
    }
  };

  React.useEffect(() => {
    initWebSocket();
    return () => {
      if (socketRef.current) {
        socketRef.current.close();
      }
    };
  }, [simulatedOffline]);

  React.useEffect(() => {
    const handleToggleSimulate = () => {
      setSimulatedOffline(prev => {
        const next = !prev;
        if (next) {
          if (socketRef.current) {
            socketRef.current.close();
          }
          setWsConnected(false);
        } else {
          // Reconnect will automatically trigger because simulatedOffline changes
        }
        return next;
      });
    };
    window.addEventListener('toggle-websocket-simulate', handleToggleSimulate);
    return () => {
      window.removeEventListener('toggle-websocket-simulate', handleToggleSimulate);
    };
  }, []);

  const broadcastLivingBlockUpdate = (sourceNoteId: string, blockIndex: number, newText: string) => {
    if (socketRef.current?.readyState === WebSocket.OPEN && !simulatedOffline) {
      socketRef.current.send(JSON.stringify({
        type: 'living_block_update',
        sourceNoteId,
        blockIndex,
        newText
      }));
    }
  };
  const handleEnterApp = () => {
    if (isAuthenticated) {
      setShowLanding(false);
      sessionStorage.setItem('momento-entered', 'true');
    } else {
      setAuthMode('register');
      setShowAuth(true);
    }
  };

  const handleAuthComplete = () => {
    setIsAuthenticated(true);
    setShowAuth(false);
    setShowLanding(false);
    sessionStorage.setItem('momento-entered', 'true');
  };

  const handleLogout = () => {
    setIsAuthenticated(false);
    setShowLanding(true);
    sessionStorage.removeItem('momento-entered');
  };

  return (
    <AnimatePresence mode="wait">
      {showLanding && !showAuth ? (
        <motion.div
          key={landingVersion}
          initial={{ opacity: 0 }}
          animate={{ opacity: 1 }}
          exit={{ opacity: 0, scale: 1.05 }}
          transition={{ duration: 0.6, ease: [0.23, 1, 0.32, 1] }}
          className="w-full h-full"
        >
          {landingVersion === 'v1' ? (
            <LandingPage 
              onEnter={handleEnterApp} 
              onLogin={() => { setAuthMode('login'); setShowAuth(true); }}
              onRegister={() => { setAuthMode('register'); setShowAuth(true); }}
              onSwitchVersion={setLandingVersion}
            />
          ) : landingVersion === 'v2' ? (
            <LandingPageV2 
              onEnter={handleEnterApp} 
              onLogin={() => { setAuthMode('login'); setShowAuth(true); }}
              onRegister={() => { setAuthMode('register'); setShowAuth(true); }}
              onSwitchVersion={setLandingVersion}
            />
          ) : (
            <LandingPageV3 
              onEnter={handleEnterApp} 
              onLogin={() => { setAuthMode('login'); setShowAuth(true); }}
              onRegister={() => { setAuthMode('register'); setShowAuth(true); }}
              onSwitchVersion={setLandingVersion}
            />
          )}
        </motion.div>
      ) : showAuth ? (
        <motion.div
          key="auth"
          initial={{ opacity: 0, x: 20 }}
          animate={{ opacity: 1, x: 0 }}
          exit={{ opacity: 0, x: -20 }}
          className="w-full h-full"
        >
          <AuthPage 
            initialMode={authMode}
            onAuthComplete={handleAuthComplete}
            onBack={() => setShowAuth(false)}
          />
        </motion.div>
      ) : (
        <motion.div 
          key="app"
          initial={{ opacity: 0, scale: 0.95 }}
          animate={{ opacity: 1, scale: 1 }}
          className={`h-screen flex bg-paper transition-colors duration-500 overflow-hidden font-sans ${isDarkMode ? 'dark' : ''}`}
        >
          <Sidebar 
            activeView={activeView}
            isSidebarOpen={isSidebarOpen}
            setIsSidebarOpen={setIsSidebarOpen}
            isDarkMode={isDarkMode}
            setIsDarkMode={setIsDarkMode}
            setActiveView={setActiveView}
            setActiveSettingsTab={setActiveSettingsTab}
            onGoHome={() => setShowLanding(true)}
            onLogout={handleLogout}
            carnets={carnets}
            notes={notes}
            activeCarnetId={activeCarnetId}
            activeNoteId={activeNoteId}
            setActiveCarnetId={setActiveCarnetId}
            setActiveNoteId={setActiveNoteId}
            flashcards={flashcards}
            onSelectReviewDeck={(noteId) => {
              setActiveReviewDeckId(noteId);
              setActiveView('revision');
            }}
            setShowNewCarnetModal={(show, parentId, isRenaming, carnetId) => {
              setShowNewCarnetModal({ isOpen: show, parentId, isRenaming, carnetId });
              if (isRenaming && carnetId) {
                const carnet = carnets.find(c => c.id === carnetId);
                if (carnet) setNewCarnetName(carnet.name);
              } else {
                setNewCarnetName('');
              }
            }}
            onDeleteCarnet={handleDeleteCarnet}
            onMoveCarnet={(draggedId, targetId) => {
              if (draggedId === targetId) return;
              
              // Basic circular check
              const isDescendant = (parentId: string, potentialChildId: string): boolean => {
                const childIds = carnets.filter(c => c.parentId === parentId).map(c => c.id);
                if (childIds.includes(potentialChildId)) return true;
                return childIds.some(id => isDescendant(id, potentialChildId));
              };

              if (targetId && isDescendant(draggedId, targetId)) {
                console.warn("Cannot move a notebook inside its own descendant");
                return;
              }

              setCarnets(prev => prev.map(c => c.id === draggedId ? { ...c, parentId: targetId } : c));
            }}
          />

          <main className="flex-1 relative overflow-hidden flex bg-paper dark:bg-dark-paper transition-colors duration-500">
            <AnimatePresence mode="wait">
              {(activeView === 'notebooks' || activeView === 'shared' || activeView === 'reminders') && (
                <motion.div
                  key={activeView}
                  initial={{ opacity: 0, x: 20 }}
                  animate={{ opacity: 1, x: 0 }}
                  exit={{ opacity: 0, x: -20 }}
                  transition={{ duration: 0.3 }}
                  className="h-full w-full"
                >
                  <NotebooksView 
                    activeNoteId={activeNoteId}
                    activeCarnet={activeCarnet}
                    filteredNotes={filteredNotes}
                    activeNote={activeNote}
                    setActiveNoteId={setActiveNoteId}
                    togglePin={togglePin}
                    setShowNewNoteModal={setShowNewNoteModal}
                    isAISidebarOpen={isAISidebarOpen}
                    setIsAISidebarOpen={setIsAISidebarOpen}
                    selectedTagIds={selectedTagIds}
                    setSelectedTagIds={setSelectedTagIds}
                    allNotes={notes}
                    activeCarnetId={activeCarnetId}
                    setShowNewCarnetModal={(show, parentId, isRenaming, carnetId) => setShowNewCarnetModal({ isOpen: show, parentId, isRenaming, carnetId })}
                    onDeleteNote={handleDeleteNote}
                    onBrainstormNote={handleBrainstormNote}
                    onUpdateNote={handleUpdateNote}
                    onOpenSidebar={() => setIsSidebarOpen(true)}
                    onSearchClick={() => setIsSearchOpen(true)}
                    wsConnected={wsConnected}
                    broadcastLivingBlockUpdate={broadcastLivingBlockUpdate}
                    carnets={carnets}
                    flashcards={flashcards}
                    onTriggerReviewDeck={(noteId) => {
                      setActiveReviewDeckId(noteId);
                      setActiveView('revision');
                    }}
                    onGenerateFlashcards={handleGenerateFlashcards}
                    isGeneratingFlashcards={isGeneratingFlashcards}
                  />
                </motion.div>
              )}

              {activeView === 'trash' && (
                <motion.div
                  key="trash"
                  initial={{ opacity: 0, x: 20 }}
                  animate={{ opacity: 1, x: 0 }}
                  exit={{ opacity: 0, x: -20 }}
                  transition={{ duration: 0.3 }}
                  className="h-full w-full"
                >
                  <TrashView 
                    deletedNotes={notes.filter(n => n.isDeleted)}
                    deletedCarnets={carnets.filter(c => c.isDeleted)}
                    onRestoreNote={handleRestoreNote}
                    onRestoreCarnet={handleRestoreCarnet}
                    onPermanentDeleteNote={handlePermanentDeleteNote}
                    onPermanentDeleteCarnet={handlePermanentDeleteCarnet}
                    onEmptyTrash={() => {
                      setNotes(notes.filter(n => !n.isDeleted));
                      setCarnets(carnets.filter(c => !c.isDeleted));
                    }}
                    onOpenSidebar={() => setIsSidebarOpen(true)}
                  />
                </motion.div>
              )}

              {activeView === 'agents' && (
                <motion.div
                  key="agents"
                  initial={{ opacity: 0, x: 20 }}
                  animate={{ opacity: 1, x: 0 }}
                  exit={{ opacity: 0, x: -20 }}
                  transition={{ duration: 0.3 }}
                  className="h-full w-full"
                >
                  <AgentsView 
                    selectedAgentId={selectedAgentId}
                    setSelectedAgentId={setSelectedAgentId}
                    carnets={carnets}
                    notes={notes}
                    onAddNote={(note) => setNotes([note, ...notes])}
                    onOpenSidebar={() => setIsSidebarOpen(true)}
                  />
                </motion.div>
              )}

              {activeView === 'settings' && (
                <motion.div
                  key="settings"
                  initial={{ opacity: 0, x: 20 }}
                  animate={{ opacity: 1, x: 0 }}
                  exit={{ opacity: 0, x: -20 }}
                  transition={{ duration: 0.3 }}
                  className="h-full w-full"
                >
                  <SettingsView 
                    activeSettingsTab={activeSettingsTab}
                    setActiveSettingsTab={setActiveSettingsTab}
                    accentColor={accentColor}
                    onAccentColorChange={setAccentColor}
                    onLogout={handleLogout}
                    onOpenSidebar={() => setIsSidebarOpen(true)}
                  />
                </motion.div>
              )}

              {activeView === 'brainstorm' && (
                <motion.div
                  key="brainstorm"
                  initial={{ opacity: 0, scale: 1.05 }}
                  animate={{ opacity: 1, scale: 1 }}
                  exit={{ opacity: 0, scale: 0.95 }}
                  transition={{ duration: 0.4, ease: [0.23, 1, 0.32, 1] }}
                  className="h-full w-full"
                >
                  <BrainstormView 
                    notes={notes}
                    onConvertNote={handleConvertIdeaToNote}
                  />
                </motion.div>
              )}

              {activeView === 'insights' && (
                <motion.div
                  key="insights"
                  initial={{ opacity: 0, scale: 1.05 }}
                  animate={{ opacity: 1, scale: 1 }}
                  exit={{ opacity: 0, scale: 0.95 }}
                  transition={{ duration: 0.4, ease: [0.23, 1, 0.32, 1] }}
                  className="h-full w-full"
                >
                  <InsightsView 
                    notes={notes}
                    onUpdateNotes={setNotes}
                    onNoteSelect={(noteId) => {
                        setActiveView('notebooks');
                        setActiveNoteId(noteId);
                    }}
                    onOpenSidebar={() => setIsSidebarOpen(true)}
                  />
                </motion.div>
              )}

              {activeView === 'temporal' && (
                <motion.div
                  key="temporal"
                  initial={{ opacity: 0, scale: 1.05 }}
                  animate={{ opacity: 1, scale: 1 }}
                  exit={{ opacity: 0, scale: 0.95 }}
                  transition={{ duration: 0.4, ease: [0.23, 1, 0.32, 1] }}
                  className="h-full w-full"
                >
                  <TemporalView 
                    notes={notes}
                    accessLogs={accessLogs}
                    onNoteSelect={(noteId) => {
                        setActiveView('notebooks');
                        setActiveNoteId(noteId);
                    }}
                  />
                </motion.div>
              )}

              {activeView === 'graph' && (
                <motion.div
                  key="graph"
                  initial={{ opacity: 0, scale: 1.05 }}
                  animate={{ opacity: 1, scale: 1 }}
                  exit={{ opacity: 0, scale: 0.95 }}
                  transition={{ duration: 0.4, ease: [0.23, 1, 0.32, 1] }}
                  className="h-full w-full"
                >
                  <GraphKnowledgeMap 
                    notes={notes}
                    carnets={carnets}
                    onOpenNote={(noteId) => {
                      setActiveView('notebooks');
                      setActiveNoteId(noteId);
                      const note = notes.find(n => n.id === noteId);
                      if (note) {
                        setActiveCarnetId(note.carnetId);
                      }
                    }}
                    onClose={() => setActiveView('notebooks')}
                  />
                </motion.div>
              )}

              {activeView === 'revision' && (
                <motion.div
                  key="revision"
                  initial={{ opacity: 0, scale: 1.02 }}
                  animate={{ opacity: 1, scale: 1 }}
                  exit={{ opacity: 0, scale: 0.98 }}
                  transition={{ duration: 0.3 }}
                  className="h-full w-full"
                >
                  <RevisionView 
                    notes={notes}
                    flashcards={flashcards}
                    onUpdateFlashcards={(updated) => {
                      setFlashcards(updated);
                      localStorage.setItem('momento-flashcards', JSON.stringify(updated));
                    }}
                    onSelectNote={(noteId) => {
                      setActiveView('notebooks');
                      setActiveNoteId(noteId);
                      const note = notes.find(n => n.id === noteId);
                      if (note) {
                        setActiveCarnetId(note.carnetId);
                      }
                    }}
                    onOpenSidebar={() => setIsSidebarOpen(true)}
                    initialActiveDeckId={activeReviewDeckId}
                    onClearActiveDeckId={() => setActiveReviewDeckId(null)}
                  />
                </motion.div>
              )}
            </AnimatePresence>

            <AISidebar 
              isOpen={isAISidebarOpen}
              setIsOpen={setIsAISidebarOpen}
              activeNote={activeNote}
              aiTab={aiTab}
              setAiTab={setAiTab}
              selectedTone={selectedTone}
              setSelectedTone={setSelectedTone}
              carnets={carnets}
              notes={notes}
              onOpenNote={setActiveNoteId}
              onUpdateNote={handleUpdateNote}
            />
          </main>

          {/* Modals */}
          <AnimatePresence>
            {showNewCarnetModal.isOpen && (
              <div className="fixed inset-0 z-50 flex items-center justify-center p-4">
                <motion.div 
                  initial={{ opacity: 0 }}
                  animate={{ opacity: 1 }}
                  exit={{ opacity: 0 }}
                  onClick={() => setShowNewCarnetModal({ isOpen: false })}
                  className="absolute inset-0 bg-ink/40 backdrop-blur-sm"
                />
                <motion.div
                  initial={{ opacity: 0, scale: 0.9, y: 20 }}
                  animate={{ opacity: 1, scale: 1, y: 0 }}
                  exit={{ opacity: 0, scale: 0.9, y: 20 }}
                  className="relative w-full max-w-md bg-paper dark:bg-dark-paper border border-border shadow-2xl rounded-2xl p-8"
                >
                  <h3 className="text-2xl font-serif font-medium text-ink dark:text-dark-ink mb-2">
                    {showNewCarnetModal.isRenaming ? 'Rename Carnet' : (showNewCarnetModal.parentId ? 'Create Sub-Carnet' : 'Create New Carnet')}
                  </h3>
                  {showNewCarnetModal.parentId && !showNewCarnetModal.isRenaming && (
                    <p className="text-[10px] text-concrete uppercase tracking-widest font-bold mb-6">
                      Inside: {carnets.find(c => c.id === showNewCarnetModal.parentId)?.name}
                    </p>
                  )}
                  <form onSubmit={handleAddCarnet} className="space-y-6">
                    <div>
                      <label className="block text-[11px] uppercase tracking-widest font-bold text-muted-ink mb-2">Notebook Name</label>
                      <input 
                        autoFocus
                        type="text" 
                        value={newCarnetName}
                        onChange={(e) => setNewCarnetName(e.target.value)}
                        placeholder="E.g., Sustainable Patterns"
                        className="w-full bg-white dark:bg-[#2A2A2A] border border-border rounded-lg px-4 py-3 outline-none focus:border-ink transition-colors font-serif italic text-lg text-ink dark:text-dark-ink"
                      />
                    </div>
                    <div className="flex gap-4 pt-4">
                      <button 
                        type="button"
                        onClick={() => {
                          setShowNewCarnetModal({ isOpen: false });
                          setNewCarnetName('');
                        }}
                        className="flex-1 py-3 border border-border rounded-lg text-sm font-medium hover:bg-slate-50 dark:hover:bg-white/5 transition-colors text-ink dark:text-dark-ink"
                      >
                        Cancel
                      </button>
                      <button 
                        type="submit"
                        className="flex-1 py-3 bg-ink dark:bg-ochre text-paper rounded-lg text-sm font-medium hover:opacity-90 transition-opacity"
                      >
                        {showNewCarnetModal.isRenaming ? 'Rename' : 'Create Notebook'}
                      </button>
                    </div>
                  </form>
                </motion.div>
              </div>
            )}

            {showNewNoteModal && (
              <div className="fixed inset-0 z-50 flex items-center justify-center p-4">
                <motion.div 
                  initial={{ opacity: 0 }}
                  animate={{ opacity: 1 }}
                  exit={{ opacity: 0 }}
                  onClick={() => setShowNewNoteModal(false)}
                  className="absolute inset-0 bg-ink/40 backdrop-blur-sm"
                />
                <motion.div
                  initial={{ opacity: 0, scale: 0.9, y: 20 }}
                  animate={{ opacity: 1, scale: 1, y: 0 }}
                  exit={{ opacity: 0, scale: 0.9, y: 20 }}
                  className="relative w-full max-w-2xl bg-paper dark:bg-dark-paper border border-border shadow-2xl rounded-2xl p-10"
                >
                  <AnimatePresence>
                    {slashMenu?.isOpen && (
                      <SlashMenu 
                        position={{ top: slashMenu.top, left: slashMenu.left }}
                        onSelect={(type) => { console.log(type); setSlashMenu(null); }}
                        onClose={() => setSlashMenu(null)}
                      />
                    )}
                  </AnimatePresence>
                  <h3 className="text-3xl font-serif font-medium text-ink dark:text-dark-ink mb-8">Add Architectural Note</h3>
                  <form onSubmit={handleAddNote} className="space-y-8">
                    <div>
                      <label className="block text-[11px] uppercase tracking-widest font-bold text-muted-ink mb-2">Concept Title</label>
                      <input 
                        autoFocus
                        type="text" 
                        value={newNoteTitle}
                        onChange={(e) => setNewNoteTitle(e.target.value)}
                        placeholder="Enter the title of your study..."
                        className="w-full bg-white dark:bg-[#2A2A2A] border border-border rounded-lg px-5 py-4 outline-none focus:border-ink transition-colors font-serif text-2xl text-ink dark:text-dark-ink"
                      />
                    </div>
                    <div>
                      <label className="block text-[11px] uppercase tracking-widest font-bold text-muted-ink mb-2">Observations & Analysis</label>
                      <textarea 
                        value={newNoteContent}
                        onChange={(e) => setNewNoteContent(e.target.value)}
                        onKeyDown={handleEditorKeyDown}
                        placeholder="Describe the spatial logic, materiality, and light interactions... (Type '/' for commands)"
                        rows={6}
                        className="w-full bg-white dark:bg-[#2A2A2A] border border-border rounded-lg px-5 py-4 outline-none focus:border-ink transition-colors font-light leading-relaxed resize-none text-ink dark:text-dark-ink"
                      />
                    </div>
                    <div className="flex gap-4 pt-4">
                      <button 
                        type="button"
                        onClick={() => setShowNewNoteModal(false)}
                        className="flex-1 py-4 border border-border rounded-lg text-sm font-medium hover:bg-slate-50 dark:hover:bg-white/5 transition-colors text-ink dark:text-dark-ink"
                      >
                        Cancel
                      </button>
                      <button 
                        type="submit"
                        className="flex-1 py-4 bg-ink dark:bg-ochre text-paper rounded-lg text-sm font-medium hover:opacity-90 transition-opacity"
                      >
                        Save Note
                      </button>
                    </div>
                  </form>
                </motion.div>
              </div>
            )}

            {isSearchOpen && (
              <SearchModal 
                isOpen={isSearchOpen}
                onClose={() => setIsSearchOpen(false)}
                notes={notes}
                carnets={carnets}
                onSelectNote={(noteId) => {
                  setActiveNoteId(noteId);
                  const searchHitNote = notes.find(n => n.id === noteId);
                  if (searchHitNote) {
                    setActiveCarnetId(searchHitNote.carnetId);
                  }
                }}
              />
            )}

            {isClipperSimulatorOpen && (
              <ClipperSimulator 
                isOpen={isClipperSimulatorOpen}
                onClose={() => setIsClipperSimulatorOpen(false)}
                carnets={carnets}
                activeCarnetId={activeCarnetId}
                onAddNote={(newNote) => setNotes(prevNotes => [newNote, ...prevNotes])}
                onTriggerToast={(title, noteId) => {
                  setClipperToast({
                    id: String(Date.now()),
                    title,
                    noteId
                  });
                }}
              />
            )}

            {clipperToast && (
              <motion.div
                initial={{ opacity: 0, y: 50, scale: 0.9 }}
                animate={{ opacity: 1, y: 0, scale: 1 }}
                exit={{ opacity: 0, y: 20, scale: 0.9 }}
                className="fixed bottom-6 right-6 z-[999] bg-[#0E0E0E] text-white border border-neutral-800 rounded-xl shadow-2xl pl-5 pr-4 py-3.5 flex items-center justify-between gap-5 tracking-wide max-w-[360px]"
              >
                <div className="flex items-center gap-2.5">
                  <span className="w-2 h-2 rounded-full bg-cyan-400 animate-pulse shrink-0" />
                  <p className="text-xs font-semibold text-neutral-100 leading-normal">
                     Note clippée — <span className="text-cyan-400 font-bold">{clipperToast.title}</span>
                  </p>
                </div>
                
                <div className="flex items-center gap-2.5 shrink-0">
                  <button 
                    onClick={() => {
                      handleOpenClippedNote(clipperToast.noteId);
                      setClipperToast(null);
                    }}
                    className="text-xs font-bold uppercase tracking-wider text-cyan-400 hover:text-cyan-300 underline underline-offset-2 transition-colors"
                  >
                    Voir
                  </button>
                  <button 
                    onClick={() => setClipperToast(null)}
                    className="p-1 hover:bg-white/10 text-neutral-400 hover:text-white rounded-lg transition-colors"
                  >
                    <X size={14} />
                  </button>
                </div>
              </motion.div>
            )}

            {toast.show && (
              <motion.div
                initial={{ opacity: 0, y: 50, scale: 0.9 }}
                animate={{ opacity: 1, y: 0, scale: 1 }}
                exit={{ opacity: 0, y: 20, scale: 0.9 }}
                className="fixed bottom-6 right-6 z-[999] bg-[#0E0E0E] text-white border border-neutral-800 rounded-xl shadow-2xl pl-5 pr-4 py-3.5 flex items-center justify-between gap-5 tracking-wide max-w-[420px]"
              >
                <div className="flex items-center gap-2.5">
                  <span className="w-2 h-2 rounded-full bg-accent animate-pulse shrink-0" />
                  <p className="text-xs font-semibold text-neutral-100 leading-normal">
                     {toast.message}
                  </p>
                </div>
                
                <div className="flex items-center gap-2.5 shrink-0">
                  <button 
                    onClick={() => {
                      setActiveView('revision');
                      setToast({ show: false, message: '' });
                    }}
                    className="text-xs font-bold uppercase tracking-wider text-accent hover:text-accent/80 underline underline-offset-2 transition-colors cursor-pointer"
                  >
                    Voir
                  </button>
                  <button 
                    onClick={() => setToast({ show: false, message: '' })}
                    className="p-1 hover:bg-white/10 text-neutral-400 hover:text-white rounded-lg transition-colors cursor-pointer"
                  >
                    <X size={14} />
                  </button>
                </div>
              </motion.div>
            )}
          </AnimatePresence>
        </motion.div>
      )}
    </AnimatePresence>
  );
}
