import React, { useMemo, useCallback, useRef, useState, useEffect } from 'react';
import { X, Circle, Lock, Save, Copy, FilePlus } from 'lucide-react';
import { useEditorStore, SETTINGS_TAB_FILE_ID } from '@/core/store';
import { CodeEditor } from '@/editor/CodeEditor';
import { SettingsPanel } from '@/ui/SettingsPanel';
import { getLanguageColor } from '@/editor/languages';
import { useSecurity } from '@/contexts/SecurityContext';
import { SecureUnlockDialog } from '@/components/SecureUnlockDialog';
import { encryptText, decryptText } from '@/lib/encryption';
import { isSecureItem, getSecureFolderId } from '@/lib/security-utils';
import { Button } from '@/components/ui/button';
import {
  ContextMenu,
  ContextMenuContent,
  ContextMenuItem,
  ContextMenuSeparator,
  ContextMenuTrigger,
} from '@/components/ui/context-menu';
import { toast } from 'sonner';

const EditorTabs: React.FC<{ onSave?: () => void; onDoubleClickEmpty?: () => void }> = ({ onSave, onDoubleClickEmpty }) => {
  const { openTabs, activeTabId, setActiveTab, closeTab, updateTab, files, settings } = useEditorStore();

  const handleClose = useCallback(
    (e: React.MouseEvent, tabId: string) => {
      e.stopPropagation();
      closeTab(tabId);
    },
    [closeTab]
  );

  const handleCloseOthers = useCallback(
    (tabId: string) => {
      setActiveTab(tabId);
      openTabs.filter((t) => t.id !== tabId).forEach((t) => closeTab(t.id));
    },
    [openTabs, closeTab, setActiveTab]
  );

  const handleCloseToTheRight = useCallback(
    (tabId: string) => {
      const index = openTabs.findIndex((t) => t.id === tabId);
      if (index === -1) return;
      openTabs.slice(index + 1).forEach((t) => closeTab(t.id));
    },
    [openTabs, closeTab]
  );

  const handleCloseUnmodified = useCallback(() => {
    openTabs.filter((t) => !t.isDirty).forEach((t) => closeTab(t.id));
  }, [openTabs, closeTab]);

  const handleCloseAll = useCallback(() => {
    openTabs.forEach((t) => closeTab(t.id));
  }, [openTabs, closeTab]);

  const handleCopyFileName = useCallback(async (fileName: string) => {
    try {
      await navigator.clipboard.writeText(fileName);
      toast.success('File name copied');
    } catch {
      toast.error('Failed to copy');
    }
  }, []);

  const unmodifiedCount = openTabs.filter((t) => !t.isDirty).length;
  const hasOthers = openTabs.length > 1;
  const hasTabsToTheRight = (index: number) => index >= 0 && index < openTabs.length - 1;

  return (
    <div className="flex bg-tab-inactive border-b border-tab-border overflow-x-auto apple-scroll">
      {settings.autoSave === false && onSave && (
        <div className="flex items-center px-2 border-r border-tab-border">
          <Button
            variant="ghost"
            size="sm"
            onClick={(e) => {
              e.stopPropagation();
              onSave();
            }}
            className="h-7 text-xs gap-1.5"
          >
            <Save className="w-3 h-3" />
            Save
          </Button>
        </div>
      )}
      {openTabs.map((tab, index) => (
        <ContextMenu key={tab.id}>
          <ContextMenuTrigger asChild>
            <div
              className={`editor-tab ${tab.id === activeTabId ? 'active' : ''}`}
              onClick={() => setActiveTab(tab.id)}
            >
              <span
                className="w-2 h-2 rounded-full flex-shrink-0"
                style={{ backgroundColor: getLanguageColor(tab.language) }}
              />
              <span className="text-sm truncate max-w-32">{tab.fileName}</span>
              {files.find(f => f.id === tab.fileId)?.secure && (
                <Lock className="w-3 h-3 text-primary flex-shrink-0" />
              )}
              {tab.isDirty && (
                <Circle className="w-2 h-2 fill-current text-muted-foreground flex-shrink-0" />
              )}
              <button
                type="button"
                onClick={(e) => handleClose(e, tab.id)}
                className="p-0.5 rounded hover:bg-white/10 opacity-60 hover:opacity-100"
              >
                <X className="w-3 h-3" />
              </button>
            </div>
          </ContextMenuTrigger>
          <ContextMenuContent className="w-52">
            <ContextMenuItem onClick={() => closeTab(tab.id)}>
              <X className="w-3 h-3 mr-2" />
              Close
            </ContextMenuItem>
            {hasOthers && (
              <ContextMenuItem onClick={() => handleCloseOthers(tab.id)}>
                Close Others
              </ContextMenuItem>
            )}
            {hasTabsToTheRight(index) && (
              <ContextMenuItem onClick={() => handleCloseToTheRight(tab.id)}>
                Close to the Right
              </ContextMenuItem>
            )}
            {unmodifiedCount > 0 && (
              <ContextMenuItem onClick={handleCloseUnmodified}>
                Close Unmodified
              </ContextMenuItem>
            )}
            {openTabs.length > 0 && (
              <ContextMenuItem onClick={handleCloseAll}>
                Close All
              </ContextMenuItem>
            )}
            <ContextMenuSeparator />
            <ContextMenuItem onClick={() => handleCopyFileName(tab.fileName)}>
              <Copy className="w-3 h-3 mr-2" />
              Copy File Name
            </ContextMenuItem>
          </ContextMenuContent>
        </ContextMenu>
      ))}
      {onDoubleClickEmpty && (
        <ContextMenu>
          <ContextMenuTrigger asChild>
            <div
              className="flex-1 min-w-[60px] cursor-text"
              onDoubleClick={(e) => {
                e.stopPropagation();
                onDoubleClickEmpty();
              }}
            />
          </ContextMenuTrigger>
          <ContextMenuContent className="w-52">
            <ContextMenuItem onClick={onDoubleClickEmpty}>
              <FilePlus className="w-3 h-3 mr-2" />
              New File
            </ContextMenuItem>
            {openTabs.length > 0 && (
              <>
                <ContextMenuSeparator />
                <ContextMenuItem onClick={handleCloseAll}>
                  <X className="w-3 h-3 mr-2" />
                  Close All
                </ContextMenuItem>
              </>
            )}
          </ContextMenuContent>
        </ContextMenu>
      )}
    </div>
  );
};

