/**
 * Scaffo.ai - Main App Component
 * Contains all state management, routing, and event handlers.
 * Loaded via Babel standalone - uses var declarations for global scope.
 * 
 * Dependencies: React, ReactDOM, auth.js, api.js, utils.js, components.jsx
 */

var { createRoot } = ReactDOM;

var App = () => {
            // ============================================
            // ALL HOOKS MUST BE AT THE TOP (React Rules)
            // ============================================
            
            // Auth State
            const [currentUser, setCurrentUser] = useState(null);
            const [authChecked, setAuthChecked] = useState(false);
            
            // App State (must be declared before any conditional returns)
            const [view, setView] = useState('home'); // home, chat, blueprint, generating, package, library
            const [messages, setMessages] = useState([]);
            const [inputValue, setInputValue] = useState('');
            const [isLoading, setIsLoading] = useState(false);
            const [aiProgress, setAiProgress] = useState(null); // { message, step, total_steps }
            const [isGeneratingMaterials, setIsGeneratingMaterials] = useState(false);
            const [isGeneratingBlueprint, setIsGeneratingBlueprint] = useState(false);
            const [blueprint, setBlueprint] = useState(null);
            const [teachingPackage, setTeachingPackage] = useState(null);
            const [extractedInfo, setExtractedInfo] = useState(null);
            const [confirmedLessonInfo, setConfirmedLessonInfo] = useState(null);
            const [adjustModalOpen, setAdjustModalOpen] = useState(false);
            const [adjustSection, setAdjustSection] = useState(null);
            const [generatingPhase, setGeneratingPhase] = useState('');
            const [generatingProgress, setGeneratingProgress] = useState(0);
            const [generatingSteps, setGeneratingSteps] = useState([]);
            const [currentGenerationId, setCurrentGenerationId] = useState(null);
            const [currentGeneration, setCurrentGeneration] = useState(null);
            const [showPackageInGeneration, setShowPackageInGeneration] = useState(false);
            const [uploadedFiles, setUploadedFiles] = useState([]);
            const [pendingAttachments, setPendingAttachments] = useState([]);
            const [isUploading, setIsUploading] = useState(false);
            const [blueprintModifiedSinceGeneration, setBlueprintModifiedSinceGeneration] = useState(false);
            const [lastGeneratedBlueprint, setLastGeneratedBlueprint] = useState(null); // Snapshot of blueprint when materials were last generated
            const [recentGenerations, setRecentGenerations] = useState([]);
            
            // Refs
            const chatRef = useRef(null);
            const fileInputRef = useRef(null);
            
            // URL routing helper (defined early so useEffect can use it)
            const navigateTo = (path) => {
                window.history.pushState({}, '', `/#${path}`);
                window.dispatchEvent(new PopStateEvent('popstate'));
            };

            // Parse hash route
            // Supports: /#/generation/:id or /#/library
            // Note: userId is NOT in URL for privacy - backend identifies user via auth token
            const parseRoute = () => {
                const hash = window.location.hash.slice(1) || '/';
                const parts = hash.split('/').filter(Boolean);
                // Format: /generation/:id or /library
                return { path: parts[0] || 'home', id: parts[1] || null };
            };
            
            // Load recent generations on mount and after generation
            const loadRecentGenerations = async () => {
                try {
                    const result = await api.getGenerations(1, 10, '');
                    setRecentGenerations(result.items || []);
                } catch (error) {
                    console.error('Failed to load recent generations:', error);
                }
            };
            
            // ============================================
            // ALL useEffect HOOKS (must be before any conditional returns)
            // ============================================
            
            // Check authentication on mount
            useEffect(() => {
                const checkAuth = async () => {
                    const storedUser = getStoredUser();
                    const token = getAuthToken();
                    
                    if (storedUser && token) {
                        // Verify token is still valid
                        try {
                            const user = await api.getCurrentUser();
                            setCurrentUser(user);
                        } catch (e) {
                            // Token invalid, clear it
                            clearAuthToken();
                        }
                    }
                    setAuthChecked(true);
                };
                checkAuth();
            }, []);

            // Handle route changes
            useEffect(() => {
                // Skip route handling if not authenticated yet
                if (!authChecked || !currentUser) return;
                
                const handleRoute = async () => {
                    const { path, id } = parseRoute();
                    
                    if (path === 'generation' && id) {
                        // Load generation by ID
                        // User is identified via auth token, not URL
                        try {
                            const gen = await api.getGeneration(id);
                            if (gen) {
                                setCurrentGenerationId(id);
                                setCurrentGeneration(gen); // Store full generation for history
                                
                                // Load conversation and add blueprint as a message
                                const conversation = gen.conversation || [];
                                
                                // Restore attachments from legacy conversation (for old records without structured attachments)
                                // This parses "📎 Attached:" markers in content to reconstruct attachment preview cards
                                // Also restore thoughtText from thought_text (backend uses snake_case, frontend uses camelCase)
                                const restoredConversation = conversation.map(function(msg) {
                                    // Convert thought_text to thoughtText for frontend display
                                    var restoredMsg = { ...msg };
                                    if (msg.thought_text) {
                                        restoredMsg.thoughtText = msg.thought_text;
                                    }
                                    
                                    // Skip attachment restoration if message already has attachments or is not a user message
                                    if (msg.attachments || msg.role !== 'user') return restoredMsg;
                                    
                                    // Check if content contains attached file indicators
                                    var content = msg.content || '';
                                    var attachedMatch = content.match(/📎 Attached:\s*(.+)$/m);
                                    if (!attachedMatch) return restoredMsg;
                                    
                                    // Parse attached files from content (format: "📎 Attached: 🖼️ filename.png" or "📎 Attached: 📝 filename.docx")
                                    var attachedPart = attachedMatch[1].trim();
                                    var attachments = [];
                                    
                                    // Determine file type by checking for image emoji (🖼️ or 🖼) at the start
                                    var isImage = /^🖼/.test(attachedPart);
                                    
                                    // Extract filename by removing the leading emoji
                                    // Handle various emoji formats: 🖼️ (U+1F5BC + U+FE0F), 📝 (U+1F4DD), 📄 (U+1F4C4), 📊 (U+1F4CA)
                                    // Use Unicode property escape for reliable emoji matching
                                    var filename = attachedPart.replace(/^[\u{1F3A8}\u{1F4DD}\u{1F4C4}\u{1F4CA}\u{1F5BC}]\uFE0F?\s*/u, '').trim();
                                    
                                    if (filename) {
                                        // Also check file extension to determine type
                                        var isImageByExt = /\.(jpg|jpeg|png|gif|webp|svg|bmp)$/i.test(filename);
                                        attachments.push({
                                            filename: filename,
                                            analysis_type: (isImage || isImageByExt) ? 'image' : 'document',
                                            // Note: file_url may not be available for legacy records
                                            file_url: null
                                        });
                                    }
                                    
                                    if (attachments.length > 0) {
                                        return { ...restoredMsg, attachments: attachments };
                                    }
                                    return restoredMsg;
                                });
                                
                                const messagesWithBlueprint = [...restoredConversation];
                                
                                // Add blueprint as a message if it exists and not already in messages
                                if (gen.blueprint) {
                                    // Check if this is a regeneration scenario (has package history)
                                    var hasPackageHistory = gen.package_history && gen.package_history.length > 0;
                                    
                                    // Filter out redundant messages from conversation that we'll replace with proper components
                                    const filteredMessages = restoredConversation.filter(msg => {
                                        // Remove plain "Blueprint generated" text (we'll add blueprint component instead)
                                        if (msg.content === 'Blueprint generated' && !msg.type) return false;
                                        // Remove "Perfect! Generating..." messages (transient)
                                        if (msg.content && msg.content.includes('Generating your lesson blueprint')) return false;
                                        // For regeneration scenario: filter out old blueprint_ready and package messages
                                        // We'll reconstruct them properly with version info
                                        if (hasPackageHistory) {
                                            if (msg.type === 'blueprint_ready') return false;
                                            if (msg.type === 'package') return false;
                                            if (msg.type === 'blueprint') return false;
                                        }
                                        return true;
                                    });
                                    
                                    // Separate regeneration messages from other messages
                                    // They should be placed AFTER history, not before
                                    var regenMessages = [];
                                    var nonRegenMessages = [];
                                    filteredMessages.forEach(function(m) {
                                        if (m.content && (
                                            m.content.includes('I\'ve modified the Blueprint') ||
                                            m.content.includes('我已修改 Blueprint') ||
                                            m.content.includes('Got it! I noticed you\'ve modified') ||
                                            m.content.includes('好的，我注意到您修改了') ||
                                            m.content.includes('Regenerating teaching materials') ||
                                            m.content.includes('正在根据更新后的内容重新生成')
                                        )) {
                                            regenMessages.push(m);
                                        } else {
                                            nonRegenMessages.push(m);
                                        }
                                    });
                                    
                                    // Replace messagesWithBlueprint with non-regen messages first
                                    messagesWithBlueprint.length = 0;
                                    nonRegenMessages.forEach(m => messagesWithBlueprint.push(m));
                                    
                                    // Check if there's a blueprint message WITH actual blueprint data
                                    // (saved conversation may have type='blueprint' but no blueprint object)
                                    var hasBlueprintMsg = filteredMessages.some(msg => msg.type === 'blueprint' && msg.blueprint);
                                    
                                    // If there's a blueprint message without data, enrich it with gen.blueprint
                                    // Also restore thoughtText if it's missing (for old data before the bug fix)
                                    for (var i = 0; i < messagesWithBlueprint.length; i++) {
                                        var m = messagesWithBlueprint[i];
                                        if (m.type === 'blueprint' && gen.blueprint) {
                                            // Enrich with blueprint data if missing
                                            if (!m.blueprint) {
                                                messagesWithBlueprint[i] = {
                                                    ...m,
                                                    blueprint: gen.blueprint,
                                                    generationId: gen.id,
                                                    blueprintHistory: gen.blueprint_history || [],
                                                    version: gen.version || 1,
                                                    updatedAt: gen.updated_at,
                                                    // CRITICAL: Restore thoughtText from blueprint for thinking log display
                                                    thoughtText: gen.blueprint.thought_text || null
                                                };
                                                // Mark as having blueprint message now
                                                hasBlueprintMsg = true;
                                            } 
                                            // Also restore thoughtText if message has blueprint but missing thoughtText
                                            else if (!m.thoughtText && gen.blueprint.thought_text) {
                                                messagesWithBlueprint[i] = {
                                                    ...m,
                                                    thoughtText: gen.blueprint.thought_text
                                                };
                                            }
                                        }
                                        
                                        // Restore extractedInfo for confirmation messages from blueprint metadata
                                        if (m.type === 'confirmation' && !m.extractedInfo && gen.blueprint) {
                                            var metadata = gen.blueprint.metadata || {};
                                            messagesWithBlueprint[i] = {
                                                ...m,
                                                extractedInfo: {
                                                    topic: metadata.topic || gen.blueprint.title || gen.title,
                                                    grade: metadata.grade_level || '',
                                                    subject: metadata.subject || '',
                                                    duration: metadata.duration_minutes ? String(metadata.duration_minutes) : '',
                                                    teaching_style: metadata.teaching_style || '',
                                                    activities: metadata.activities || [],
                                                    objectives: metadata.objectives || [],
                                                    assessment_type: metadata.assessment_type || '',
                                                    suggested_packages: metadata.selected_packages || ['slide', 'lesson_plan'],
                                                    status: 'ready_to_generate'
                                                },
                                                // Preserve thoughtText if it was saved
                                                thoughtText: m.thoughtText || null
                                            };
                                        }
                                    }
                                    
                                    /* DISABLED: Confirmed summary card in history - skipped to reduce user interaction cost
                                    const hasConfirmedSummary = filteredMessages.some(msg => msg.type === 'confirmed_summary');
                                    const hasGatheredMsg = filteredMessages.some(msg => 
                                        msg.content && msg.content.includes("I've gathered all the information")
                                    );
                                    
                                    if (!hasConfirmedSummary) {
                                        const metadata = gen.blueprint.metadata || {};
                                        const lessonInfo = {
                                            topic: metadata.topic || gen.blueprint.title || gen.title,
                                            grade: metadata.grade_level,
                                            subject: metadata.subject,
                                            duration: metadata.duration_minutes ? metadata.duration_minutes : null,
                                            teaching_style: metadata.teaching_style,
                                            assessment_type: metadata.assessment_type,
                                            objectives: metadata.objectives || metadata.learning_objectives || [],
                                            activities: metadata.activities || []
                                        };
                                        if (lessonInfo.topic || lessonInfo.grade || lessonInfo.subject) {
                                            if (!hasGatheredMsg) {
                                                messagesWithBlueprint.push({
                                                    role: 'assistant',
                                                    content: "Great! I've gathered all the information. Please review and confirm the details below, or make any edits before generating your blueprint."
                                                });
                                            }
                                            messagesWithBlueprint.push({
                                                role: 'assistant',
                                                type: 'confirmed_summary',
                                                lessonInfo: lessonInfo,
                                                content: 'Lesson details confirmed'
                                            });
                                        }
                                    }
                                    */
                                    
                                    // Add package history as messages BEFORE current blueprint
                                    // Each history entry becomes: Blueprint (read-only) + Package pair
                                    var pkgHistory = gen.package_history || [];
                                    if (pkgHistory.length > 0) {
                                        // Sort by version ascending (oldest first)
                                        var sortedHistory = pkgHistory.slice().sort(function(a, b) {
                                            return (a.version || 0) - (b.version || 0);
                                        });
                                        
                                        // Find the position of the first blueprint message in conversation
                                        // History should be inserted BEFORE it
                                        var insertIndex = -1;
                                        for (var fi = 0; fi < messagesWithBlueprint.length; fi++) {
                                            if (messagesWithBlueprint[fi].type === 'blueprint') {
                                                insertIndex = fi;
                                                break;
                                            }
                                        }
                                        
                                        // Build history messages array
                                        var historyMessages = [];
                                        for (var hi = 0; hi < sortedHistory.length; hi++) {
                                            var histEntry = sortedHistory[hi];
                                            var histVersion = (typeof histEntry.version === 'number') ? histEntry.version : (hi + 1);
                                            var histTimestamp = histEntry.timestamp ? new Date(histEntry.timestamp).toLocaleString() : '';
                                            var isHistZh = /[\u4e00-\u9fa5]/.test((histEntry.blueprint_snapshot && histEntry.blueprint_snapshot.title) || '');
                                            
                                            // Add history blueprint (read-only)
                                            if (histEntry.blueprint_snapshot) {
                                                var histThoughtText = histEntry.blueprint_snapshot.thought_text || null;
                                                historyMessages.push({
                                                    id: 'hist-bp-' + histVersion,
                                                    role: 'assistant',
                                                    type: 'blueprint',
                                                    blueprint: histEntry.blueprint_snapshot,
                                                    content: 'Blueprint v' + histVersion,
                                                    isReadOnly: true,
                                                    isHistoryVersion: true,
                                                    historyVersion: histVersion,
                                                    historyTimestamp: histTimestamp,
                                                    // Restore thought_text from saved blueprint snapshot
                                                    thoughtText: histThoughtText
                                                });
                                                
                                                // Add blueprint_ready message after blueprint (before package)
                                                historyMessages.push({
                                                    id: 'hist-bp-ready-' + histVersion,
                                                    role: 'assistant',
                                                    type: 'blueprint_ready',
                                                    content: isHistZh 
                                                        ? 'Blueprint v' + histVersion + ' 已生成完成！'
                                                        : 'Blueprint v' + histVersion + ' is ready!',
                                                    isHistoryVersion: true,
                                                    historyVersion: histVersion,
                                                    materialsGenerated: true  // Hide buttons for history
                                                });
                                            }
                                            
                                            // Add history package
                                            if (histEntry.package) {
                                                historyMessages.push({
                                                    id: 'hist-pkg-' + histVersion,
                                                    role: 'assistant',
                                                    type: 'package',
                                                    pkg: histEntry.package,
                                                    content: 'Materials v' + histVersion,
                                                    isHistoryVersion: true,
                                                    historyVersion: histVersion,
                                                    historyTimestamp: histTimestamp
                                                });
                                            }
                                        }
                                        
                                        // Insert history messages before the current blueprint
                                        if (insertIndex >= 0 && historyMessages.length > 0) {
                                            // Splice history messages into the array before the current blueprint
                                            messagesWithBlueprint.splice.apply(messagesWithBlueprint, [insertIndex, 0].concat(historyMessages));
                                        } else if (historyMessages.length > 0) {
                                            // No blueprint message found, append at end (fallback)
                                            historyMessages.forEach(function(hm) { messagesWithBlueprint.push(hm); });
                                        }
                                        
                                        // Now add regeneration messages after history (they were separated earlier)
                                        // Find where to insert: after the last history package message
                                        if (regenMessages.length > 0) {
                                            // Find the last history package message index
                                            var lastHistPkgIdx = -1;
                                            for (var ri = 0; ri < messagesWithBlueprint.length; ri++) {
                                                if (messagesWithBlueprint[ri].isHistoryVersion && messagesWithBlueprint[ri].type === 'package') {
                                                    lastHistPkgIdx = ri;
                                                }
                                            }
                                            if (lastHistPkgIdx >= 0) {
                                                // Insert regen messages after last history package
                                                messagesWithBlueprint.splice.apply(messagesWithBlueprint, [lastHistPkgIdx + 1, 0].concat(regenMessages));
                                            } else {
                                                // Fallback: add at the end (before current blueprint will be added)
                                                regenMessages.forEach(function(rm) { messagesWithBlueprint.push(rm); });
                                            }
                                        } else {
                                            // No saved regen messages - generate fallback ones
                                            var lastHistEntry = sortedHistory[sortedHistory.length - 1];
                                            var lastHistBlueprint = lastHistEntry.blueprint_snapshot || {};
                                            var currentBlueprint = gen.blueprint || {};
                                            
                                            // Detect language
                                            var isZhLang = /[\u4e00-\u9fa5]/.test(currentBlueprint.title || gen.title || '');
                                            
                                            // Detect changes between last history and current
                                            var changesList = [];
                                            if (lastHistBlueprint.title !== currentBlueprint.title) {
                                                changesList.push(isZhLang ? '标题' : 'Title');
                                            }
                                            if (lastHistBlueprint.summary !== currentBlueprint.summary) {
                                                changesList.push(isZhLang ? '概述' : 'Summary');
                                            }
                                            if (JSON.stringify(lastHistBlueprint.learning_objectives) !== JSON.stringify(currentBlueprint.learning_objectives)) {
                                                changesList.push(isZhLang ? '学习目标' : 'Learning Objectives');
                                            }
                                            if (JSON.stringify(lastHistBlueprint.lesson_flow) !== JSON.stringify(currentBlueprint.lesson_flow)) {
                                                changesList.push(isZhLang ? '教学流程' : 'Lesson Flow');
                                            }
                                            if (JSON.stringify(lastHistBlueprint.differentiation_strategies) !== JSON.stringify(currentBlueprint.differentiation_strategies)) {
                                                changesList.push(isZhLang ? '差异化策略' : 'Differentiation Strategies');
                                            }
                                            if (lastHistBlueprint.raw_content !== currentBlueprint.raw_content) {
                                                if (changesList.length === 0) {
                                                    changesList.push(isZhLang ? '课程内容' : 'Content');
                                                }
                                            }
                                            
                                            var changesText = changesList.length > 0 ? changesList.join(', ') : (isZhLang ? '课程内容' : 'content');
                                            var nextVersion = (lastHistEntry.version || 1) + 1;
                                            
                                            // Find last history package to insert after
                                            var lastHistPkgIdx2 = -1;
                                            for (var ri2 = 0; ri2 < messagesWithBlueprint.length; ri2++) {
                                                if (messagesWithBlueprint[ri2].isHistoryVersion && messagesWithBlueprint[ri2].type === 'package') {
                                                    lastHistPkgIdx2 = ri2;
                                                }
                                            }
                                            
                                            var fallbackRegenMsgs = [
                                                {
                                                    id: 'regen-user-' + nextVersion,
                                                    role: 'user',
                                                    content: isZhLang 
                                                        ? '我已修改 Blueprint，请重新生成教学材料。'
                                                        : 'I\'ve modified the Blueprint, please regenerate teaching materials.'
                                                },
                                                {
                                                    id: 'regen-ack-' + nextVersion,
                                                    role: 'assistant',
                                                    content: isZhLang
                                                        ? '好的，我注意到您修改了 Blueprint 的 **' + changesText + '**。\n\n💭 我会根据更新后的内容重新生成教学材料，确保与新的课程设计保持一致。'
                                                        : 'Got it! I noticed you\'ve modified the Blueprint\'s **' + changesText + '**.\n\n💭 I\'ll regenerate the teaching materials based on the updates to ensure alignment with your new lesson design.'
                                                }
                                            ];
                                            
                                            if (lastHistPkgIdx2 >= 0) {
                                                messagesWithBlueprint.splice.apply(messagesWithBlueprint, [lastHistPkgIdx2 + 1, 0].concat(fallbackRegenMsgs));
                                            } else {
                                                fallbackRegenMsgs.forEach(function(m) { messagesWithBlueprint.push(m); });
                                            }
                                        }
                                    }
                                    
                                    // Add a simple transition message before current blueprint (replaces the removed confirmation card)
                                    const hasTransitionMsg = filteredMessages.some(msg => 
                                        msg.content && (msg.content.includes("I've created your lesson blueprint") || msg.content.includes("Here's your lesson blueprint") || msg.content.includes("已生成") || msg.content.includes("蓝图"))
                                    );
                                    // Only add transition message if there's no history (for fresh generations)
                                    if (!hasTransitionMsg && pkgHistory.length === 0) {
                                        // Detect conversation language by checking user messages
                                        const userMessages = filteredMessages.filter(m => m.role === 'user');
                                        const lastUserMsg = userMessages.length > 0 ? userMessages[userMessages.length - 1].content : '';
                                        const isChinese = /[\u4e00-\u9fa5]/.test(lastUserMsg);
                                        
                                        messagesWithBlueprint.push({
                                            role: 'assistant',
                                            content: isChinese 
                                                ? "已根据您提供的信息生成课程蓝图。您可以在下方预览和编辑，准备好后即可生成教学材料。"
                                                : "I've created your lesson blueprint based on the information provided. You can review and edit it below, then generate your teaching materials when ready."
                                        });
                                    }
                                    
                                    // For regeneration scenario, we filtered out old blueprint/package messages
                                    // so always add the current version
                                    if (!hasBlueprintMsg || hasPackageHistory) {
                                        // Current version blueprint - with version label if has history
                                        var currentVersion = hasPackageHistory ? (gen.package && gen.package.version) || (pkgHistory.length + 1) : 1;
                                        
                                        // Check if current blueprint's thought_text is same as any history version
                                        // to avoid duplicate thinking display
                                        var currentThought = gen.blueprint && gen.blueprint.thought_text ? gen.blueprint.thought_text : null;
                                        var isDuplicateThought = false;
                                        if (currentThought && pkgHistory && pkgHistory.length > 0) {
                                            for (var hi = 0; hi < pkgHistory.length; hi++) {
                                                var histBp = pkgHistory[hi].blueprint_snapshot;
                                                if (histBp && histBp.thought_text === currentThought) {
                                                    isDuplicateThought = true;
                                                    break;
                                                }
                                            }
                                        }
                                        
                                        messagesWithBlueprint.push({
                                            role: 'assistant',
                                            type: 'blueprint',
                                            blueprint: gen.blueprint,
                                            content: hasPackageHistory ? 'Blueprint v' + currentVersion : 'Blueprint generated',
                                            // Include generation info for history tracking
                                            generationId: gen.id,
                                            blueprintHistory: gen.blueprint_history || [],
                                            version: currentVersion,
                                            updatedAt: gen.updated_at,
                                            // Restore thought_text from saved blueprint for thinking display
                                            // Skip if duplicate of history version to avoid showing same thinking twice
                                            thoughtText: isDuplicateThought ? null : currentThought
                                        });
                                    }
                                    
                                    // Add blueprint_ready message if no package yet (to show Create Materials button)
                                    if (!gen.package && !hasPackageHistory) {
                                        var isZhLang = /[\u4e00-\u9fa5]/.test(gen.blueprint.title || '');
                                        messagesWithBlueprint.push({
                                            role: 'assistant',
                                            type: 'blueprint_ready',
                                            content: isZhLang 
                                                ? '您的课程蓝图已准备就绪！您可以继续生成教学材料，或者先编辑蓝图。'
                                                : 'Your lesson blueprint is ready! You can now generate teaching materials, or edit the blueprint first.'
                                        });
                                    }
                                    
                                    setBlueprint(gen.blueprint);
                                }
                                
                                // Add current package message if exists
                                if (gen.package) {
                                    var hasPackageMsg = restoredConversation.some(function(msg) { return msg.type === 'package'; });
                                    // For regeneration scenario, we filtered out old package messages
                                    if (!hasPackageMsg || hasPackageHistory) {
                                        var pkgVersion = (gen.package && gen.package.version) || 1;
                                        messagesWithBlueprint.push({
                                            role: 'assistant',
                                            type: 'package',
                                            pkg: gen.package,
                                            content: hasPackageHistory ? 'Materials v' + pkgVersion : 'Teaching materials generated'
                                        });
                                    } else if (!hasPackageHistory) {
                                        // Ensure existing package messages have pkg data filled in
                                        for (var pi = 0; pi < messagesWithBlueprint.length; pi++) {
                                            var pmsg = messagesWithBlueprint[pi];
                                            if (pmsg.type === 'package' && !pmsg.pkg && !pmsg.isHistoryVersion) {
                                                messagesWithBlueprint[pi] = Object.assign({}, pmsg, {
                                                    pkg: gen.package
                                                });
                                            }
                                        }
                                    }
                                    setTeachingPackage(gen.package);
                                    // Save blueprint snapshot for change detection on regeneration
                                    if (gen.blueprint) {
                                        // Ensure blueprint has raw_content for future comparisons
                                        var blueprintSnapshot = JSON.parse(JSON.stringify(gen.blueprint));
                                        if (!blueprintSnapshot.raw_content) {
                                            blueprintSnapshot.raw_content = blueprintToMarkdown(gen.blueprint);
                                        }
                                        setLastGeneratedBlueprint(blueprintSnapshot);
                                    }
                                } else {
                                    // CRITICAL: Reset teachingPackage to null when loading a generation without package
                                    // This prevents state carryover from a previously viewed generation that had a package
                                    setTeachingPackage(null);
                                    setLastGeneratedBlueprint(null);
                                }
                                
                                setMessages(messagesWithBlueprint);
                                setView('chat');
                            } else {
                                // Generation not found
                                console.warn('Generation not found, redirecting to home');
                                navigateTo('/');
                            }
                        } catch (e) {
                            console.error('Failed to load generation:', e);
                            // Clear URL and go home
                            navigateTo('/');
                        }
                    } else if (path === 'library') {
                        setView('library');
                    } else if (path === 'chat') {
                        setView('chat');
                    } else {
                        setView('home');
                    }
                };

                handleRoute();
                window.addEventListener('popstate', handleRoute);
                return () => window.removeEventListener('popstate', handleRoute);
            }, [authChecked, currentUser]);
            
            // Load recent generations when user is authenticated
            useEffect(() => {
                if (authChecked && currentUser) {
                    loadRecentGenerations();
                }
            }, [authChecked, currentUser]);
            
            // Scroll to bottom of chat
            useEffect(() => {
                if (chatRef.current) {
                    chatRef.current.scrollTop = chatRef.current.scrollHeight;
                }
            }, [messages]);
            
            // ============================================
            // Auth Handlers
            // ============================================
            
            const handleLogin = (user) => {
                setCurrentUser(user);
            };
            
            const handleLogout = async () => {
                try {
                    await api.logout();
                } catch (e) {
                    // Ignore logout errors
                }
                clearAuthToken();
                setCurrentUser(null);
                setView('home');
                setMessages([]);
                setBlueprint(null);
                setTeachingPackage(null);
                setCurrentGenerationId(null);
                setCurrentGeneration(null);
                // Navigate to home page and update URL
                window.history.pushState({}, '', '/#/');
            };
            
            // ============================================
            // Conditional Renders (after all hooks)
            // ============================================
            
            // Show loading while checking auth
            if (!authChecked) {
                return (
                    <div className="min-h-screen bg-gradient-to-br from-teal-50 via-white to-cyan-50 flex items-center justify-center">
                        <div className="text-center">
                            <span className="material-symbols-outlined animate-spin text-4xl text-primary">progress_activity</span>
                            <p className="text-gray-500 mt-4">Loading...</p>
                        </div>
                    </div>
                );
            }
            
            // Show login page if not authenticated
            if (!currentUser) {
                return <LoginPage onLogin={handleLogin} />;
            }

            // Handle file upload - uploads file and adds to pending attachments
            const handleFileUpload = async (event) => {
                const file = event.target.files[0];
                if (!file) return;
                
                setIsUploading(true);
                const formData = new FormData();
                formData.append('file', file);
                
                try {
                    const response = await fetch('/api/v1/upload-file', {
                        method: 'POST',
                        headers: getAuthHeaders(),
                        body: formData
                    });
                    
                    if (!response.ok) throw new Error('Upload failed');
                    
                    const result = await response.json();
                    
                    // Add to pending attachments (shown in input area, sent with next message)
                    setPendingAttachments(prev => [...prev, {
                        id: Date.now(),
                        filename: result.filename,
                        extracted_text: result.extracted_text,
                        summary: result.summary,
                        analysis_type: result.analysis_type,
                        text_length: result.text_length || 0,
                        file_url: result.file_url || null  // URL to view/download the file
                    }]);
                    
                    if (view === 'home') setView('chat');
                    
                } catch (error) {
                    console.error('File upload error:', error);
                    alert('Failed to upload file. Please try again.');
                } finally {
                    setIsUploading(false);
                }
                
                // Reset file input
                event.target.value = '';
            };
            
            // Remove a pending attachment
            const removePendingAttachment = (attachmentId) => {
                setPendingAttachments(prev => prev.filter(a => a.id !== attachmentId));
            };
            
            // Handle new chat
            const handleNewChat = () => {
                setView('home');
                setMessages([]);
                setBlueprint(null);
                setTeachingPackage(null);
                setExtractedInfo(null);
                setCurrentGenerationId(null);
                setCurrentGeneration(null);
                setShowPackageInGeneration(false);
                setUploadedFiles([]);
                navigateTo('/');
            };

            // Handle send message
            const handleSend = async () => {
                // Allow sending with just attachments (no text)
                if ((!inputValue.trim() && pendingAttachments.length === 0) || isLoading) return;
                
                const userMessage = inputValue.trim();
                const currentAttachments = [...pendingAttachments];
                
                // Clear input and attachments
                setInputValue('');
                setPendingAttachments([]);
                
                // Add attachments to persistent uploadedFiles for blueprint generation
                if (currentAttachments.length > 0) {
                    setUploadedFiles(prev => [...prev, ...currentAttachments]);
                }
                
                // Build user message with attachment info for display
                var displayMessage = userMessage;
                if (currentAttachments.length > 0) {
                    var attachmentInfo = currentAttachments.map(function(a) {
                        return getFileIcon(a.analysis_type) + ' ' + a.filename;
                    }).join(', ');
                    displayMessage = currentAttachments.length > 0 && userMessage 
                        ? userMessage + '\n\n📎 Attached: ' + attachmentInfo
                        : (userMessage || '📎 Attached: ' + attachmentInfo);
                }
                
                // Store attachments with URLs as part of the message object
                var messageAttachments = currentAttachments.map(function(a) {
                    return { filename: a.filename, file_url: a.file_url, analysis_type: a.analysis_type };
                });
                
                setMessages(prev => [...prev, { role: 'user', content: displayMessage, attachments: messageAttachments }]);
                setIsLoading(true);
                
                if (view === 'home') setView('chat');
                
                try {
                    // Include user's message in history (not yet in messages state due to React batching)
                    // Preserve type and attachments for proper message rendering after reload
                    const history = [
                        ...messages.map(m => ({ role: m.role, content: m.content, type: m.type, attachments: m.attachments, thought_text: m.thoughtText })),
                        { role: 'user', content: displayMessage }
                    ];
                    
                    // Combine all uploaded file content (including just-attached files) for blueprint detection
                    var allFiles = [...uploadedFiles, ...currentAttachments];
                    var fileContent = null;
                    if (allFiles.length > 0) {
                        fileContent = allFiles.map(function(f) { 
                            return f.extracted_text || ''; 
                        }).join('\n\n---\n\n');
                    }
                    
                    // Check if user has existing materials (to detect feedback vs new request)
                    var hasExistingMaterials = !!(teachingPackage && teachingPackage.files && teachingPackage.files.length > 0);
                    
                    // Use SSE streaming version for real-time progress feedback
                    const result = await api.analyzeIntentStream(
                        userMessage || 'Please analyze the attached files', 
                        history, 
                        fileContent,
                        hasExistingMaterials,
                        currentGenerationId,
                        function(progress) {
                            // Update AI progress state for UI feedback
                            setAiProgress({ 
                                message: progress.message, 
                                step: progress.step, 
                                total_steps: progress.total_steps,
                                is_ai_thinking: progress.is_ai_thinking || false,
                                thought_text: progress.thought_text || ''
                            });
                        }
                    );
                    setAiProgress(null); // Clear progress when done
                    
                    // Handle feedback status - user is giving feedback or requesting regeneration
                    if (result.status === 'feedback') {
                        // Check if this is a regeneration request (user wants to regenerate package)
                        var userMsgLower = userMessage.toLowerCase();
                        var isRegenerationRequest = (
                            userMsgLower.includes('重新生成') || 
                            userMsgLower.includes('regenerate') ||
                            userMsgLower.includes('重新做') ||
                            userMsgLower.includes('再生成') ||
                            (result.extracted_info && result.extracted_info.suggested_packages && result.extracted_info.suggested_packages.length > 0)
                        );
                        
                        // If we have a blueprint and this is a regeneration request, trigger package generation
                        if (isRegenerationRequest && blueprint && currentGenerationId) {
                            console.log('🔄 Auto-triggering package regeneration from feedback status');
                            setMessages(prev => [...prev, { 
                                role: 'assistant', 
                                content: result.message,
                                thoughtText: result.thought_text || null
                            }]);
                            // Auto-trigger package regeneration with skipUserMessage=true
                            // (user's original message is already in the chat)
                            setTimeout(function() {
                                handleCreateMaterials(true);
                            }, 500);
                            return;
                        }
                        
                        // Otherwise just show the feedback message
                        setMessages(prev => [...prev, { 
                            role: 'assistant', 
                            content: result.message,
                            quickOptions: result.quick_options || [],
                            thoughtText: result.thought_text || null
                        }]);
                        setView('chat');
                        return;
                    }
                    
                    // Handle blueprint_provided status - user uploaded a blueprint file
                    if (result.status === 'blueprint_provided') {
                        setMessages(prev => [...prev, { role: 'assistant', content: result.message, thoughtText: result.thought_text || null }]);
                        
                        // Convert extracted blueprint to proper format
                        var extractedBp = result.extracted_blueprint || {};
                        var blueprintResult = {
                            title: extractedBp.title || 'Lesson Plan',
                            summary: extractedBp.summary || '',
                            metadata: {
                                grade_level: extractedBp.grade_level || '',
                                subject: extractedBp.subject || '',
                                duration_minutes: extractedBp.duration_minutes || 45
                            },
                            learning_objectives: (extractedBp.learning_objectives || []).map(function(obj) {
                                return typeof obj === 'string' ? { text: obj } : obj;
                            }),
                            lesson_flow: (extractedBp.lesson_flow || []).map(function(phase, idx) {
                                return {
                                    title: phase.title || 'Phase ' + (idx + 1),
                                    duration_minutes: phase.duration_minutes || 10,
                                    description: phase.description || '',
                                    phase: phase.phase || ''
                                };
                            }),
                            standards: {
                                primary_standards: extractedBp.standards || []
                            },
                            differentiation_strategies: extractedBp.differentiation_strategies || {}
                        };
                        
                        setBlueprint(blueprintResult);
                        
                        // Add blueprint as a message in the chat
                        setMessages(prev => [...prev, {
                            role: 'assistant',
                            type: 'blueprint',
                            blueprint: blueprintResult,
                            content: 'Blueprint from your uploaded file'
                        }]);
                        
                        // Clear uploaded files after using them
                        setUploadedFiles([]);
                        setView('chat');
                        return;
                    }
                    
                    setExtractedInfo(result.extracted_info);
                    setMessages(prev => [...prev, { 
                        role: 'assistant', 
                        content: result.message,
                        quickOptions: result.quick_options || [],
                        thoughtText: result.thought_text || null
                    }]);
                    
                    // If ready to generate blueprint - show confirmation card for review
                    if (result.status === 'ready_to_generate' && result.confidence >= 0.7) {
                        const info = result.extracted_info;
                        
                        // Detect language for confirmation message
                        var confirmCardMsg = getLocalizedMsg(messages, 
                            "Great! I've gathered all the information. Please review and confirm the details below, or make any edits before generating your blueprint.",
                            "太棒了！我已收集所有信息。请在下方检查并确认详情，或在生成蓝图前进行编辑。"
                        );
                        
                        // Show confirmation card for user to review and select packages
                        setMessages(prev => [...prev, {
                            role: 'assistant',
                            type: 'confirmation',
                            content: confirmCardMsg,
                            extractedInfo: info,
                            thoughtText: result.thought_text || null
                        }]);
                        setView('chat');
                    }
                } catch (error) {
                    console.error('Error:', error);
                    var errorMsg = detectLanguage() === 'zh'
                        ? "🔄 遇到临时问题，请重新发送您的消息或刷新页面后重试。"
                        : "🔄 Encountered a temporary issue. Please resend your message or refresh the page and try again.";
                    setMessages(prev => [...prev, { role: 'assistant', content: errorMsg }]);
                } finally {
                    setIsLoading(false);
                }
            };

            // Handle quick option click - sends the selected option as a message
            // option can be either { label, value } object or a string (for backward compatibility)
            const handleQuickOptionSend = async (option) => {
                if (isLoading) return;
                
                // Support both object { label, value } and string formats
                var displayText = typeof option === 'object' ? option.label : option;
                var valueText = typeof option === 'object' ? option.value : option;
                
                // Show the label (Chinese) to user, but send value to backend for processing
                setMessages(prev => [...prev, { role: 'user', content: displayText }]);
                setIsLoading(true);
                
                if (view === 'home') setView('chat');
                
                try {
                    // Include user's option in history (not yet in messages state due to React batching)
                    // Preserve type and attachments for proper message rendering after reload
                    // Use displayText (label) for history to maintain language consistency
                    const history = [
                        ...messages.map(m => ({ role: m.role, content: m.content, type: m.type, attachments: m.attachments, thought_text: m.thoughtText })),
                        { role: 'user', content: displayText }
                    ];
                    
                    // Check if user has existing materials
                    var hasExistingMaterials = !!(teachingPackage && teachingPackage.files && teachingPackage.files.length > 0);
                    
                    // Send the value to backend for intent analysis (SSE streaming version)
                    const result = await api.analyzeIntentStream(
                        valueText, history, null, hasExistingMaterials, currentGenerationId,
                        function(progress) {
                            setAiProgress({ message: progress.message, step: progress.step, total_steps: progress.total_steps, is_ai_thinking: progress.is_ai_thinking || false, thought_text: progress.thought_text || '' });
                        }
                    );
                    setAiProgress(null); // Clear progress when done
                    
                    // Handle feedback status - check if regeneration is requested
                    if (result.status === 'feedback') {
                        var valueLower = valueText.toLowerCase();
                        var isRegenRequest = (
                            valueLower.includes('重新生成') || 
                            valueLower.includes('regenerate') ||
                            valueLower.includes('重新做') ||
                            valueLower.includes('再生成') ||
                            (result.extracted_info && result.extracted_info.suggested_packages && result.extracted_info.suggested_packages.length > 0)
                        );
                        
                        // If we have a blueprint and this is a regeneration request, trigger package generation
                        if (isRegenRequest && blueprint && currentGenerationId) {
                            console.log('🔄 Auto-triggering package regeneration from feedback status (generation context)');
                            setMessages(prev => [...prev, { 
                                role: 'assistant', 
                                content: result.message,
                                thoughtText: result.thought_text || null
                            }]);
                            // Auto-trigger package regeneration with skipUserMessage=true
                            // (user's original message is already in the chat)
                            setTimeout(function() {
                                handleCreateMaterials(true);
                            }, 500);
                            return;
                        }
                        
                        setMessages(prev => [...prev, { 
                            role: 'assistant', 
                            content: result.message,
                            quickOptions: result.quick_options || [],
                            thoughtText: result.thought_text || null
                        }]);
                        setView('chat');
                        return;
                    }
                    
                    setExtractedInfo(result.extracted_info);
                    setMessages(prev => [...prev, { 
                        role: 'assistant', 
                        content: result.message,
                        quickOptions: result.quick_options || [],
                        thoughtText: result.thought_text || null
                    }]);
                    
                    // If ready to generate blueprint - show confirmation card for review
                    if (result.status === 'ready_to_generate' && result.confidence >= 0.7) {
                        const info = result.extracted_info;
                        
                        // Detect language for confirmation message
                        var confirmCardMsgQuick = getLocalizedMsg(messages, 
                            "Great! I've gathered all the information. Please review and confirm the details below, or make any edits before generating your blueprint.",
                            "太棒了！我已收集所有信息。请在下方检查并确认详情，或在生成蓝图前进行编辑。"
                        );
                        
                        // Show confirmation card for user to review and select packages
                        setMessages(prev => [...prev, {
                            role: 'assistant',
                            type: 'confirmation',
                            content: confirmCardMsgQuick,
                            extractedInfo: info,
                            thoughtText: result.thought_text || null
                        }]);
                        setView('chat');
                    }
                } catch (error) {
                    console.error('Quick option error:', error);
                    var errorMsg = detectLanguage() === 'zh'
                        ? "🔄 遇到临时问题，请重新点击选项或输入您的回复。"
                        : "🔄 Encountered a temporary issue. Please click the option again or type your response.";
                    setMessages(prev => [...prev, { role: 'assistant', content: errorMsg }]);
                } finally {
                    setIsLoading(false);
                }
            };

            // Handle confirmed blueprint generation
            const handleConfirmGenerate = async (confirmedInfo) => {
                setIsLoading(true);
                setIsGeneratingBlueprint(true);
                
                // Detect language from topic
                var isZhTopic = confirmedInfo.topic && /[\u4e00-\u9fa5]/.test(confirmedInfo.topic);
                
                // Save the confirmed lesson info for display (including selected packages)
                setConfirmedLessonInfo(confirmedInfo);
                
                // Add a summary of confirmed info as user message
                var summaryParts = [];
                if (confirmedInfo.topic) summaryParts.push((isZhTopic ? '主题: ' : 'Topic: ') + confirmedInfo.topic);
                if (confirmedInfo.grade) summaryParts.push((isZhTopic ? '年级: ' : 'Grade: ') + confirmedInfo.grade);
                if (confirmedInfo.subject) summaryParts.push((isZhTopic ? '学科: ' : 'Subject: ') + confirmedInfo.subject);
                if (confirmedInfo.duration) summaryParts.push((isZhTopic ? '时长: ' : 'Duration: ') + confirmedInfo.duration + (isZhTopic ? ' 分钟' : ' min'));
                if (confirmedInfo.teaching_style) summaryParts.push((isZhTopic ? '教学风格: ' : 'Style: ') + confirmedInfo.teaching_style);
                
                // Add selected packages to summary
                if (confirmedInfo.selectedPackages && confirmedInfo.selectedPackages.length > 0) {
                    var pkgLabels = {
                        slide: isZhTopic ? '互动课件' : 'Slides',
                        lesson_plan: isZhTopic ? '教案' : 'Lesson Plan',
                        worksheet: isZhTopic ? '学生练习' : 'Worksheet',
                        quiz: isZhTopic ? '测验' : 'Quiz',
                        exit_ticket: isZhTopic ? '出门检测' : 'Exit Ticket',
                        group_activity: isZhTopic ? '小组活动' : 'Group Activity',
                        rubric: isZhTopic ? '评分标准' : 'Rubric',
                        vocabulary_cards: isZhTopic ? '词汇卡片' : 'Vocabulary Cards'
                    };
                    var selectedLabels = confirmedInfo.selectedPackages.map(function(p) { return pkgLabels[p] || p; });
                    summaryParts.push((isZhTopic ? '生成材料: ' : 'Materials: ') + selectedLabels.join(', '));
                }
                
                // Detect language for user confirmation message
                var confirmMsgPrefix = isZhTopic ? "确认！按以下信息生成蓝图：" : "Confirmed! Generate blueprint with:";
                setMessages(prev => [...prev, { 
                    role: 'user', 
                    content: confirmMsgPrefix + "\n" + summaryParts.join(' | ')
                }]);
                
                // Add a generating message
                var generatingMsgConfirm = isZhTopic 
                    ? "太棒了！正在为您生成课程蓝图..."
                    : "Perfect! Generating your lesson blueprint now...";
                setMessages(prev => [...prev, { 
                    role: 'assistant', 
                    content: generatingMsgConfirm
                }]);
                
                try {
                    // Preserve type, attachments, and thought_text for proper message rendering after reload
                    const fullConversation = messages.map(m => ({ role: m.role, content: m.content, type: m.type, attachments: m.attachments, thought_text: m.thoughtText }));
                    
                    // Combine confirmed additional_context with uploaded file content
                    var confirmedCombinedCtx = confirmedInfo.additional_context || '';
                    if (uploadedFiles.length > 0) {
                        var confirmedFileParts = uploadedFiles.map(function(f) {
                            return '--- Uploaded Reference: ' + f.filename + ' ---\n' + (f.extracted_text || '');
                        }).join('\n\n');
                        confirmedCombinedCtx = confirmedCombinedCtx ? confirmedCombinedCtx + '\n\n' + confirmedFileParts : confirmedFileParts;
                    }
                    
                    // Use SSE streaming version for real-time progress feedback
                    const blueprintResult = await api.generateBlueprintStream({
                        topic: confirmedInfo.topic,
                        grade: confirmedInfo.grade || '5',
                        subject: confirmedInfo.subject || '',
                        duration: parseInt(confirmedInfo.duration) || 45,
                        objectives: confirmedInfo.objectives || [],
                        special_requirements: confirmedInfo.special_requirements || [],
                        additional_context: confirmedCombinedCtx,
                        teaching_style: confirmedInfo.teaching_style || '',
                        activities: confirmedInfo.activities || [],
                        student_context: confirmedInfo.student_context || '',
                        assessment_type: confirmedInfo.assessment_type || '',
                        selected_packages: confirmedInfo.selectedPackages || ['slide', 'lesson_plan']
                    }, fullConversation, (function() {
                        // Throttle partial_content updates to prevent UI freezing during streaming
                        // Complex regex parsing in tryParseStreamingBlueprint can block the main thread
                        var lastUpdateTime = 0;
                        var pendingProgress = null;
                        var throttleTimeout = null;
                        var THROTTLE_INTERVAL = 300; // ms - update UI at most every 300ms
                        
                        return function(progress) {
                            var now = Date.now();
                            var hasPartialContent = progress.partial_content && progress.partial_content.length > 0;
                            
                            // Always update immediately for non-writing progress (status messages)
                            if (!progress.is_writing || !hasPartialContent) {
                                setAiProgress({ 
                                    message: progress.message, 
                                    step: progress.step, 
                                    total_steps: progress.total_steps, 
                                    is_ai_thinking: progress.is_ai_thinking || false, 
                                    thought_text: progress.thought_text || '',
                                    is_writing: progress.is_writing || false,
                                    partial_content: progress.partial_content || ''
                                });
                                return;
                            }
                            
                            // For streaming content, apply throttling
                            pendingProgress = progress;
                            
                            // If enough time has passed, update immediately
                            if (now - lastUpdateTime >= THROTTLE_INTERVAL) {
                                lastUpdateTime = now;
                                setAiProgress({ 
                                    message: progress.message, 
                                    step: progress.step, 
                                    total_steps: progress.total_steps, 
                                    is_ai_thinking: progress.is_ai_thinking || false, 
                                    thought_text: progress.thought_text || '',
                                    is_writing: progress.is_writing || false,
                                    partial_content: progress.partial_content || ''
                                });
                            } else if (!throttleTimeout) {
                                // Schedule update for the end of throttle interval
                                throttleTimeout = setTimeout(function() {
                                    throttleTimeout = null;
                                    lastUpdateTime = Date.now();
                                    if (pendingProgress) {
                                        setAiProgress({ 
                                            message: pendingProgress.message, 
                                            step: pendingProgress.step, 
                                            total_steps: pendingProgress.total_steps, 
                                            is_ai_thinking: pendingProgress.is_ai_thinking || false, 
                                            thought_text: pendingProgress.thought_text || '',
                                            is_writing: pendingProgress.is_writing || false,
                                            partial_content: pendingProgress.partial_content || ''
                                        });
                                    }
                                }, THROTTLE_INTERVAL - (now - lastUpdateTime));
                            }
                        };
                    })());
                    setAiProgress(null); // Clear progress when done
                    
                    // Extract blueprint and generation_id from result
                    var blueprintData = blueprintResult.blueprint;
                    var newGenerationId = blueprintResult.generation_id;
                    
                    // Add selected packages to blueprint result
                    blueprintData.selected_packages = confirmedInfo.selectedPackages || ['slide', 'lesson_plan'];
                    
                    setBlueprint(blueprintData);
                    
                    // CRITICAL: Immediately set the new generation ID to prevent overwriting old generations
                    if (newGenerationId) {
                        setCurrentGenerationId(newGenerationId);
                        console.log('📝 New blueprint created with generation_id:', newGenerationId);
                    }
                    
                    await loadRecentGenerations();
                    
                    // Add blueprint as a message (with thought_text and generationId)
                    setMessages(prev => [...prev, {
                        role: 'assistant',
                        type: 'blueprint',
                        blueprint: blueprintData,
                        content: 'Blueprint generated successfully',
                        thoughtText: blueprintData.thought_text || null,
                        generationId: newGenerationId  // Include the new generation ID
                    }]);
                    
                    // Add post-blueprint guidance message with quick options (localized)
                    var blueprintReadyMsg = isZhTopic
                        ? "Blueprint 已生成完成！您可以点击上方预览并编辑，或直接开始生成教学材料。"
                        : "Blueprint ready! You can preview and edit above, or start generating teaching materials.";
                    setMessages(prev => [...prev, {
                        role: 'assistant',
                        type: 'blueprint_ready',
                        content: blueprintReadyMsg
                    }]);
                    
                    // Clear uploaded files
                    setUploadedFiles([]);
                    
                    // Navigate to the new generation view
                    if (newGenerationId) {
                        const newGen = await api.getGeneration(newGenerationId);
                        if (newGen) {
                            setCurrentGeneration(newGen);
                            navigateTo(`/generation/${newGenerationId}`);
                        }
                    }
                    setView('chat');
                } catch (error) {
                    console.error('Blueprint generation error:', error);
                    var errorMsg = isZhTopic
                        ? "🔄 生成蓝图时遇到临时问题，请点击确认卡片上的「✨ 生成蓝图」按钮重试。"
                        : "🔄 Encountered an issue while generating the blueprint. Please click the '✨ Generate Blueprint' button on the confirmation card to retry.";
                    setMessages(prev => [...prev, { 
                        role: 'assistant', 
                        content: errorMsg
                    }]);
                } finally {
                    setIsLoading(false);
                    setIsGeneratingBlueprint(false);
                }
            };

            // Handle blueprint save (from markdown edit)
            const handleBlueprintSave = (markdown) => {
                console.log('Blueprint markdown saved:', markdown);
                if (blueprint) {
                    // Parse markdown to extract updated metadata
                    const updatedBlueprint = { ...blueprint, raw_content: markdown };
                    
                    // Extract title from first # heading
                    const titleMatch = markdown.match(/^#\s+(.+)$/m);
                    if (titleMatch) {
                        updatedBlueprint.title = titleMatch[1].trim();
                    }
                    
                    // Extract metadata line: **Grade:** X | **Subject:** Y | **Duration:** Z minutes
                    const metadataMatch = markdown.match(/\*\*Grade:\*\*\s*([^|]+)\s*\|\s*\*\*Subject:\*\*\s*([^|]+)\s*\|\s*\*\*Duration:\*\*\s*(\d+)\s*minutes/i);
                    if (metadataMatch) {
                        updatedBlueprint.metadata = {
                            ...updatedBlueprint.metadata,
                            grade_level: metadataMatch[1].trim(),
                            subject: metadataMatch[2].trim(),
                            duration_minutes: parseInt(metadataMatch[3], 10)
                        };
                    }
                    
                    // Extract summary (text between title and metadata line)
                    const summaryMatch = markdown.match(/^#\s+.+\n+(.+?)(?=\n+\*\*Grade:\*\*)/s);
                    if (summaryMatch) {
                        updatedBlueprint.summary = summaryMatch[1].trim();
                    }
                    
                    setBlueprint(updatedBlueprint);
                    
                    // Mark blueprint as modified since last material generation
                    // This enables the Regenerate button to appear
                    if (teachingPackage !== null) {
                        setBlueprintModifiedSinceGeneration(true);
                    }
                    
                    // Update the message in the messages array with incremented version to force re-render
                    setMessages(prev => prev.map(msg => 
                        msg.type === 'blueprint' ? { 
                            ...msg, 
                            blueprint: updatedBlueprint,
                            blueprintVersion: (msg.blueprintVersion || 0) + 1
                        } : msg
                    ));
                }
            };

            // Handle blueprint adjustment
            const handleAdjust = (sectionId) => {
                setAdjustSection(sectionId);
                setAdjustModalOpen(true);
            };

            const handleAdjustSubmit = async (sectionId, instructions) => {
                setAdjustModalOpen(false);
                setIsLoading(true);
                
                try {
                    const updatedBlueprint = await api.adjustBlueprint(blueprint, sectionId, instructions);
                    setBlueprint(updatedBlueprint);
                    
                    // Update the blueprint message
                    setMessages(prev => prev.map(msg => 
                        msg.type === 'blueprint' ? { ...msg, blueprint: updatedBlueprint } : msg
                    ));
                } catch (error) {
                    console.error('Error adjusting blueprint:', error);
                } finally {
                    setIsLoading(false);
                }
            };

            // Handle create materials - now shows progress in chat
            // skipUserMessage: if true, don't add a synthetic user message (used when triggered from chat)
            const handleCreateMaterials = async (skipUserMessage = false) => {
                // Set generating state to disable buttons
                setIsGeneratingMaterials(true);
                
                // Only show "Generating from Blueprint" context card on REGENERATION (not first generation)
                // On first generation, the blueprint is already visible in the chat above
                var isRegeneration = teachingPackage !== null;
                
                if (isRegeneration) {
                    // Compare blueprints to find what changed
                    var changes = [];
                    
                    // If we have a snapshot of the last generated blueprint, compare in detail
                    if (lastGeneratedBlueprint) {
                        var currentMeta = blueprint.metadata || {};
                        var oldMeta = lastGeneratedBlueprint.metadata || {};
                        
                        // Check title change
                        if (blueprint.title !== lastGeneratedBlueprint.title) {
                            changes.push('标题');
                        }
                        
                        // Check metadata changes
                        if (currentMeta.topic !== oldMeta.topic) changes.push('主题');
                        if (currentMeta.grade_level !== oldMeta.grade_level) changes.push('年级');
                        if (currentMeta.subject !== oldMeta.subject) changes.push('学科');
                        if (currentMeta.duration_minutes !== oldMeta.duration_minutes) changes.push('时长');
                        if (currentMeta.teaching_style !== oldMeta.teaching_style) changes.push('教学风格');
                        
                        // Check learning objectives
                        var currentObjs = JSON.stringify(blueprint.learning_objectives || []);
                        var oldObjs = JSON.stringify(lastGeneratedBlueprint.learning_objectives || []);
                        if (currentObjs !== oldObjs) changes.push('学习目标');
                        
                        // Check lesson flow
                        var currentFlow = JSON.stringify(blueprint.lesson_flow || []);
                        var oldFlow = JSON.stringify(lastGeneratedBlueprint.lesson_flow || []);
                        if (currentFlow !== oldFlow) changes.push('教学流程');
                        
                        // Check assessments
                        var currentAssess = JSON.stringify(blueprint.assessments || []);
                        var oldAssess = JSON.stringify(lastGeneratedBlueprint.assessments || []);
                        if (currentAssess !== oldAssess) changes.push('评估方式');
                        
                        // Check raw content (markdown) and try to detect specific section changes
                        var currentRaw = blueprint.raw_content || '';
                        var oldRaw = lastGeneratedBlueprint.raw_content || '';
                        if (currentRaw && currentRaw !== oldRaw) {
                            // If old raw content doesn't exist, we can't compare sections
                            // but we know something changed since raw_content was set
                            if (!oldRaw) {
                                if (changes.length === 0) {
                                    changes.push('课程内容细节');
                                }
                            } else {
                                // Extract sections from markdown to detect what changed
                                var extractSections = function(md) {
                                    var sections = {};
                                    var lines = md.split('\n');
                                    var currentSection = '';
                                    var content = [];
                                    for (var i = 0; i < lines.length; i++) {
                                        var line = lines[i];
                                        var match = line.match(/^##\s+(.+)$/);
                                        if (match) {
                                            if (currentSection) {
                                                sections[currentSection] = content.join('\n');
                                            }
                                            currentSection = match[1].trim();
                                            content = [];
                                        } else if (currentSection) {
                                            content.push(line);
                                        }
                                    }
                                    if (currentSection) {
                                        sections[currentSection] = content.join('\n');
                                    }
                                    return sections;
                                };
                                
                                var currentSections = extractSections(currentRaw);
                                var oldSections = extractSections(oldRaw);
                                var sectionChanges = [];
                                
                                // Check each section
                                var allSectionNames = Object.keys(Object.assign({}, currentSections, oldSections));
                                for (var s = 0; s < allSectionNames.length; s++) {
                                    var sectionName = allSectionNames[s];
                                    if (currentSections[sectionName] !== oldSections[sectionName]) {
                                        // Map English section names to Chinese
                                        var sectionNameMap = {
                                            'Learning Objectives': '学习目标',
                                            'Standards Alignment': '课程标准',
                                            'Lesson Flow': '教学流程',
                                            'Differentiation Strategies': '差异化策略',
                                            'Assessment Strategies': '评估策略',
                                            'Materials & Resources': '教学资源',
                                            'Overview': '概述'
                                        };
                                        var displayName = sectionNameMap[sectionName] || sectionName;
                                        if (changes.indexOf(displayName) === -1 && sectionChanges.indexOf(displayName) === -1) {
                                            sectionChanges.push(displayName);
                                        }
                                    }
                                }
                                
                                // Add section changes that aren't already in changes
                                for (var j = 0; j < sectionChanges.length; j++) {
                                    if (changes.indexOf(sectionChanges[j]) === -1) {
                                        changes.push(sectionChanges[j]);
                                    }
                                }
                                
                                // If no specific sections detected but raw content changed
                                if (changes.length === 0) {
                                    changes.push('课程内容细节');
                                }
                            }
                        }
                    } else {
                        // No snapshot available - use generic message (will be localized later)
                        changes.push('content');
                    }
                    
                    // Detect language from conversation
                    var userLang = (function() {
                        var userMsgs = messages.filter(function(m) { return m.role === 'user'; });
                        var lastUserContent = userMsgs.length > 0 ? userMsgs[userMsgs.length - 1].content : '';
                        return isChinese(lastUserContent) ? 'zh' : 'en';
                    })();
                    
                    // Change name translations
                    var changeNameMap = {
                        '标题': { en: 'title', zh: '标题' },
                        '主题': { en: 'topic', zh: '主题' },
                        '年级': { en: 'grade level', zh: '年级' },
                        '学科': { en: 'subject', zh: '学科' },
                        '时长': { en: 'duration', zh: '时长' },
                        '教学风格': { en: 'teaching style', zh: '教学风格' },
                        '学习目标': { en: 'learning objectives', zh: '学习目标' },
                        '教学流程': { en: 'lesson flow', zh: '教学流程' },
                        '评估方式': { en: 'assessments', zh: '评估方式' },
                        '课程标准': { en: 'standards alignment', zh: '课程标准' },
                        '差异化策略': { en: 'differentiation strategies', zh: '差异化策略' },
                        '评估策略': { en: 'assessment strategies', zh: '评估策略' },
                        '教学资源': { en: 'materials & resources', zh: '教学资源' },
                        '概述': { en: 'overview', zh: '概述' },
                        '课程内容细节': { en: 'content details', zh: '课程内容细节' },
                        '课程内容': { en: 'content', zh: '课程内容' },
                        'content': { en: 'content', zh: '课程内容' }
                    };
                    
                    // Localize change names
                    var localizedChanges = changes.map(function(c) {
                        var mapped = changeNameMap[c];
                        return mapped ? mapped[userLang] : c;
                    });
                    
                    // Generate detailed change description
                    var changeDesc = '';
                    var joinStr = userLang === 'zh' ? '、' : ', ';
                    if (localizedChanges.length > 0) {
                        changeDesc = '**' + localizedChanges.join(joinStr) + '**';
                    } else {
                        changeDesc = userLang === 'zh' ? '**课程内容**' : '**content**';
                    }
                    
                    // Add user message indicating they want to regenerate with modified blueprint
                    // Skip if triggered from chat (user message already exists)
                    var userRegenMsg = skipUserMessage ? null : {
                        id: Date.now() - 2,
                        role: 'user',
                        content: userLang === 'zh' 
                            ? '我已修改 Blueprint，请重新生成教学材料。'
                            : 'I\'ve modified the Blueprint, please regenerate teaching materials.'
                    };
                    
                    // Generate detailed change diff for user feedback
                    var detailedChanges = [];
                    if (lastGeneratedBlueprint) {
                        // Title change
                        if (blueprint.title !== lastGeneratedBlueprint.title) {
                            detailedChanges.push({
                                field: userLang === 'zh' ? '标题' : 'Title',
                                from: lastGeneratedBlueprint.title || '',
                                to: blueprint.title || ''
                            });
                        }
                        // Duration change
                        var currentMeta = blueprint.metadata || {};
                        var oldMeta = lastGeneratedBlueprint.metadata || {};
                        if (currentMeta.duration_minutes !== oldMeta.duration_minutes) {
                            detailedChanges.push({
                                field: userLang === 'zh' ? '时长' : 'Duration',
                                from: (oldMeta.duration_minutes || 45) + (userLang === 'zh' ? ' 分钟' : ' min'),
                                to: (currentMeta.duration_minutes || 45) + (userLang === 'zh' ? ' 分钟' : ' min')
                            });
                        }
                        // Grade change
                        if (currentMeta.grade_level !== oldMeta.grade_level) {
                            detailedChanges.push({
                                field: userLang === 'zh' ? '年级' : 'Grade',
                                from: oldMeta.grade_level || '',
                                to: currentMeta.grade_level || ''
                            });
                        }
                        // Learning objectives change
                        var currentObjs = blueprint.learning_objectives || [];
                        var oldObjs = lastGeneratedBlueprint.learning_objectives || [];
                        if (JSON.stringify(currentObjs) !== JSON.stringify(oldObjs)) {
                            var objDiff = {
                                field: userLang === 'zh' ? '学习目标' : 'Learning Objectives',
                                details: []
                            };
                            // Find added objectives
                            currentObjs.forEach(function(obj, idx) {
                                var objText = typeof obj === 'string' ? obj : (obj.text || obj.objective || '');
                                var oldObj = oldObjs[idx];
                                var oldText = oldObj ? (typeof oldObj === 'string' ? oldObj : (oldObj.text || oldObj.objective || '')) : null;
                                if (!oldText) {
                                    objDiff.details.push((userLang === 'zh' ? '+ 新增: ' : '+ Added: ') + objText.substring(0, 50) + (objText.length > 50 ? '...' : ''));
                                } else if (objText !== oldText) {
                                    objDiff.details.push((userLang === 'zh' ? '~ 修改: ' : '~ Changed: ') + objText.substring(0, 40) + '...');
                                }
                            });
                            if (objDiff.details.length > 0) {
                                detailedChanges.push(objDiff);
                            }
                        }
                        // Lesson flow change
                        var currentFlow = blueprint.lesson_flow || [];
                        var oldFlow = lastGeneratedBlueprint.lesson_flow || [];
                        if (JSON.stringify(currentFlow) !== JSON.stringify(oldFlow)) {
                            var flowDiff = {
                                field: userLang === 'zh' ? '教学流程' : 'Lesson Flow',
                                details: []
                            };
                            currentFlow.forEach(function(phase, idx) {
                                var oldPhase = oldFlow[idx];
                                if (!oldPhase) {
                                    flowDiff.details.push((userLang === 'zh' ? '+ 新增阶段: ' : '+ New phase: ') + (phase.title || phase.phase || ''));
                                } else if (phase.title !== oldPhase.title || phase.duration_minutes !== oldPhase.duration_minutes) {
                                    flowDiff.details.push((userLang === 'zh' ? '~ 修改: ' : '~ Changed: ') + (phase.title || phase.phase || '') + 
                                        (phase.duration_minutes !== oldPhase.duration_minutes ? 
                                            ' (' + oldPhase.duration_minutes + '→' + phase.duration_minutes + (userLang === 'zh' ? '分钟)' : 'min)') : ''));
                                }
                            });
                            if (flowDiff.details.length > 0) {
                                detailedChanges.push(flowDiff);
                            }
                        }
                    }
                    
                    // Build detailed change description text
                    var detailedChangeText = '';
                    if (detailedChanges.length > 0) {
                        detailedChangeText = '\n\n📝 ' + (userLang === 'zh' ? '**具体修改内容：**' : '**Specific changes:**');
                        detailedChanges.forEach(function(change) {
                            if (change.from !== undefined && change.to !== undefined) {
                                detailedChangeText += '\n• **' + change.field + '**: `' + change.from + '` → `' + change.to + '`';
                            } else if (change.details && change.details.length > 0) {
                                detailedChangeText += '\n• **' + change.field + '**:';
                                change.details.slice(0, 3).forEach(function(d) {
                                    detailedChangeText += '\n  ' + d;
                                });
                                if (change.details.length > 3) {
                                    detailedChangeText += '\n  ' + (userLang === 'zh' ? '...还有 ' + (change.details.length - 3) + ' 项修改' : '...and ' + (change.details.length - 3) + ' more changes');
                                }
                            }
                        });
                    }
                    
                    // Generate thoughtful acknowledgment based on changes (localized)
                    var thoughtProcess = '';
                    var hasObjectives = changes.includes('学习目标') || changes.includes('Learning Objectives');
                    var hasFlow = changes.includes('教学流程') || changes.includes('Lesson Flow');
                    var hasDuration = changes.includes('时长');
                    var hasGradeOrStyle = changes.includes('年级') || changes.includes('教学风格');
                    
                    if (userLang === 'zh') {
                        thoughtProcess = '\n\n🔄 **重新生成策略：**';
                        if (hasObjectives) {
                            thoughtProcess += '\n• 学习目标调整 → 重新设计活动和评估方式';
                        }
                        if (hasFlow) {
                            thoughtProcess += '\n• 教学流程修改 → 更新课件结构和互动环节';
                        }
                        if (hasDuration) {
                            thoughtProcess += '\n• 时长变化 → 重新平衡各环节内容深度';
                        }
                        if (hasGradeOrStyle) {
                            thoughtProcess += '\n• 年级/风格变化 → 调整语言难度和互动形式';
                        }
                        if (!hasObjectives && !hasFlow && !hasDuration && !hasGradeOrStyle) {
                            thoughtProcess += '\n• 仔细检查所有修改，确保材料与 Blueprint 完全一致';
                        }
                    } else {
                        thoughtProcess = '\n\n🔄 **Regeneration strategy:**';
                        if (hasObjectives) {
                            thoughtProcess += '\n• Learning objectives changed → Redesign activities and assessments';
                        }
                        if (hasFlow) {
                            thoughtProcess += '\n• Lesson flow modified → Update slide structure and interactions';
                        }
                        if (hasDuration) {
                            thoughtProcess += '\n• Duration changed → Rebalance content depth';
                        }
                        if (hasGradeOrStyle) {
                            thoughtProcess += '\n• Grade/style changed → Adjust language and interaction level';
                        }
                        if (!hasObjectives && !hasFlow && !hasDuration && !hasGradeOrStyle) {
                            thoughtProcess += '\n• Review all changes to ensure perfect alignment';
                        }
                    }
                    
                    // Add Tess acknowledgment message with details
                    var ackContent = userLang === 'zh'
                        ? '好的，我注意到您修改了 Blueprint 的 ' + changeDesc + '。' + detailedChangeText + thoughtProcess + '\n\n⏳ 正在根据更新后的内容重新生成教学材料...'
                        : 'Got it! I noticed you\'ve modified the Blueprint\'s ' + changeDesc + '.' + detailedChangeText + thoughtProcess + '\n\n⏳ Regenerating teaching materials based on the updates...';
                    
                    var assistantAckMsg = {
                        id: Date.now() - 1,
                        role: 'assistant',
                        content: ackContent
                    };
                    
                    // Build updated messages array with regeneration context
                    var updatedMessages = messages.map(function(msg) {
                        if (msg.type === 'blueprint') {
                            return Object.assign({}, msg, { isReadOnly: true });
                        }
                        return msg;
                    });
                    // Add user message only if not triggered from chat (user message already exists)
                    if (userRegenMsg) {
                        updatedMessages.push(userRegenMsg);
                    }
                    updatedMessages.push(assistantAckMsg);
                    
                    setMessages(updatedMessages);
                    
                    // Small delay to let users see the acknowledgment
                    await new Promise(resolve => setTimeout(resolve, 800));
                    
                    // Show the current blueprint being used as context for regeneration
                    var blueprintMsg = {
                        id: Date.now(),
                        role: 'assistant',
                        type: 'blueprint',
                        blueprint: blueprint,
                        content: 'Blueprint being used for generation',
                        isGenerationContext: true  // Flag to indicate this is the generation context
                    };
                    updatedMessages = updatedMessages.concat([blueprintMsg]);
                    setMessages(updatedMessages);
                    
                    // Small delay to let users see the blueprint context
                    await new Promise(resolve => setTimeout(resolve, 300));
                }
                
                // Determine which messages to send to API
                // For regeneration, use updatedMessages (includes regen context)
                // For first generation, use original messages
                var conversationToSend = typeof updatedMessages !== 'undefined' ? updatedMessages : messages;
                
                // Add a generating message to the chat
                var generatingMsgId = Date.now();
                // Get selected packages from blueprint for display
                var packagesToGenerate = blueprint.selected_packages || ['slide', 'lesson_plan', 'worksheet', 'quiz', 'exit_ticket'];
                setMessages(function(prev) {
                    return prev.concat([{
                        id: generatingMsgId,
                        role: 'assistant',
                        type: 'generating',
                        phase: 'Initializing...',
                        progress: 5,
                        content: 'Creating teaching materials...',
                        selectedPackages: packagesToGenerate
                    }]);
                });
                
                // Scroll to bottom
                setTimeout(function() {
                    if (chatRef.current) {
                        chatRef.current.scrollTop = chatRef.current.scrollHeight;
                    }
                }, 100);
                
                try {
                    // If currentGenerationId exists, this is a regeneration - pass it to update existing generation
                    var response = await api.generatePackage(blueprint, conversationToSend, currentGenerationId);
                    var reader = response.body.getReader();
                    var decoder = new TextDecoder();
                    var currentPhase = 'Initializing...';
                    var currentProgress = 10;
                    var currentDetailLog = '';
                    var activityLogs = [];
                    // NEW: Track step status explicitly for reliable UI updates
                    var completedSteps = [];
                    var currentStep = null;
                    var slidePreview = null;  // For SSE slide preview
                    
                    // Throttle for UI updates to prevent lag during rapid SSE events
                    var lastUIUpdateTime = 0;
                    var pendingUIUpdate = null;
                    var UI_THROTTLE_INTERVAL = 200; // ms - update UI at most every 200ms
                    
                    var updateGeneratingMessage = function() {
                        // Update both messages array AND standalone state for GeneratingView
                        setGeneratingPhase(currentPhase);
                        setGeneratingProgress(currentProgress);
                        // Also update generatingSteps for GeneratingView
                        setGeneratingSteps({
                            completedSteps: completedSteps.slice(),
                            currentStep: currentStep
                        });
                        
                        setMessages(function(prev) {
                            return prev.map(function(msg) {
                                if (msg.id === generatingMsgId) {
                                    return Object.assign({}, msg, { 
                                        phase: currentPhase, 
                                        progress: currentProgress,
                                        detailLog: currentDetailLog,
                                        activityLogs: activityLogs.slice(-12),
                                        completedSteps: completedSteps.slice(),
                                        currentStep: currentStep,
                                        slidePreview: slidePreview
                                    });
                                }
                                return msg;
                            });
                        });
                    };
                    
                    var throttledUIUpdate = function(forceUpdate) {
                        var now = Date.now();
                        if (forceUpdate || now - lastUIUpdateTime >= UI_THROTTLE_INTERVAL) {
                            lastUIUpdateTime = now;
                            if (pendingUIUpdate) {
                                clearTimeout(pendingUIUpdate);
                                pendingUIUpdate = null;
                            }
                            updateGeneratingMessage();
                        } else if (!pendingUIUpdate) {
                            pendingUIUpdate = setTimeout(function() {
                                pendingUIUpdate = null;
                                lastUIUpdateTime = Date.now();
                                updateGeneratingMessage();
                            }, UI_THROTTLE_INTERVAL - (now - lastUIUpdateTime));
                        }
                    };
                    
                    while (true) {
                        var result = await reader.read();
                        if (result.done) break;
                        
                        var text = decoder.decode(result.value);
                        var lines = text.split('\n').filter(function(l) { return l.startsWith('data: '); });
                        
                        for (var i = 0; i < lines.length; i++) {
                            var line = lines[i];
                            try {
                                var data = JSON.parse(line.slice(6));
                                
                                if (data.type === 'start') {
                                    currentPhase = data.message;
                                    currentProgress = 10;
                                    activityLogs.push('▶ ' + data.message);
                                } else if (data.type === 'keepalive') {
                                    // Keepalive to prevent proxy timeout, just update phase
                                    currentPhase = data.message || 'Still working...';
                                } else if (data.type === 'detail') {
                                    // Detail progress (per-slide updates)
                                    currentDetailLog = data.message;
                                    // CRITICAL: Also update phase so UI step status updates in real-time
                                    if (data.phase) {
                                        currentPhase = data.message;
                                        currentStep = data.phase;
                                    }
                                    // Add to activity log for visual feedback
                                    if (data.message.includes('✅') || data.message.includes('Image') || data.message.includes('background') || data.message.includes('interactive') || data.message.includes('🖼️') || data.message.includes('🎨') || data.message.includes('🎮')) {
                                        activityLogs.push(data.message);
                                    }
                                    // Update progress bar for detail events with sub_step info
                                    if (data.sub_step !== undefined && data.sub_total) {
                                        var subProgress = (data.sub_step / data.sub_total) * 30 + 10;
                                        currentProgress = Math.max(currentProgress, Math.min(subProgress, 40));
                                    }
                                } else if (data.type === 'slide_preview') {
                                    // NEW: Handle real-time slide preview
                                    slidePreview = {
                                        slide_count: data.slide_count,
                                        slides_preview: data.slides_preview,
                                        theme: data.theme
                                    };
                                    activityLogs.push('📄 ' + data.message);
                                } else if (data.type === 'progress') {
                                    currentPhase = data.message;
                                    currentDetailLog = '';
                                    // Track current step explicitly
                                    if (data.phase) {
                                        currentStep = data.phase;
                                    }
                                    // Handle completion status
                                    if (data.completed && data.phase) {
                                        // Mark this step as completed - normalize phase name
                                        var completedPhase = data.phase.replace('_complete', '');
                                        // Handle 'slides' -> 'slide' normalization
                                        if (completedPhase === 'slides') completedPhase = 'slide';
                                        if (!completedSteps.includes(completedPhase)) {
                                            completedSteps.push(completedPhase);
                                            console.log('[Scaffo] Step completed:', completedPhase, 'All completed:', completedSteps);
                                        }
                                        // Clear current step when this phase is done
                                        if (currentStep === data.phase) {
                                            currentStep = null;
                                        }
                                        activityLogs.push('✅ ' + data.message.replace('Generating ', '').replace('...', ''));
                                    } else {
                                        activityLogs.push('▸ ' + data.message);
                                    }
                                    // Check for parallel generation signal
                                    if (data.message && data.message.includes('parallel')) {
                                        currentStep = 'parallel';
                                    }
                                    if (data.step && data.total) {
                                        currentProgress = data.completed ? 
                                            (data.step / data.total) * 90 + 10 :
                                            ((data.step - 1) / data.total) * 90 + 20;
                                        currentProgress = Math.min(currentProgress, 95);
                                    } else {
                                        currentProgress = Math.min(currentProgress + 15, 90);
                                    }
                                } else if (data.type === 'complete') {
                                    // Replace generating message with package message
                                    setMessages(function(prev) {
                                        return prev.map(function(msg) {
                                            if (msg.id === generatingMsgId) {
                                                return {
                                                    id: msg.id,
                                                    role: 'assistant',
                                                    type: 'package',
                                                    pkg: data.package,
                                                    content: 'Teaching materials generated'
                                                };
                                            }
                                            return msg;
                                        });
                                    });
                                    
                                    setTeachingPackage(data.package);
                                    // Reset modification flag and save blueprint snapshot with raw_content for comparison
                                    setBlueprintModifiedSinceGeneration(false);
                                    // Ensure blueprint has raw_content for future comparisons
                                    var blueprintSnapshot = JSON.parse(JSON.stringify(blueprint));
                                    if (!blueprintSnapshot.raw_content) {
                                        blueprintSnapshot.raw_content = blueprintToMarkdown(blueprint);
                                    }
                                    setLastGeneratedBlueprint(blueprintSnapshot);
                                    if (data.generation_id) {
                                        // Only navigate if this is a new generation (not regeneration)
                                        // For regeneration, currentGenerationId is already set
                                        if (!currentGenerationId || currentGenerationId !== data.generation_id) {
                                            setCurrentGenerationId(data.generation_id);
                                            navigateTo('/generation/' + data.generation_id);
                                        }
                                    }
                                    loadRecentGenerations();
                                    setIsGeneratingMaterials(false);
                                    return; // Exit the function
                                } else if (data.type === 'error') {
                                    console.error('Generation error:', data.message);
                                    // Remove generating message and show error
                                    setMessages(function(prev) {
                                        return prev.filter(function(msg) { return msg.id !== generatingMsgId; }).concat([{
                                            role: 'assistant',
                                            content: 'Sorry, there was an error generating the materials. Please try again.'
                                        }]);
                                    });
                                    setIsGeneratingMaterials(false);
                                    return;
                                }
                                
                                // Update the generating message with progress (throttled to prevent UI lag)
                                // Force immediate update for important events (completion, errors)
                                var isImportantEvent = data.type === 'complete' || data.type === 'error' || data.completed;
                                throttledUIUpdate(isImportantEvent);
                            } catch (e) {}
                        }
                    }
                } catch (error) {
                    console.error('Error generating package:', error);
                    // Remove generating message and show error
                    setMessages(function(prev) {
                        return prev.filter(function(msg) { return msg.id !== generatingMsgId; }).concat([{
                            role: 'assistant',
                            content: 'Sorry, there was an error generating the materials. Please try again.'
                        }]);
                    });
                    setIsGeneratingMaterials(false);
                }
            };

            // Render view
            const renderContent = () => {
                switch (view) {
                    case 'home':
                    case 'chat':
                        return (
                            <main className="flex-1 flex flex-col h-full overflow-hidden relative">
                                {/* Chat Panel - full width */}
                                <div className="flex-1 flex flex-col h-full relative z-10 bg-background-light dark:bg-background-dark">
                                    <div ref={chatRef} className="flex-1 overflow-y-auto no-scrollbar p-6 md:p-8 flex flex-col">
                                        {messages.length === 0 ? (
                                            <div className="flex-1 flex flex-col justify-center items-center">
                                                <div className="w-full max-w-xl flex flex-col gap-10">
                                                    <div className="flex flex-col items-center text-center gap-4 animate-fade-in-up">
                                                        <div className="relative">
                                                            <div className="w-16 h-16 rounded-2xl bg-white dark:bg-surface-dark shadow-soft flex items-center justify-center mb-2 z-10 relative">
                                                                <span className="material-symbols-outlined text-primary text-4xl">waving_hand</span>
                                                            </div>
                                                            <div className="absolute inset-0 bg-primary/20 blur-xl rounded-full scale-110 -z-10"></div>
                                                        </div>
                                                        <div className="space-y-1">
                                                            <h1 className="text-[#101718] dark:text-white text-2xl md:text-3xl font-black tracking-[-0.033em] leading-tight">
                                                                {(() => {
                                                                    const hour = new Date().getHours();
                                                                    const name = currentUser && currentUser.name ? currentUser.name : 'Teacher';
                                                                    if (hour < 12) return `Good morning, ${name}.`;
                                                                    if (hour < 18) return `Good afternoon, ${name}.`;
                                                                    return `Good evening, ${name}.`;
                                                                })()}
                                                            </h1>
                                                            <p className="text-[#5c818a] dark:text-gray-400 text-base font-medium">What are we planning today?</p>
                                                        </div>
                                                    </div>
                                                </div>
                                            </div>
                                        ) : (
                                            <div className="space-y-4 w-full max-w-4xl mx-auto">
                                                {messages.map((msg, i) => (
                                                    <ChatMessage 
                                                        key={msg.type === 'blueprint' ? `blueprint-${i}-${msg.blueprintVersion || 0}` : i} 
                                                        message={msg.content} 
                                                        isUser={msg.role === 'user'}
                                                        type={msg.type}
                                                        blueprint={msg.blueprint}
                                                        pkg={msg.pkg}
                                                        phase={msg.phase}
                                                        progress={msg.progress}
                                                        detailLog={msg.detailLog}
                                                        activityLogs={msg.activityLogs}
                                                        onBlueprintSave={handleBlueprintSave}
                                                        onBlueprintGenerate={handleCreateMaterials}
                                                        generationId={msg.generationId || currentGenerationId}
                                                        blueprintHistory={msg.blueprintHistory || (currentGeneration && currentGeneration.blueprint_history)}
                                                        version={msg.version || (currentGeneration && currentGeneration.version)}
                                                        updatedAt={msg.updatedAt || (currentGeneration && currentGeneration.updated_at)}
                                                        quickOptions={msg.quickOptions}
                                                        onQuickOptionClick={handleQuickOptionSend}
                                                        isLastMessage={i === messages.length - 1}
                                                        extractedInfo={msg.extractedInfo}
                                                        lessonInfo={msg.lessonInfo}
                                                        onConfirmGenerate={handleConfirmGenerate}
                                                        isGeneratingMaterials={isGeneratingMaterials}
                                                        isGeneratingBlueprint={isGeneratingBlueprint}
                                                        onCreateMaterials={handleCreateMaterials}
                                                        materialsGenerated={teachingPackage !== null}
                                                        blueprintModifiedSinceGeneration={blueprintModifiedSinceGeneration}
                                                        onBlueprintModified={() => setBlueprintModifiedSinceGeneration(true)}
                                                        isGenerationContext={msg.isGenerationContext}
                                                        attachments={msg.attachments}
                                                        isReadOnly={msg.isReadOnly}
                                                        isHistoryVersion={msg.isHistoryVersion}
                                                        historyVersion={msg.historyVersion}
                                                        historyTimestamp={msg.historyTimestamp}
                                                        thoughtText={msg.thoughtText}
                                                        streamingContent={aiProgress && aiProgress.partial_content ? aiProgress.partial_content : null}
                                                        isStreaming={aiProgress && aiProgress.is_writing && i === messages.length - 1}
                                                        conversationMessages={messages}
                                                        selectedPackages={msg.selectedPackages}
                                                        completedSteps={msg.completedSteps}
                                                        currentStep={msg.currentStep}
                                                        slidePreview={msg.slidePreview}
                                                    />
                                                ))}
                                                {isLoading && (
                                                    <div className="flex flex-col gap-2 items-start animate-fade-in">
                                                        <div className="flex gap-2 items-center mb-1">
                                                            <div className="size-6 rounded-full bg-primary/10 flex items-center justify-center">
                                                                <span className="material-symbols-outlined text-primary text-sm">dashboard_customize</span>
                                                            </div>
                                                            <span className="text-xs font-bold text-primary">Tess</span>
                                                        </div>
                                                        
                                                        {/* Show thinking during streaming (before response) */}
                                                        {aiProgress && aiProgress.is_ai_thinking && aiProgress.thought_text && (
                                                            <ThinkingCollapse 
                                                                thoughtText={aiProgress.thought_text} 
                                                                isChinese={aiProgress.message && /[\u4e00-\u9fff]/.test(aiProgress.message)}
                                                                isStreaming={true}
                                                            />
                                                        )}
                                                        
                                                        {/* Show streaming blueprint content - using StreamingBlueprintCard component for stable caching */}
                                                        {aiProgress && aiProgress.is_writing && aiProgress.partial_content && (
                                                            <StreamingBlueprintCard 
                                                                partialContent={aiProgress.partial_content}
                                                                isChinese={aiProgress.message && /[\u4e00-\u9fff]/.test(aiProgress.message)}
                                                            />
                                                        )}
                                                        
                                                        {/* Progress indicator */}
                                                        <div className="flex items-start gap-3">
                                                            <div className="flex flex-col gap-1 bg-gray-50 dark:bg-gray-800/50 px-4 py-3 rounded-2xl min-w-56">
                                                                {aiProgress ? (
                                                                    <div className="flex flex-col gap-2" style={{maxWidth: '320px', minWidth: '200px'}}>
                                                                        {/* Header with icon and status */}
                                                                        <div className="flex items-center gap-2">
                                                                            {aiProgress.is_ai_thinking ? (
                                                                                <span className="text-primary">✦</span>
                                                                            ) : aiProgress.is_writing ? (
                                                                                <span className="material-symbols-outlined text-primary text-sm animate-pulse">edit_note</span>
                                                                            ) : aiProgress.message && aiProgress.message.includes('✅') ? (
                                                                                <span className="text-base">✅</span>
                                                                            ) : aiProgress.message && aiProgress.message.includes('✨') ? (
                                                                                <span className="text-base">✨</span>
                                                                            ) : (
                                                                                <span className="material-symbols-outlined text-primary text-sm animate-spin">progress_activity</span>
                                                                            )}
                                                                            <span className="text-sm text-gray-600 dark:text-gray-300 font-medium">
                                                                                {aiProgress.message ? aiProgress.message.replace('🤖 ', '').replace('✅ ', '').replace('✨ ', '').replace('💭 ', '') : ''}
                                                                            </span>
                                                                        </div>
                                                                        {/* Progress indicator */}
                                                                        {aiProgress.is_ai_thinking ? (
                                                                            <div className="flex items-center gap-2">
                                                                                <div className="flex-1 h-1 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden">
                                                                                    <div className="h-full bg-gradient-to-r from-primary via-primary/60 to-primary rounded-full animate-[pulse_1.5s_ease-in-out_infinite]" style={{width: '100%'}}></div>
                                                                                </div>
                                                                                <span className="text-xs text-gray-400 tabular-nums">{aiProgress.thought_text ? aiProgress.thought_text.length : '0'} chars</span>
                                                                            </div>
                                                                        ) : aiProgress.is_writing && aiProgress.partial_content ? (
                                                                            <div className="space-y-3">
                                                                                <div className="flex items-center gap-2">
                                                                                    <div className="flex-1 h-1 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden">
                                                                                        <div className="h-full bg-gradient-to-r from-green-400 via-green-500 to-green-400 rounded-full animate-[pulse_1s_ease-in-out_infinite]" style={{width: '100%'}}></div>
                                                                                    </div>
                                                                                    <span className="text-xs text-gray-400 tabular-nums">{aiProgress.partial_content.length} chars</span>
                                                                                </div>
                                                                                {/* Live Blueprint Preview */}
                                                                                <div className="mt-3 p-4 bg-white dark:bg-gray-800 rounded-xl border border-green-200 dark:border-green-800/50 shadow-sm max-h-[400px] overflow-y-auto">
                                                                                    {(() => {
                                                                                        const parsed = tryParseStreamingBlueprint(aiProgress.partial_content);
                                                                                        if (parsed.success && parsed.markdown) {
                                                                                            const htmlContent = typeof marked !== 'undefined' ? marked.parse(parsed.markdown) : parsed.markdown;
                                                                                            return React.createElement('div', {
                                                                                                className: 'prose prose-sm dark:prose-invert max-w-none',
                                                                                                dangerouslySetInnerHTML: { __html: htmlContent }
                                                                                            });
                                                                                        } else {
                                                                                            return React.createElement('pre', {
                                                                                                className: 'text-xs text-gray-600 dark:text-gray-400 font-mono whitespace-pre-wrap break-words'
                                                                                            }, aiProgress.partial_content.slice(-2000));
                                                                                        }
                                                                                    })()}
                                                                                </div>
                                                                            </div>
                                                                        ) : aiProgress.step >= 4 && !aiProgress.is_ai_thinking ? (
                                                                            <div className="flex items-center gap-2">
                                                                                <div className="flex-1 h-1 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden">
                                                                                    <div className="h-full bg-gradient-to-r from-amber-400 via-amber-500 to-amber-400 rounded-full animate-[pulse_1.2s_ease-in-out_infinite]" style={{width: '100%'}}></div>
                                                                                </div>
                                                                                <span className="text-xs text-amber-500">Finalizing...</span>
                                                                            </div>
                                                                        ) : (
                                                                            <div className="flex items-center gap-2">
                                                                                <div className="flex-1 h-1.5 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden">
                                                                                    <div 
                                                                                        className="h-full bg-primary rounded-full transition-all duration-300"
                                                                                        style={{width: aiProgress.total_steps ? ((aiProgress.step / aiProgress.total_steps) * 100) + '%' : '0%'}}
                                                                                    ></div>
                                                                                </div>
                                                                                <span className="text-xs text-gray-400">{aiProgress.step}/{aiProgress.total_steps}</span>
                                                                            </div>
                                                                        )}
                                                                    </div>
                                                                ) : (
                                                                    <div className="flex items-center gap-2">
                                                                        <div className="flex gap-1">
                                                                            <div className="w-2 h-2 bg-primary rounded-full animate-bounce" style={{animationDelay: '0ms'}}></div>
                                                                            <div className="w-2 h-2 bg-primary rounded-full animate-bounce" style={{animationDelay: '150ms'}}></div>
                                                                            <div className="w-2 h-2 bg-primary rounded-full animate-bounce" style={{animationDelay: '300ms'}}></div>
                                                                        </div>
                                                                    </div>
                                                                )}
                                                            </div>
                                                        </div>
                                                    </div>
                                                )}
                                            </div>
                                        )}
                                    </div>
                                    
                                    {/* Input Area */}
                                    <div className="p-4 md:p-6 bg-background-light dark:bg-background-dark">
                                        <div className="w-full max-w-3xl mx-auto">
                                            <div className="relative bg-white dark:bg-surface-dark rounded-2xl shadow-lg border border-gray-200 dark:border-gray-700 flex flex-col transition-all hover:shadow-xl">
                                                {/* Pending Attachments Preview */}
                                                {pendingAttachments.length > 0 && (
                                                    <div className="px-3 pt-3 pb-1 flex flex-wrap gap-2 border-b border-gray-100 dark:border-gray-800">
                                                        {pendingAttachments.map(attachment => (
                                                            <div 
                                                                key={attachment.id}
                                                                className="group flex items-center gap-2 bg-gray-100 dark:bg-gray-800 rounded-lg px-3 py-1.5 text-sm animate-fade-in hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors"
                                                            >
                                                                <span>{getFileIcon(attachment.analysis_type)}</span>
                                                                {attachment.file_url ? (
                                                                    <a 
                                                                        href={attachment.file_url}
                                                                        target="_blank"
                                                                        rel="noopener noreferrer"
                                                                        className="text-primary hover:text-primary-hover max-w-[150px] truncate font-medium"
                                                                        title={`View ${attachment.filename}`}
                                                                        onClick={(e) => e.stopPropagation()}
                                                                    >
                                                                        {attachment.filename}
                                                                    </a>
                                                                ) : (
                                                                    <span className="text-gray-700 dark:text-gray-300 max-w-[150px] truncate">
                                                                        {attachment.filename}
                                                                    </span>
                                                                )}
                                                                <span className="text-xs text-gray-400">
                                                                    {attachment.text_length > 0 ? `${Math.round(attachment.text_length / 1000)}k chars` : ''}
                                                                </span>
                                                                {attachment.file_url && (
                                                                    <a
                                                                        href={attachment.file_url}
                                                                        target="_blank"
                                                                        rel="noopener noreferrer"
                                                                        className="text-gray-400 hover:text-primary transition-colors"
                                                                        title="Open in new tab"
                                                                        onClick={(e) => e.stopPropagation()}
                                                                    >
                                                                        <span className="material-symbols-outlined text-[16px]">open_in_new</span>
                                                                    </a>
                                                                )}
                                                                <button
                                                                    onClick={() => removePendingAttachment(attachment.id)}
                                                                    className="ml-1 text-gray-400 hover:text-red-500 transition-colors"
                                                                    title="Remove attachment"
                                                                >
                                                                    <span className="material-symbols-outlined text-[16px]">close</span>
                                                                </button>
                                                            </div>
                                                        ))}
                                                    </div>
                                                )}
                                                
                                                <textarea
                                                    className="w-full bg-transparent border-none focus:ring-0 text-[#34322D] dark:text-white placeholder:text-gray-400 dark:placeholder:text-gray-500 resize-none h-16 p-3 text-[15px] leading-relaxed rounded-t-lg font-chat"
                                                    placeholder={pendingAttachments.length > 0 ? "Add a message about these files, or just send them..." : "What would you like to teach today?"}
                                                    value={inputValue}
                                                    onChange={(e) => setInputValue(e.target.value)}
                                                    onKeyDown={(e) => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); handleSend(); } }}
                                                />
                                                <div className="flex items-center justify-between px-3 pb-2 pt-1">
                                                    <div className="flex items-center gap-2">
                                                        <input 
                                                            ref={fileInputRef} 
                                                            type="file" 
                                                            onChange={handleFileUpload}
                                                            accept=".txt,.md,.pdf,.doc,.docx,.jpg,.jpeg,.png,.gif,.webp,image/*"
                                                            style={{display: 'none'}}
                                                        />
                                                        <button 
                                                            onClick={() => fileInputRef.current && fileInputRef.current.click()}
                                                            disabled={isUploading}
                                                            className="flex items-center justify-center w-9 h-9 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 transition-colors disabled:opacity-50"
                                                            title="Upload files: PDF, Word, images, or text documents"
                                                        >
                                                            {isUploading ? (
                                                                <span className="material-symbols-outlined text-[20px] animate-spin">progress_activity</span>
                                                            ) : (
                                                                <span className="material-symbols-outlined text-[20px]">attach_file</span>
                                                            )}
                                                        </button>
                                                        {pendingAttachments.length > 0 && (
                                                            <span className="text-xs text-primary font-medium">
                                                                {pendingAttachments.length} file{pendingAttachments.length > 1 ? 's' : ''} attached
                                                            </span>
                                                        )}
                                                    </div>
                                                    <button 
                                                        data-send-button="true"
                                                        onClick={handleSend} 
                                                        disabled={isLoading || (!inputValue.trim() && pendingAttachments.length === 0)} 
                                                        className="h-10 w-10 flex items-center justify-center rounded-full bg-primary text-white hover:bg-primary-hover transition-all shadow-md active:scale-95 disabled:opacity-40 disabled:cursor-not-allowed disabled:hover:bg-primary"
                                                    >
                                                        <span className="material-symbols-outlined text-[22px]">arrow_upward</span>
                                                    </button>
                                                </div>
                                            </div>
                                            
                                            {/* Example Prompts - Only show on home */}
                                            {messages.length === 0 && view === 'home' && (
                                                <div className="mt-6 flex flex-wrap justify-center gap-2">
                                                    <span className="text-[11px] text-gray-400 dark:text-gray-500 py-1.5">Examples:</span>
                                                    <button 
                                                        onClick={function() { setInputValue('Teach 7th grade students about photosynthesis and cellular respiration'); handleSend(); }}
                                                        className="text-[12px] px-3 py-1.5 rounded-full bg-gray-100 dark:bg-gray-800 text-gray-600 dark:text-gray-300 hover:bg-primary/10 hover:text-primary transition-colors"
                                                    >
                                                        "Photosynthesis for 7th grade"
                                                    </button>
                                                    <button 
                                                        onClick={function() { setInputValue('Create materials for teaching the American Revolution to 5th graders'); handleSend(); }}
                                                        className="text-[12px] px-3 py-1.5 rounded-full bg-gray-100 dark:bg-gray-800 text-gray-600 dark:text-gray-300 hover:bg-primary/10 hover:text-primary transition-colors"
                                                    >
                                                        "American Revolution for 5th grade"
                                                    </button>
                                                    <button 
                                                        onClick={function() { setInputValue('Help me teach fractions and decimals to 4th grade math students'); handleSend(); }}
                                                        className="text-[12px] px-3 py-1.5 rounded-full bg-gray-100 dark:bg-gray-800 text-gray-600 dark:text-gray-300 hover:bg-primary/10 hover:text-primary transition-colors"
                                                    >
                                                        "Fractions for 4th grade"
                                                    </button>
                                                </div>
                                            )}
                                        </div>
                                    </div>
                                </div>
                            </main>
                        );
                    
                    case 'generating':
                        return (
                            <main className="flex-1 flex items-center justify-center bg-background-light dark:bg-background-dark">
                                <GeneratingView phase={generatingPhase} progress={generatingProgress} stepTracking={generatingSteps} />
                            </main>
                        );
                    
                    case 'generation':
                        return (
                            <GenerationView
                                blueprint={blueprint}
                                teachingPackage={teachingPackage}
                                messages={messages}
                                onBack={handleNewChat}
                                onCreateMaterials={handleCreateMaterials}
                                isGeneratingMaterials={isGeneratingMaterials}
                                onAdjust={(sectionId) => {
                                    setAdjustSection(sectionId);
                                    setAdjustModalOpen(true);
                                }}
                            />
                        );
                    
                    default:
                        return null;
                }
            };

            // Handle selecting a generation from sidebar
            const handleSelectGeneration = async (gen) => {
                // Navigate to the generation - route handler will load the data
                // User is identified via auth token, not URL (privacy)
                navigateTo(`/generation/${gen.id}`);
            };

            // Handle deleting a generation
            const handleDeleteGeneration = async (genId) => {
                try {
                    // Optimistic update: immediately remove from UI
                    setRecentGenerations(prev => prev.filter(g => g.id !== genId));
                    
                    // Call API to delete
                    await api.deleteGeneration(genId);
                    
                    // Refresh list to ensure sync with server
                    await loadRecentGenerations();
                    
                    // If viewing the deleted generation, go home
                    if (currentGenerationId === genId) {
                        handleNewChat();
                    }
                } catch (error) {
                    console.error('Failed to delete generation:', error);
                    // Reload list to restore state on error
                    await loadRecentGenerations();
                    alert('Failed to delete generation. Please try again.');
                }
            };

            // Handle selecting a template
            const handleSelectTemplate = (template) => {
                // Pre-fill the input with template-based prompt
                setInputValue(`Create a lesson using the ${template.title} framework`);
                navigateTo('/');
                setView('home');
            };

            // Render library view
            if (view === 'library') {
                return (
                    <div className="flex h-screen w-full">
                        <DarkModeToggle />
                        <TemplateLibraryView
                            onBack={() => navigateTo('/')}
                            onSelectTemplate={handleSelectTemplate}
                        />
                    </div>
                );
            }

            return (
                <div className="flex h-screen w-full">
                    <DarkModeToggle />
                    {view !== 'generating' && view !== 'package' && (
                        <Sidebar 
                            onNewChat={handleNewChat}
                            onOpenLibrary={() => navigateTo('/library')}
                            recentGenerations={recentGenerations}
                            onSelectGeneration={handleSelectGeneration}
                            onDeleteGeneration={handleDeleteGeneration}
                            currentGenerationId={currentGenerationId}
                            currentUser={currentUser}
                            onLogout={handleLogout}
                        />
                    )}
                    {renderContent()}
                    <AdjustModal
                        isOpen={adjustModalOpen}
                        onClose={() => setAdjustModalOpen(false)}
                        onSubmit={handleAdjustSubmit}
                        sectionId={adjustSection}
                    />
                </div>
            );
        };

        // Render
var root = createRoot(document.getElementById('root'));
        root.render(<App />);
