import { useState, useEffect, useRef } from 'react';
import { marked } from 'marked';
import jsPDF from 'jspdf';
import { message } from '@tauri-apps/plugin-dialog';
import { Note } from '../types';
import { NextcloudAPI } from '../api/nextcloud';
import { FloatingToolbar } from './FloatingToolbar';
import { InsertToolbar } from './InsertToolbar';

interface NoteEditorProps {
  note: Note | null;
  onUpdateNote: (note: Note) => void;
  onToggleFavorite?: (note: Note, favorite: boolean) => void;
  onUnsavedChanges?: (hasChanges: boolean) => void;
  categories: string[];
  isFocusMode?: boolean;
  onToggleFocusMode?: () => void;
  editorFont?: string;
  editorFontSize?: number;
  previewFont?: string;
  previewFontSize?: number;
  api?: NextcloudAPI | null;
}

const imageCache = new Map<string, string>();


export function NoteEditor({ note, onUpdateNote, onToggleFavorite, onUnsavedChanges, categories, isFocusMode, onToggleFocusMode, editorFont = 'Source Code Pro', editorFontSize = 14, previewFont = 'Merriweather', previewFontSize = 16, api }: NoteEditorProps) {
  const [localContent, setLocalContent] = useState('');
  const [localCategory, setLocalCategory] = useState('');
  const [localFavorite, setLocalFavorite] = useState(false);
  const [isSaving, setIsSaving] = useState(false);
  const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);
  const [isExportingPDF, setIsExportingPDF] = useState(false);
  const [isPreviewMode, setIsPreviewMode] = useState(false);
  const [processedContent, setProcessedContent] = useState('');
  const [isLoadingImages, setIsLoadingImages] = useState(false);
  const [isUploading, setIsUploading] = useState(false);
  const previousNoteIdRef = useRef<number | string | null>(null);
  const previousNoteContentRef = useRef<string>('');
  const textareaRef = useRef<HTMLTextAreaElement>(null);
  const fileInputRef = useRef<HTMLInputElement>(null);

  useEffect(() => {
    onUnsavedChanges?.(hasUnsavedChanges);
  }, [hasUnsavedChanges, onUnsavedChanges]);

  // Handle Escape key to exit focus mode
  useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      if (e.key === 'Escape' && isFocusMode && onToggleFocusMode) {
        onToggleFocusMode();
      }
    };
    
    document.addEventListener('keydown', handleKeyDown);
    return () => document.removeEventListener('keydown', handleKeyDown);
  }, [isFocusMode, onToggleFocusMode]);

  // Auto-resize textarea when content changes, switching from preview to edit, or font size changes
  useEffect(() => {
    if (textareaRef.current && !isPreviewMode) {
      // Use setTimeout to ensure DOM has updated
      setTimeout(() => {
        if (textareaRef.current) {
          // Save cursor position and scroll position
          const cursorPosition = textareaRef.current.selectionStart;
          const scrollTop = textareaRef.current.scrollTop;
          
          textareaRef.current.style.height = 'auto';
          textareaRef.current.style.height = textareaRef.current.scrollHeight + 'px';
          
          // Restore cursor position and scroll position
          textareaRef.current.setSelectionRange(cursorPosition, cursorPosition);
          textareaRef.current.scrollTop = scrollTop;
        }
      }, 0);
    }
  }, [localContent, isPreviewMode, editorFontSize]);

  // Process images when entering preview mode or content changes
  useEffect(() => {
    if (!isPreviewMode || !note || !api) {
      setProcessedContent(localContent);
      return;
    }

    // Guard: Only process if localContent has been updated for the current note
    // This prevents processing stale content from the previous note
    if (previousNoteIdRef.current !== note.id) {
      console.log(`[Note ${note.id}] Skipping image processing - waiting for content to sync (previousNoteIdRef: ${previousNoteIdRef.current})`);
      return;
    }

    const processImages = async () => {
      console.log(`[Note ${note.id}] Processing images in preview mode. Content length: ${localContent.length}`);
      setIsLoadingImages(true);
      setProcessedContent(''); // Clear old content immediately
      
      // Find all image references in markdown: ![alt](path)
      const imageRegex = /!\[([^\]]*)\]\(([^)]+)\)/g;
      let content = localContent;
      const matches = [...localContent.matchAll(imageRegex)];
      console.log(`[Note ${note.id}] Found ${matches.length} images to process`);
      
      for (const match of matches) {
        const [fullMatch, alt, imagePath] = match;
        
        // Skip external URLs (http/https)
        if (imagePath.startsWith('http://') || imagePath.startsWith('https://')) {
          continue;
        }
        
        // Check cache first
        const cacheKey = `${note.id}:${imagePath}`;
        if (imageCache.has(cacheKey)) {
          const dataUrl = imageCache.get(cacheKey)!;
          content = content.replace(fullMatch, `![${alt}](${dataUrl})`);
          continue;
        }
        
        try {
          const dataUrl = await api.fetchAttachment(note.id, imagePath, note.category);
          imageCache.set(cacheKey, dataUrl);
          content = content.replace(fullMatch, `![${alt}](${dataUrl})`);
        } catch (error) {
          console.error(`Failed to fetch attachment: ${imagePath}`, error);
          // Keep original path, image will show as broken
        }
      }
      
      setProcessedContent(content);
      setIsLoadingImages(false);
    };

    processImages();
  }, [isPreviewMode, localContent, note?.id, api]);

  useEffect(() => {
    const loadNewNote = () => {
      if (note) {
        setLocalContent(note.content);
        setLocalCategory(note.category || '');
        setLocalFavorite(note.favorite);
        setHasUnsavedChanges(false);
        
        previousNoteIdRef.current = note.id;
        previousNoteContentRef.current = note.content;
      }
    };

    // Switching to a different note
    if (previousNoteIdRef.current !== null && previousNoteIdRef.current !== note?.id) {
      console.log(`Switching from note ${previousNoteIdRef.current} to note ${note?.id}`);
      setProcessedContent('');
      if (hasUnsavedChanges) {
        handleSave();
      }
      loadNewNote();
    } 
    // Same note but content changed from server (and no unsaved local changes)
    else if (note && previousNoteIdRef.current === note.id && !hasUnsavedChanges && previousNoteContentRef.current !== note.content) {
      console.log(`Note ${note.id} content changed from server (prev: ${previousNoteContentRef.current.length} chars, new: ${note.content.length} chars)`);
      loadNewNote();
    }
    // Initial load
    else if (!note || previousNoteIdRef.current === null) {
      loadNewNote();
    }
    // Favorite status changed (e.g., from sync)
    else if (note && note.favorite !== localFavorite) {
      setLocalFavorite(note.favorite);
    }
  }, [note?.id, note?.content, note?.modified, note?.favorite]);

  const handleSave = () => {
    if (!note || !hasUnsavedChanges) return;
    
    console.log('Saving note content length:', localContent.length);
    console.log('Last 50 chars:', localContent.slice(-50));
    setIsSaving(true);
    setHasUnsavedChanges(false);
    
    const firstLine = localContent.split('\n')[0].replace(/^#+\s*/, '').trim();
    const title = firstLine || 'Untitled';
    
    onUpdateNote({
      ...note,
      title,
      content: localContent,
      category: localCategory,
      favorite: localFavorite,
    });
    setTimeout(() => setIsSaving(false), 500);
  };

  const handleContentChange = (value: string) => {
    setLocalContent(value);
    setHasUnsavedChanges(true);
  };

  const handleDiscard = () => {
    if (!note) return;
    
    setLocalContent(note.content);
    setLocalCategory(note.category || '');
    setLocalFavorite(note.favorite);
    setHasUnsavedChanges(false);
  };

  const loadFontAsBase64 = async (fontPath: string): Promise<string> => {
    const response = await fetch(fontPath);
    const blob = await response.blob();
    return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.onloadend = () => {
        const base64 = reader.result as string;
        // Remove data URL prefix to get just the base64 string
        resolve(base64.split(',')[1]);
      };
      reader.onerror = reject;
      reader.readAsDataURL(blob);
    });
  };

  const handleExportPDF = async () => {
    if (!note) return;

    setIsExportingPDF(true);

    try {
      // Create PDF
      const pdf = new jsPDF({
        orientation: 'portrait',
        unit: 'mm',
        format: 'a4',
      });

      // Load and add custom fonts based on preview font selection
      const fontMap: { [key: string]: { regular: string; italic: string; name: string } } = {
        'Merriweather': {
          regular: '/fonts/Merriweather-VariableFont_opsz,wdth,wght.ttf',
          italic: '/fonts/Merriweather-Italic-VariableFont_opsz,wdth,wght.ttf',
          name: 'Merriweather'
        },
        'Crimson Pro': {
          regular: '/fonts/CrimsonPro-VariableFont_wght.ttf',
          italic: '/fonts/CrimsonPro-Italic-VariableFont_wght.ttf',
          name: 'CrimsonPro'
        },
        'Roboto Serif': {
          regular: '/fonts/RobotoSerif-VariableFont_GRAD,opsz,wdth,wght.ttf',
          italic: '/fonts/RobotoSerif-Italic-VariableFont_GRAD,opsz,wdth,wght.ttf',
          name: 'RobotoSerif'
        },
        'Average': {
          regular: '/fonts/Average-Regular.ttf',
          italic: '/fonts/Average-Regular.ttf', // No italic variant
          name: 'Average'
        }
      };

      const selectedFont = fontMap[previewFont];
      if (selectedFont) {
        try {
          const regularBase64 = await loadFontAsBase64(selectedFont.regular);
          pdf.addFileToVFS(`${selectedFont.name}-normal.ttf`, regularBase64);
          pdf.addFont(`${selectedFont.name}-normal.ttf`, selectedFont.name, 'normal');
          
          const italicBase64 = await loadFontAsBase64(selectedFont.italic);
          pdf.addFileToVFS(`${selectedFont.name}-italic.ttf`, italicBase64);
          pdf.addFont(`${selectedFont.name}-italic.ttf`, selectedFont.name, 'italic');
          
          // Set the custom font as default
          pdf.setFont(selectedFont.name, 'normal');
        } catch (fontError) {
          console.error('Failed to load custom font, using default:', fontError);
        }
      }

      // Add Source Code Pro for code blocks
      try {
        const codeFont = await loadFontAsBase64('/fonts/SourceCodePro-VariableFont_wght.ttf');
        pdf.addFileToVFS('SourceCodePro-normal.ttf', codeFont);
        pdf.addFont('SourceCodePro-normal.ttf', 'SourceCodePro', 'normal');
      } catch (codeFontError) {
        console.error('Failed to load code font:', codeFontError);
      }

      // Process images to embed them as data URLs
      let contentForPDF = localContent;
      if (api) {
        const imageRegex = /!\[([^\]]*)\]\(([^)]+)\)/g;
        const matches = [...localContent.matchAll(imageRegex)];
        
        for (const match of matches) {
          const [fullMatch, alt, imagePath] = match;
          
          // Skip external URLs
          if (imagePath.startsWith('http://') || imagePath.startsWith('https://')) {
            continue;
          }
          
          // Check cache first
          const cacheKey = `${note.id}:${imagePath}`;
          if (imageCache.has(cacheKey)) {
            const dataUrl = imageCache.get(cacheKey)!;
            contentForPDF = contentForPDF.replace(fullMatch, `![${alt}](${dataUrl})`);
            continue;
          }
          
          try {
            const dataUrl = await api.fetchAttachment(note.id, imagePath, note.category);
            imageCache.set(cacheKey, dataUrl);
            contentForPDF = contentForPDF.replace(fullMatch, `![${alt}](${dataUrl})`);
          } catch (error) {
            console.error(`Failed to fetch attachment for PDF: ${imagePath}`, error);
          }
        }
      }

      const container = document.createElement('div');
      container.style.fontFamily = `"${previewFont}", Georgia, serif`;
      container.style.fontSize = `${previewFontSize}px`;
      container.style.lineHeight = '1.6';
      container.style.color = '#000000';
      
      const titleElement = document.createElement('h1');
      const firstLine = localContent.split('\n')[0].replace(/^#+\s*/, '').trim();
      titleElement.textContent = firstLine || 'Untitled';
      titleElement.style.marginTop = '0';
      titleElement.style.marginBottom = '20px';
      titleElement.style.fontSize = '24px';
      titleElement.style.fontWeight = 'bold';
      titleElement.style.color = '#000000';
      titleElement.style.textAlign = 'center';
      titleElement.style.fontFamily = `"${previewFont}", Georgia, serif`;
      container.appendChild(titleElement);
      
      const contentElement = document.createElement('div');
      const html = marked.parse(contentForPDF || '', { async: false }) as string;
      contentElement.innerHTML = html;
      contentElement.style.fontSize = `${previewFontSize}px`;
      contentElement.style.lineHeight = '1.6';
      contentElement.style.color = '#000000';
      container.appendChild(contentElement);
      
      const style = document.createElement('style');
      style.textContent = `
        body, p, h1, h2, h3, div { font-family: "${previewFont}", Georgia, serif !important; }
        code, pre, pre * { font-family: "Source Code Pro", "Courier New", monospace !important; }
        pre { background: #f5f5f5; padding: 10px; border-radius: 4px; overflow-x: auto; }
        code { padding: 0; }
        h1 { font-size: 2em; font-weight: bold; margin-top: 0.67em; margin-bottom: 0.67em; }
        h2 { font-size: 1.5em; font-weight: bold; margin-top: 0.83em; margin-bottom: 0.83em; }
        h3 { font-size: 1.17em; font-weight: bold; margin-top: 1em; margin-bottom: 1em; }
        p { margin: 0.5em 0; }
        ul, ol { margin: 0.5em 0; padding-left: 2em; list-style-position: outside; font-family: "${previewFont}", Georgia, serif !important; }
        ul { list-style-type: disc; }
        ol { list-style-type: decimal; }
        li { margin: 0.25em 0; display: list-item; font-family: "${previewFont}", Georgia, serif !important; }
        em { font-style: italic; vertical-align: baseline; }
        strong { font-weight: bold; vertical-align: baseline; line-height: inherit; }
        img { max-width: 100%; height: auto; display: block; margin: 1em 0; }
      `;
      container.appendChild(style);

      // Use jsPDF's html() method with custom font set
      await pdf.html(container, {
        callback: async (doc) => {
          const firstLine = localContent.split('\n')[0].replace(/^#+\s*/, '').trim();
          const fileName = `${firstLine || 'note'}.pdf`;
          doc.save(fileName);
          
          setTimeout(async () => {
            try {
              await message(`PDF exported successfully!\n\nFile: ${fileName}\nLocation: Downloads folder`, {
                title: 'Export Complete',
                kind: 'info',
              });
            } catch (err) {
              console.log('Dialog shown successfully or not available');
            }
            setIsExportingPDF(false);
          }, 500);
        },
        margin: [20, 20, 20, 20],
        autoPaging: 'text',
        width: 170,
        windowWidth: 650,
      });
    } catch (error) {
      console.error('PDF export failed:', error);
      try {
        await message('Failed to export PDF. Please try again.', {
          title: 'Export Failed',
          kind: 'error',
        });
      } catch (err) {
        console.error('Could not show error dialog');
      }
      setIsExportingPDF(false);
    }
  };

  const handleFavoriteToggle = () => {
    const newFavorite = !localFavorite;
    setLocalFavorite(newFavorite);
    
    if (note && onToggleFavorite) {
      // Use dedicated favorite toggle callback if provided
      onToggleFavorite(note, newFavorite);
    } else if (note) {
      // Fallback to full update if no callback provided
      const firstLine = localContent.split('\n')[0].replace(/^#+\s*/, '').trim();
      const title = firstLine || 'Untitled';
      
      onUpdateNote({
        ...note,
        title,
        content: localContent,
        category: localCategory,
        favorite: newFavorite,
      });
    }
  };

  const handleCategoryChange = (category: string) => {
    setLocalCategory(category);
    setHasUnsavedChanges(true);
  };

  const handleAttachmentUpload = async (event: React.ChangeEvent<HTMLInputElement>) => {
    const file = event.target.files?.[0];
    if (!file || !note || !api) return;

    setIsUploading(true);
    try {
      const relativePath = await api.uploadAttachment(note.id, file, note.category);
      
      // Determine if it's an image or other file
      const isImage = file.type.startsWith('image/');
      const markdownLink = isImage 
        ? `![${file.name}](${relativePath})`
        : `[${file.name}](${relativePath})`;
      
      // Insert at cursor position or end of content
      const textarea = textareaRef.current;
      if (textarea) {
        const cursorPos = textarea.selectionStart;
        const newContent = localContent.slice(0, cursorPos) + markdownLink + localContent.slice(cursorPos);
        setLocalContent(newContent);
        setHasUnsavedChanges(true);
        
        // Move cursor after inserted text
        setTimeout(() => {
          textarea.focus();
          const newPos = cursorPos + markdownLink.length;
          textarea.setSelectionRange(newPos, newPos);
        }, 0);
      } else {
        // Append to end
        setLocalContent(localContent + '\n' + markdownLink);
        setHasUnsavedChanges(true);
      }
      
      await message(`Attachment uploaded successfully!`, {
        title: 'Upload Complete',
        kind: 'info',
      });
    } catch (error) {
      console.error('Upload failed:', error);
      await message(`Failed to upload attachment: ${error}`, {
        title: 'Upload Failed',
        kind: 'error',
      });
    } finally {
      setIsUploading(false);
      // Reset file input
      if (fileInputRef.current) {
        fileInputRef.current.value = '';
      }
    }
  };

  const handleInsertLink = (text: string, url: string) => {
    const textarea = textareaRef.current;
    if (!textarea) return;
    
    const cursorPos = textarea.selectionStart;
    const markdownLink = `[${text}](${url})`;
    const newContent = localContent.slice(0, cursorPos) + markdownLink + localContent.slice(cursorPos);
    setLocalContent(newContent);
    setHasUnsavedChanges(true);
    
    setTimeout(() => {
      textarea.focus();
      const newPos = cursorPos + markdownLink.length;
      textarea.setSelectionRange(newPos, newPos);
    }, 0);
  };

  const handleInsertFile = () => {
    fileInputRef.current?.click();
  };

  const handleFormat = (format: 'bold' | 'italic' | 'strikethrough' | 'code' | 'codeblock' | 'quote' | 'ul' | 'ol' | 'link' | 'h1' | 'h2' | 'h3') => {
    if (!textareaRef.current) return;
    
    const textarea = textareaRef.current;
    const start = textarea.selectionStart;
    const end = textarea.selectionEnd;
    const selectedText = localContent.substring(start, end);
    
    if (!selectedText) return;
    
    let formattedText = '';
    let cursorOffset = 0;
    let isRemoving = false;
    
    // Helper to check and remove inline formatting
    const toggleInline = (text: string, wrapper: string): { result: string; removed: boolean } => {
      const escaped = wrapper.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
      const regex = new RegExp(`^${escaped}(.+)${escaped}$`, 's');
      const match = text.match(regex);
      if (match) {
        return { result: match[1], removed: true };
      }
      return { result: `${wrapper}${text}${wrapper}`, removed: false };
    };
    
    // Helper to check and remove line-prefix formatting
    const toggleLinePrefix = (text: string, prefixRegex: RegExp, addPrefix: (line: string, i: number) => string): { result: string; removed: boolean } => {
      const lines = text.split('\n');
      const allHavePrefix = lines.every(line => prefixRegex.test(line));
      if (allHavePrefix) {
        return { 
          result: lines.map(line => line.replace(prefixRegex, '')).join('\n'), 
          removed: true 
        };
      }
      return { 
        result: lines.map((line, i) => addPrefix(line, i)).join('\n'), 
        removed: false 
      };
    };
    
    switch (format) {
      case 'bold': {
        const { result, removed } = toggleInline(selectedText, '**');
        formattedText = result;
        isRemoving = removed;
        break;
      }
      case 'italic': {
        const { result, removed } = toggleInline(selectedText, '*');
        formattedText = result;
        isRemoving = removed;
        break;
      }
      case 'strikethrough': {
        const { result, removed } = toggleInline(selectedText, '~~');
        formattedText = result;
        isRemoving = removed;
        break;
      }
      case 'code': {
        const { result, removed } = toggleInline(selectedText, '`');
        formattedText = result;
        isRemoving = removed;
        break;
      }
      case 'codeblock': {
        const codeBlockMatch = selectedText.match(/^```\n?([\s\S]*?)\n?```$/);
        if (codeBlockMatch) {
          formattedText = codeBlockMatch[1];
          isRemoving = true;
        } else {
          formattedText = `\`\`\`\n${selectedText}\n\`\`\``;
        }
        break;
      }
      case 'quote': {
        const { result, removed } = toggleLinePrefix(selectedText, /^>\s?/, (line) => `> ${line}`);
        formattedText = result;
        isRemoving = removed;
        break;
      }
      case 'ul': {
        const { result, removed } = toggleLinePrefix(selectedText, /^[-*+]\s/, (line) => `- ${line}`);
        formattedText = result;
        isRemoving = removed;
        break;
      }
      case 'ol': {
        const { result, removed } = toggleLinePrefix(selectedText, /^\d+\.\s/, (line, i) => `${i + 1}. ${line}`);
        formattedText = result;
        isRemoving = removed;
        break;
      }
      case 'link': {
        const linkMatch = selectedText.match(/^\[(.+)\]\((.+)\)$/);
        if (linkMatch) {
          formattedText = linkMatch[1]; // Just return the text part
          isRemoving = true;
        } else {
          formattedText = `[${selectedText}](url)`;
          cursorOffset = formattedText.length - 4;
        }
        break;
      }
      case 'h1': {
        const { result, removed } = toggleLinePrefix(selectedText, /^#\s/, (line) => `# ${line}`);
        formattedText = result;
        isRemoving = removed;
        break;
      }
      case 'h2': {
        const { result, removed } = toggleLinePrefix(selectedText, /^##\s/, (line) => `## ${line}`);
        formattedText = result;
        isRemoving = removed;
        break;
      }
      case 'h3': {
        const { result, removed } = toggleLinePrefix(selectedText, /^###\s/, (line) => `### ${line}`);
        formattedText = result;
        isRemoving = removed;
        break;
      }
    }
    
    const newContent = localContent.substring(0, start) + formattedText + localContent.substring(end);
    setLocalContent(newContent);
    setHasUnsavedChanges(true);
    
    setTimeout(() => {
      textarea.focus();
      if (format === 'link' && !isRemoving) {
        // Select "url" for easy replacement
        textarea.setSelectionRange(start + cursorOffset, start + cursorOffset + 3);
      } else {
        textarea.setSelectionRange(start, start + formattedText.length);
      }
    }, 0);
  };

  if (!note) {
    return (
      <div className="flex-1 flex items-center justify-center bg-white dark:bg-gray-900 text-gray-400">
        <div className="text-center">
          <svg className="w-20 h-20 mx-auto mb-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
          </svg>
          <p className="text-lg font-medium">No Note Selected</p>
          <p className="text-sm mt-2">Select a note from the sidebar or create a new one</p>
        </div>
      </div>
    );
  }

  return (
    <div className="flex-1 flex flex-col bg-white dark:bg-gray-900">
      {/* Toolbar */}
      <div className="border-b border-gray-200 dark:border-gray-700 px-6 py-3 bg-gray-50 dark:bg-gray-800/50">
        <div className="flex items-center justify-between">
          <div className="flex items-center gap-3">
            {/* Category Selector */}
            <div className="relative">
              <select
                value={localCategory}
                onChange={(e) => handleCategoryChange(e.target.value)}
                className="appearance-none pl-8 pr-8 py-1.5 text-sm rounded-full bg-gray-100 dark:bg-gray-700 border-0 text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-600 focus:ring-2 focus:ring-blue-500 focus:ring-offset-0 cursor-pointer transition-colors"
              >
                <option value="">No Category</option>
                {categories.map((cat) => (
                  <option key={cat} value={cat}>
                    {cat}
                  </option>
                ))}
              </select>
              <svg className="w-4 h-4 absolute left-2.5 top-1/2 -translate-y-1/2 text-gray-500 dark:text-gray-400 pointer-events-none" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z" />
              </svg>
              <svg className="w-3 h-3 absolute right-2.5 top-1/2 -translate-y-1/2 text-gray-500 dark:text-gray-400 pointer-events-none" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
              </svg>
            </div>

            {/* Preview Toggle */}
            <button
              onClick={() => setIsPreviewMode(!isPreviewMode)}
              className={`px-3 py-1.5 rounded-full transition-colors flex items-center gap-1.5 text-sm ${
                isPreviewMode 
                  ? 'bg-blue-500 text-white' 
                  : 'bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-600'
              }`}
              title={isPreviewMode ? "Edit Mode" : "Preview Mode"}
            >
              {isPreviewMode ? (
                <>
                  <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                    <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z" />
                  </svg>
                  <span>Edit</span>
                </>
              ) : (
                <>
                  <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                    <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
                    <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z" />
                  </svg>
                  <span>Preview</span>
                </>
              )}
            </button>
          </div>

          <div className="flex items-center gap-2">
            {/* Status */}
            {(hasUnsavedChanges || isSaving) && (
              <span className={`text-xs px-2 py-1 rounded-full ${
                isSaving 
                  ? 'bg-gray-100 dark:bg-gray-700 text-gray-500 dark:text-gray-400' 
                  : 'bg-orange-100 dark:bg-orange-900/30 text-orange-600 dark:text-orange-400'
              }`}>
                {isSaving ? 'Saving...' : 'Unsaved'}
              </span>
            )}

            {/* Action Buttons */}
            <div className="flex items-center gap-1 pl-2 border-l border-gray-200 dark:border-gray-700">
              <button
                onClick={handleFavoriteToggle}
                className="p-1.5 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg transition-colors"
                title={localFavorite ? "Remove from Favorites" : "Add to Favorites"}
              >
                <svg 
                  className={`w-5 h-5 ${localFavorite ? 'text-yellow-500 fill-current' : 'text-gray-600 dark:text-gray-400'}`}
                  fill={localFavorite ? "currentColor" : "none"}
                  stroke="currentColor" 
                  viewBox="0 0 24 24"
                >
                  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M11.049 2.927c.3-.921 1.603-.921 1.902 0l1.519 4.674a1 1 0 00.95.69h4.915c.969 0 1.371 1.24.588 1.81l-3.976 2.888a1 1 0 00-.363 1.118l1.518 4.674c.3.922-.755 1.688-1.538 1.118l-3.976-2.888a1 1 0 00-1.176 0l-3.976 2.888c-.783.57-1.838-.197-1.538-1.118l1.518-4.674a1 1 0 00-.363-1.118l-3.976-2.888c-.784-.57-.38-1.81.588-1.81h4.914a1 1 0 00.951-.69l1.519-4.674z" />
                </svg>
              </button>

              <button
                onClick={handleSave}
                disabled={!hasUnsavedChanges || isSaving}
                className={`p-1.5 rounded-lg transition-colors ${
                  hasUnsavedChanges && !isSaving
                    ? 'text-blue-600 dark:text-blue-400 hover:bg-blue-50 dark:hover:bg-blue-900/30'
                    : 'text-gray-300 dark:text-gray-600 cursor-not-allowed'
                }`}
                title="Save Note"
              >
                <svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
                </svg>
              </button>

              <button
                onClick={handleDiscard}
                disabled={!hasUnsavedChanges || isSaving}
                className={`p-1.5 rounded-lg transition-colors ${
                  hasUnsavedChanges && !isSaving
                    ? 'text-gray-600 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700'
                    : 'text-gray-300 dark:text-gray-600 cursor-not-allowed'
                }`}
                title="Discard Changes"
              >
                <svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
                </svg>
              </button>
              
              <button
                onClick={handleExportPDF}
                disabled={isExportingPDF}
                className={`p-1.5 rounded-lg transition-colors ${
                  isExportingPDF
                    ? 'text-blue-500 cursor-wait'
                    : 'text-gray-600 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700'
                }`}
                title={isExportingPDF ? "Generating PDF..." : "Export as PDF"}
              >
                {isExportingPDF ? (
                  <svg className="w-5 h-5 animate-spin" fill="none" viewBox="0 0 24 24">
                    <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
                    <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
                  </svg>
                ) : (
                  <svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                    <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
                  </svg>
                )}
              </button>

              {/* Focus Mode Toggle */}
              {onToggleFocusMode && (
                <button
                  onClick={onToggleFocusMode}
                  className={`p-1.5 rounded-lg transition-colors ${
                    isFocusMode
                      ? 'text-blue-600 dark:text-blue-400 bg-blue-50 dark:bg-blue-900/30'
                      : 'text-gray-600 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700'
                  }`}
                  title={isFocusMode ? "Exit Focus Mode (Esc)" : "Focus Mode"}
                >
                  {isFocusMode ? (
                    <svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                      <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 5l-5-5m5 5v-4m0 4h-4" />
                    </svg>
                  ) : (
                    <svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                      <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 5l-5-5m5 5v-4m0 4h-4" />
                    </svg>
                  )}
                </button>
              )}
            </div>
          </div>
        </div>
      </div>
      
      <div className="flex-1 overflow-y-auto">
        <div className={`min-h-full ${isFocusMode ? 'max-w-3xl mx-auto w-full' : ''}`}>
          {isPreviewMode ? (
            <div className="relative">
              {isLoadingImages && (
                <div className="absolute top-4 right-4 flex items-center gap-2 text-sm text-gray-500 dark:text-gray-400 bg-white dark:bg-gray-800 px-3 py-1.5 rounded-full shadow-sm">
                  <svg className="w-4 h-4 animate-spin" fill="none" viewBox="0 0 24 24">
                    <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
                    <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
                  </svg>
                  Loading images...
                </div>
              )}
              <div 
                className={`prose prose-slate dark:prose-invert p-8 ${isFocusMode ? '' : 'max-w-none'} [&_code]:font-mono [&_pre]:font-mono [&_code]:py-0 [&_code]:px-1 [&_code]:align-baseline [&_code]:leading-none [&_img]:max-w-full [&_img]:rounded-lg [&_img]:shadow-md`}
                style={{ fontSize: `${previewFontSize}px`, fontFamily: previewFont }}
                dangerouslySetInnerHTML={{ 
                  __html: marked.parse(processedContent || '', { async: false }) as string 
                }}
              />
            </div>
          ) : (
            <div className="min-h-full p-8">
              <FloatingToolbar onFormat={handleFormat} textareaRef={textareaRef} />
              <InsertToolbar 
                textareaRef={textareaRef} 
                onInsertLink={handleInsertLink} 
                onInsertFile={handleInsertFile}
                isUploading={isUploading}
              />
              <input
                ref={fileInputRef}
                type="file"
                onChange={handleAttachmentUpload}
                className="hidden"
                accept="image/*,.pdf,.doc,.docx,.txt,.md"
              />
              <textarea
                ref={textareaRef}
                value={localContent}
                onChange={(e) => {
                  handleContentChange(e.target.value);
                  // Auto-resize textarea to fit content
                  e.target.style.height = 'auto';
                  e.target.style.height = e.target.scrollHeight + 'px';
                }}
                className="w-full resize-none border-none outline-none focus:ring-0 bg-transparent text-gray-900 dark:text-gray-100 overflow-hidden"
                style={{ fontSize: `${editorFontSize}px`, lineHeight: '1.6', minHeight: '100%', fontFamily: editorFont }}
                placeholder="Start writing in markdown..."
              />
            </div>
          )}
        </div>
      </div>
    </div>
  );
}