export const EditorArea: React.FC = () => {
  const { openTabs, activeTabId, files, updateFile, updateTab, settings, bookmarks, addBookmark, loadBookmarks, addFile, openFile } = useEditorStore();
  const { isUnlocked, getUnlockedPassword } = useSecurity();
  const [showUnlockDialog, setShowUnlockDialog] = useState(false);
  const [currentCursorLine, setCurrentCursorLine] = useState(1);
  const [decryptedContent, setDecryptedContent] = useState<string | null>(null);
  const saveTimeoutRef = useRef<NodeJS.Timeout | null>(null);
  const pendingContentRef = useRef<string | null>(null);

  const activeTab = useMemo(
    () => openTabs.find((t) => t.id === activeTabId),
    [openTabs, activeTabId]
  );

  const activeFile = useMemo(
    () => (activeTab ? files.find((f) => f.id === activeTab.fileId) : null),
    [activeTab, files]
  );

  // Check if file is secure (directly or inherited from parent folder)
  const isSecureNote = useMemo(() => {
    if (!activeFile) return false;
    return isSecureItem(activeFile, files);
  }, [activeFile, files]);

  // Get the secure folder ID (for files inside secure folders, use parent folder ID)
  const secureFolderId = useMemo(() => {
    if (!activeFile) return null;
    return getSecureFolderId(activeFile, files);
  }, [activeFile, files]);

  // Check if the secure folder (or file itself) is unlocked
  const isUnlockedNote = useMemo(() => {
    if (!isSecureNote || !secureFolderId) return true;
    return isUnlocked(secureFolderId);
  }, [isSecureNote, secureFolderId, isUnlocked]);

  // Decrypt content when secure note is unlocked
  useEffect(() => {
    if (activeFile && isSecureNote && isUnlockedNote && activeFile.content) {
      // Use secure folder password if file is inside a secure folder
      const passwordId = secureFolderId || activeFile.id;
      const password = getUnlockedPassword(passwordId);
      if (password) {
        decryptText(activeFile.content, password)
          .then(decrypted => {
            setDecryptedContent(decrypted);
          })
          .catch(err => {
            console.error('Decryption error:', err);
            setDecryptedContent('[Decryption failed]');
          });
      }
    } else if (activeFile && !isSecureNote) {
      setDecryptedContent(null);
    } else if (activeFile && isSecureNote && !isUnlockedNote) {
      setDecryptedContent('[Encrypted - Unlock to view]');
    }
  }, [activeFile, isSecureNote, isUnlockedNote, secureFolderId, getUnlockedPassword]);

  // Manual save function
  const handleManualSave = useCallback(async () => {
    if (!activeFile || !activeTab) return;
    
    const content = pendingContentRef.current || (decryptedContent !== null ? decryptedContent : (activeFile.content || ''));
    let contentToSave = content;
    
    // If secure note, encrypt before saving
    if (isSecureNote && isUnlockedNote) {
      // Use secure folder password if file is inside a secure folder
      const passwordId = secureFolderId || activeFile.id;
      const password = getUnlockedPassword(passwordId);
      if (password) {
        try {
          contentToSave = await encryptText(content, password);
        } catch (err) {
          console.error('Encryption error:', err);
          toast.error('Failed to encrypt content');
          return;
        }
      } else {
        toast.error('No password available');
        return;
      }
    }
    
    try {
      await updateFile(activeFile.id, { content: contentToSave });
      updateTab(activeTab.id, { isDirty: false });
      pendingContentRef.current = null;
      toast.success('File saved');
    } catch (error) {
      console.error('Save error:', error);
      toast.error('Failed to save file');
    }
  }, [activeFile, activeTab, updateFile, updateTab, isSecureNote, isUnlockedNote, secureFolderId, getUnlockedPassword, decryptedContent]);

  const handleGutterLineClick = useCallback(async (line: number) => {
    if (!activeFile || isSecureNote) return;
    try {
      await addBookmark(activeFile.id, line, `Line ${line}`);
      await loadBookmarks();
      toast.success('Bookmark added');
    } catch (error) {
      console.error('Failed to add bookmark:', error);
      toast.error('Failed to add bookmark');
    }
  }, [activeFile, isSecureNote, addBookmark, loadBookmarks]);

  const handleContentChange = useCallback(
    async (content: string) => {
      if (activeFile && activeTab) {
        // Store pending content
        pendingContentRef.current = content;
        
        // Mark as dirty
        if (!activeTab.isDirty) {
          updateTab(activeTab.id, { isDirty: true });
        }
        
        // Auto-save if enabled
        if (settings.autoSave !== false) {
          // Clear existing timeout
          if (saveTimeoutRef.current) {
            clearTimeout(saveTimeoutRef.current);
          }
          
          // Set new timeout for auto-save
          saveTimeoutRef.current = setTimeout(async () => {
            let contentToSave = content;
            
            // If secure note, encrypt before saving
            if (isSecureNote && isUnlockedNote) {
              // Use secure folder password if file is inside a secure folder
              const passwordId = secureFolderId || activeFile.id;
              const password = getUnlockedPassword(passwordId);
              if (password) {
                try {
                  contentToSave = await encryptText(content, password);
                } catch (err) {
                  console.error('Encryption error:', err);
                  return; // Don't save if encryption fails
                }
              } else {
                return; // Don't save if no password
              }
            }
            
            try {
              await updateFile(activeFile.id, { content: contentToSave });
              updateTab(activeTab.id, { isDirty: false });
              pendingContentRef.current = null;
            } catch (error) {
              console.error('Auto-save error:', error);
            }
          }, settings.autoSaveDelay || 1000);
        }
      }
    },
    [activeFile, activeTab, updateFile, updateTab, isSecureNote, isUnlockedNote, secureFolderId, getUnlockedPassword, settings.autoSave, settings.autoSaveDelay]
  );

  // Cleanup timeout on unmount
  useEffect(() => {
    return () => {
      if (saveTimeoutRef.current) {
        clearTimeout(saveTimeoutRef.current);
      }
    };
  }, []);

  // Show unlock dialog when trying to open secure note
  useEffect(() => {
    if (activeFile && isSecureNote && !isUnlockedNote && !showUnlockDialog) {
      setShowUnlockDialog(true);
    }
  }, [activeFile, isSecureNote, isUnlockedNote, showUnlockDialog]);

  // Reset cursor line and pending content when switching files
  useEffect(() => {
    if (activeFile) {
      setCurrentCursorLine(1);
      pendingContentRef.current = null;
    }
  }, [activeFile?.id]);

  const handleCreateUntitled = useCallback(async () => {
    try {
      const newFile = await addFile({
        name: 'Untitled',
        type: 'file',
        parentId: null,
        language: 'plaintext',
        content: '',
      });
      openFile(newFile.id);
    } catch (error) {
      console.error('Failed to create untitled file:', error);
      toast.error('Failed to create new file');
    }
  }, [addFile, openFile]);

  if (openTabs.length === 0) {
    return (
      <div
        className="flex-1 flex flex-col items-center justify-center bg-editor-bg cursor-text"
        onDoubleClick={handleCreateUntitled}
      >
        <div className="text-center max-w-2xl px-8">
          <img
            src="/logo.png"
            alt="MindPad"
            width={200}
            height={200}
            className="h-20 w-auto mx-auto mb-6 object-contain h-[200px] "
          />
          <h2 className="text-2xl font-semibold mb-2">Welcome to MindPad</h2>
          <p className="text-muted-foreground text-sm mb-8">
            Select a note from the sidebar to start editing, or double-click
            here to create a new file.
          </p>
        </div>
      </div>
    );
  }

  const isSettingsTab = activeTab?.fileId === SETTINGS_TAB_FILE_ID;

  return (
    <div className="flex-1 flex flex-col min-h-0 bg-editor-bg overflow-hidden">
      <EditorTabs onSave={isSettingsTab ? undefined : handleManualSave} onDoubleClickEmpty={handleCreateUntitled} />
      <div className="flex-1 min-h-0 overflow-hidden relative">
        {isSettingsTab ? (
          <div className="absolute inset-0 overflow-auto bg-background">
            <SettingsPanel />
          </div>
        ) : isSecureNote && !isUnlockedNote ? (
          <div className="h-full flex items-center justify-center bg-editor-bg">
            <div className="text-center">
              <div className="w-16 h-16 mx-auto mb-4 rounded-2xl bg-primary/10 flex items-center justify-center">
                <Lock className="w-8 h-8 text-primary" />
              </div>
              <h3 className="text-lg font-semibold mb-2">Secure Note Locked</h3>
              <p className="text-muted-foreground text-sm mb-4">
                This note is encrypted. Unlock it to view and edit.
              </p>
              <button
                onClick={() => setShowUnlockDialog(true)}
                className="px-4 py-2 bg-primary text-primary-foreground rounded-lg hover:bg-primary/90"
              >
                Unlock Note
              </button>
            </div>
          </div>
        ) : (
          activeFile && (
            <div key={activeFile.id} className="absolute inset-0 flex flex-col overflow-hidden">
              <div className="editor-scroll-container flex-1 min-h-0 flex flex-col">
                <div className="editor-inner flex-1 min-h-0 flex flex-col">
                  <CodeEditor
                    content={decryptedContent !== null ? decryptedContent : (activeFile.content || '')}
                    language={activeFile.language || 'plaintext'}
                    onChange={handleContentChange}
                    readOnly={isSecureNote && !isUnlockedNote}
                    onCursorLineChange={setCurrentCursorLine}
                    onLineClick={!isSecureNote ? handleGutterLineClick : undefined}
                    bookmarks={!isSecureNote ? bookmarks.filter(b => b.fileId === activeFile.id).map(b => ({ line: b.line, id: b.id })) : []}
                  />
                </div>
              </div>
            </div>
          )
        )}
        
        {/* Secure Unlock Dialog */}
        {activeFile && isSecureNote && (
          <SecureUnlockDialog
            open={showUnlockDialog}
            onOpenChange={setShowUnlockDialog}
            itemId={secureFolderId || activeFile.id}
            itemName={secureFolderId ? files.find(f => f.id === secureFolderId)?.name || 'Secure Folder' : activeFile.name}
            itemType={secureFolderId ? 'folder' : 'note'}
            onUnlocked={() => {
              setShowUnlockDialog(false);
            }}
          />
        )}

      </div>
    </div>
  );
};

export default EditorArea;
