import React, { useState, lazy, Suspense } from 'react';
import { Toaster } from './components/ui/sonner';
import { CodeEditor } from './components/CodeEditor';
import { AIChat } from './components/AIChat';
import { Toolbar } from './components/Toolbar';
import { FileTree, FileNode } from './components/FileTree';
import { FileTabs } from './components/FileTabs';
import { ConsolePanel } from './components/ConsolePanel';
import { FileSearchModal } from './components/FileSearchModal';
import { SearchInFilesPanel } from './components/SearchInFilesPanel';
import { CommandPalette, createDefaultCommands } from './components/CommandPalette';
import { ResizablePanelGroup, ResizablePanel, ResizableHandle } from './components/ui/resizable';
import { Dialog, DialogContent, DialogHeader, DialogTitle } from './components/ui/dialog';
import { useIsMobile } from './hooks/use-mobile';
import { useKeyboardShortcuts } from './hooks/use-keyboard-shortcuts';
import { Tabs, TabsContent, TabsList, TabsTrigger } from './components/ui/tabs';
import { toast } from 'sonner';
import { ExtraTabs } from './components/ui/tabs-extra';
import { Button } from './components/ui/button';
import { initPostHog, captureEvent } from './lib/posthog';
import { initSentry, captureError } from './lib/sentry';
import { LoadingSpinner } from './components/ui/loading-spinner';

import { PlatformId } from './lib/platforms';
import { ProjectConfig } from './components/NewProjectModal';

// Lazy load heavy/modal components for code splitting and better initial load
const TemplatesDrawer = lazy(() => import('./components/TemplatesDrawer').then(m => ({ default: m.TemplatesDrawer })));
const WelcomeDialog = lazy(() => import('./components/WelcomeDialog').then(m => ({ default: m.WelcomeDialog })));
const PreviewModal = lazy(() => import('./components/PreviewModal').then(m => ({ default: m.PreviewModal })));
const NewProjectModal = lazy(() => import('./components/NewProjectModal').then(m => ({ default: m.NewProjectModal })));
const EducationPanel = lazy(() => import('./components/EducationPanel').then(m => ({ default: m.EducationPanel })));
const PassportLogin = lazy(() => import('./components/PassportLogin').then(m => ({ default: m.PassportLogin })));
const TranslationPanel = lazy(() => import('./components/TranslationPanel').then(m => ({ default: m.TranslationPanel })));
const AvatarToolkit = lazy(() => import('./components/AvatarToolkit'));
const VisualScriptingCanvas = lazy(() => import('./components/visual-scripting/VisualScriptingCanvas'));
const AssetLibrary = lazy(() => import('./components/assets/AssetLibrary'));
const LivePreview = lazy(() => import('./components/preview/LivePreview'));

function App() {
  const [currentCode, setCurrentCode] = useState('');
  const [showTemplates, setShowTemplates] = useState(false);
  const [showPreview, setShowPreview] = useState(false);
  const [showNewProject, setShowNewProject] = useState(false);
  const [showFileSearch, setShowFileSearch] = useState(false);
  const [showCommandPalette, setShowCommandPalette] = useState(false);
  const [showSearchInFiles, setShowSearchInFiles] = useState(false);
  const [showTranslation, setShowTranslation] = useState(false);
  const [showAvatarToolkit, setShowAvatarToolkit] = useState(false);
  const [showVisualScripting, setShowVisualScripting] = useState(false);
  const [showAssetLibrary, setShowAssetLibrary] = useState(false);
  const [showLivePreview, setShowLivePreview] = useState(false);
  const [code, setCode] = useState('');
  const [currentPlatform, setCurrentPlatform] = useState<PlatformId>('roblox');
  const isMobile = useIsMobile();

  const [showPassportLogin, setShowPassportLogin] = useState(false);
  const [consoleCollapsed, setConsoleCollapsed] = useState(isMobile);
  const [user, setUser] = useState<{ login: string; avatarUrl: string; email: string } | null>(() => {
    try {
      const stored = typeof window !== 'undefined' ? localStorage.getItem('aethex-user') : null;
      return stored ? JSON.parse(stored) : null;
    } catch (error) {
      console.error('Failed to load user from localStorage:', error);
      captureError(error as Error, { context: 'user_state_initialization' });
      return null;
    }
  });

  React.useEffect(() => {
    try {
      initPostHog();
      initSentry();
    } catch (error) {
      console.error('Failed to initialize analytics:', error);
    }
  }, []);

  // Keyboard shortcuts
  useKeyboardShortcuts([
    {
      key: 's',
      meta: true, // Cmd on Mac
      ctrl: true, // Ctrl on Windows/Linux
      handler: () => {
        toast.success('File saved automatically!');
        captureEvent('keyboard_shortcut', { action: 'save' });
      },
      description: 'Save file',
    },
    {
      key: 'p',
      meta: true,
      ctrl: true,
      handler: () => {
        setShowFileSearch(true);
        captureEvent('keyboard_shortcut', { action: 'file_search' });
      },
      description: 'Quick file search',
    },
    {
      key: 'k',
      meta: true,
      ctrl: true,
      handler: () => {
        setShowCommandPalette(true);
        captureEvent('keyboard_shortcut', { action: 'command_palette' });
      },
      description: 'Command palette',
    },
    {
      key: 'n',
      meta: true,
      ctrl: true,
      handler: () => {
        setShowNewProject(true);
        captureEvent('keyboard_shortcut', { action: 'new_project' });
      },
      description: 'New project',
    },
    {
      key: '/',
      meta: true,
      ctrl: true,
      handler: () => {
        // Monaco editor has built-in Cmd/Ctrl+F for find
        toast.info('Use Cmd/Ctrl+F in the editor to find text');
        captureEvent('keyboard_shortcut', { action: 'find' });
      },
      description: 'Find in editor',
    },
    {
      key: 'f',
      meta: true,
      ctrl: true,
      shift: true,
      handler: () => {
        setShowSearchInFiles(true);
        captureEvent('keyboard_shortcut', { action: 'search_in_files' });
      },
      description: 'Search in all files',
    },
    {
      key: '`',
      meta: true,
      ctrl: true,
      handler: () => {
        setConsoleCollapsed(!consoleCollapsed);
        captureEvent('keyboard_shortcut', { action: 'toggle_terminal' });
      },
      description: 'Toggle terminal',
    },
  ]);

  const handleLoginSuccess = (user: { login: string; avatarUrl: string; email: string }) => {
    try {
      setUser(user);
      localStorage.setItem('aethex-user', JSON.stringify(user));
      captureEvent('login', { user });
      toast.success('Successfully signed in!');
    } catch (error) {
      console.error('Failed to save user session:', error);
      captureError(error as Error, { context: 'login_success' });
      toast.error('Failed to save session. Please try again.');
    }
  };

  const handleSignOut = () => {
    try {
      setUser(null);
      localStorage.removeItem('aethex-user');
      toast.success('Signed out successfully');
    } catch (error) {
      console.error('Failed to sign out:', error);
      captureError(error as Error, { context: 'sign_out' });
      toast.error('Failed to sign out. Please try again.');
    }
  };

  const [files, setFiles] = useState<FileNode[]>([
    {
      id: 'root',
      name: 'src',
      type: 'folder',
      children: [
        {
          id: 'file-1',
          name: 'script.lua',
          type: 'file',
          content: `-- Welcome to AeThex Studio!
-- Write your Roblox Lua code here

local Players = game:GetService("Players")

Players.PlayerAdded:Connect(function(player)
    print(player.Name .. " joined the game!")
    
    local leaderstats = Instance.new("Folder")
    leaderstats.Name = "leaderstats"
    leaderstats.Parent = player
    
    local coins = Instance.new("IntValue")
    coins.Name = "Coins"
    coins.Value = 0
    coins.Parent = leaderstats
end)`,
        },
      ],
    },
  ]);

  const [openFiles, setOpenFiles] = useState<FileNode[]>([]);
  const [activeFileId, setActiveFileId] = useState<string>('file-1');

  const handleTemplateSelect = (templateCode: string) => {
    setCode(templateCode);
    setCurrentCode(templateCode);
    // Update active file content
    if (activeFileId) {
      handleCodeChange(templateCode);
    }
  };

  const handleCodeChange = (newCode: string) => {
    setCurrentCode(newCode);
    setCode(newCode);

    // Update the file content in the files tree
    if (activeFileId) {
      setFiles((prev) => {
        const updateFileContent = (nodes: FileNode[]): FileNode[] => {
          return nodes.map((node) => {
            if (node.id === activeFileId) {
              return { ...node, content: newCode };
            }
            if (node.children) {
              return { ...node, children: updateFileContent(node.children) };
            }
            return node;
          });
        };
        return updateFileContent(prev || []);
      });

      // Also update in openFiles to keep tabs in sync
      setOpenFiles((prev) =>
        (prev || []).map((file) =>
          file.id === activeFileId ? { ...file, content: newCode } : file
        )
      );
    }
  };

  const handleFileSelect = (file: FileNode) => {
    if (file.type === 'file') {
      setActiveFileId(file.id);
      if (!(openFiles || []).find((f) => f.id === file.id)) {
        setOpenFiles((prev) => [...(prev || []), file]);
      }
      setCode(file.content || '');
      setCurrentCode(file.content || '');
    }
    captureEvent('file_select', { fileId: file.id });
  };

  const handleFileCreate = (name: string, parentId?: string) => {
    try {
      if (!name || name.trim() === '') {
        toast.error('File name cannot be empty');
        return;
      }

      const newFile: FileNode = {
        id: `file-${Date.now()}`,
        name: name.endsWith('.lua') ? name : `${name}.lua`,
        type: 'file',
        content: '-- New file\n',
      };

      setFiles((prev) => {
        const addToFolder = (nodes: FileNode[]): FileNode[] => {
          return nodes.map((node) => {
            if (node.id === 'root' && !parentId) {
              return {
                ...node,
                children: [...(node.children || []), newFile],
              };
            }
            if (node.id === parentId && node.type === 'folder') {
              return {
                ...node,
                children: [...(node.children || []), newFile],
              };
            }
            if (node.children) {
              return { ...node, children: addToFolder(node.children) };
            }
            return node;
          });
        };
        return addToFolder(prev || []);
      });

      captureEvent('file_create', { name, parentId });
      toast.success(`Created ${newFile.name}`);
    } catch (error) {
      console.error('Failed to create file:', error);
      captureError(error as Error, { context: 'file_create', name, parentId });
      toast.error('Failed to create file. Please try again.');
    }
  };

  const handleFileRename = (id: string, newName: string) => {
    try {
      if (!newName || newName.trim() === '') {
        toast.error('File name cannot be empty');
        return;
      }

      setFiles((prev) => {
        const rename = (nodes: FileNode[]): FileNode[] => {
          return nodes.map((node) => {
            if (node.id === id) {
              return { ...node, name: newName };
            }
            if (node.children) {
              return { ...node, children: rename(node.children) };
            }
            return node;
          });
        };
        return rename(prev || []);
      });

      captureEvent('file_rename', { id, newName });
    } catch (error) {
      console.error('Failed to rename file:', error);
      captureError(error as Error, { context: 'file_rename', id, newName });
      toast.error('Failed to rename file. Please try again.');
    }
  };

  const handleFileDelete = (id: string) => {
    try {
      setFiles((prev) => {
        const deleteNode = (nodes: FileNode[]): FileNode[] => {
          return nodes.filter((node) => {
            if (node.id === id) return false;
            if (node.children) {
              node.children = deleteNode(node.children);
            }
            return true;
          });
        };
        return deleteNode(prev || []);
      });

      setOpenFiles((prev) => (prev || []).filter((f) => f.id !== id));
      if (activeFileId === id) {
        setActiveFileId((openFiles || [])[0]?.id || '');
      }

      captureEvent('file_delete', { id });
    } catch (error) {
      console.error('Failed to delete file:', error);
      captureError(error as Error, { context: 'file_delete', id });
      toast.error('Failed to delete file. Please try again.');
    }
  };

  const handleFileMove = (fileId: string, targetParentId: string) => {
    try {
      setFiles((prev) => {
        let movedNode: FileNode | null = null;

        // First, find and remove the node from its current location
        const removeNode = (nodes: FileNode[]): FileNode[] => {
          return nodes.filter((node) => {
            if (node.id === fileId) {
              movedNode = node;
              return false;
            }
            if (node.children) {
              node.children = removeNode(node.children);
            }
            return true;
          });
        };

        // Then, add the node to the target folder
        const addToTarget = (nodes: FileNode[]): FileNode[] => {
          return nodes.map((node) => {
            if (node.id === targetParentId && node.type === 'folder') {
              return {
                ...node,
                children: [...(node.children || []), movedNode!],
              };
            }
            if (node.children) {
              return { ...node, children: addToTarget(node.children) };
            }
            return node;
          });
        };

        const withoutMoved = removeNode(prev || []);
        if (movedNode) {
          return addToTarget(withoutMoved);
        }
        return prev || [];
      });

      captureEvent('file_move', { fileId, targetParentId });
    } catch (error) {
      console.error('Failed to move file:', error);
      captureError(error as Error, { context: 'file_move', fileId, targetParentId });
      toast.error('Failed to move file. Please try again.');
    }
  };

  const handleFileClose = (id: string) => {
    setOpenFiles((prev) => (prev || []).filter((f) => f.id !== id));
    if (activeFileId === id) {
      const remaining = (openFiles || []).filter((f) => f.id !== id);
      setActiveFileId(remaining[0]?.id || '');
    }
  };

  const handleCreateProject = (config: ProjectConfig) => {
    try {
      if (!config.name || config.name.trim() === '') {
        toast.error('Project name cannot be empty');
        return;
      }

      const projectFiles: FileNode[] = [
        {
          id: 'root',
          name: config.name,
          type: 'folder',
          children: [
            {
              id: `file-${Date.now()}`,
              name: 'main.lua',
              type: 'file',
              content: `-- ${config.name}\n-- Template: ${config.template}\n\nprint("Project initialized!")`,
            },
          ],
        },
      ];

      setFiles(projectFiles);
      setOpenFiles([]);
      setActiveFileId('');

      captureEvent('project_create', { name: config.name, template: config.template });
      toast.success(`Project "${config.name}" created successfully!`);
    } catch (error) {
      console.error('Failed to create project:', error);
      captureError(error as Error, { context: 'project_create', config });
      toast.error('Failed to create project. Please try again.');
    }
  };

  // Example user stub for profile
  const demoUser = user || {
    login: 'demo-user',
    avatarUrl: 'https://avatars.githubusercontent.com/u/1?v=4',
    email: 'demo@aethex.com',
  };
  return (
    <div className="h-screen w-screen flex flex-col bg-background text-foreground">
      {/* Top Bar */}
      <div className="flex items-center h-12 px-4 bg-card border-b border-border shadow-sm z-20">
        <span className="text-xl font-bold tracking-tight select-none">
          Ae<span className="text-accent">Thex</span>
        </span>
        <span className="ml-2 text-sm text-muted-foreground font-medium select-none">Studio</span>
        <div className="flex-1" />
        <Toolbar
          code={currentCode}
          currentPlatform={currentPlatform}
          onPlatformChange={setCurrentPlatform}
          onTranslateClick={() => setShowTranslation(true)}
          onTemplatesClick={() => setShowTemplates(true)}
          onPreviewClick={() => setShowPreview(true)}
          onNewProjectClick={() => setShowNewProject(true)}
          onAvatarToolkitClick={() => setShowAvatarToolkit(true)}
          onVisualScriptingClick={() => setShowVisualScripting(true)}
          onAssetLibraryClick={() => setShowAssetLibrary(true)}
          onLivePreviewClick={() => setShowLivePreview(true)}
        />
      </div>

      {/* Main Content Area */}
      <div className="flex flex-1 min-h-0 min-w-0 overflow-hidden">
        {/* Activity Bar */}
        <div className="flex flex-col items-center w-12 bg-muted border-r border-border py-2 gap-2 z-10">
          {/* Example activity icons, replace with real navigation/actions */}
          <button className="w-8 h-8 rounded flex items-center justify-center hover:bg-accent/20 text-accent" title="Files">
            <svg width="20" height="20" fill="none" stroke="currentColor" strokeWidth="2" viewBox="0 0 24 24"><path d="M4 4h16v16H4z" /></svg>
          </button>
          <button className="w-8 h-8 rounded flex items-center justify-center hover:bg-accent/20 text-accent" title="AI">
            <svg width="20" height="20" fill="none" stroke="currentColor" strokeWidth="2" viewBox="0 0 24 24"><circle cx="12" cy="12" r="8" /></svg>
          </button>
          <button className="w-8 h-8 rounded flex items-center justify-center hover:bg-accent/20 text-accent" title="Learn">
            <svg width="20" height="20" fill="none" stroke="currentColor" strokeWidth="2" viewBox="0 0 24 24"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20" /></svg>
          </button>
        </div>

        {/* Main Panels */}
        <div className="flex-1 flex flex-col min-h-0 min-w-0">
          <div className="flex-1 min-h-0 min-w-0 overflow-hidden">
            <ResizablePanelGroup orientation="horizontal">
              <ResizablePanel defaultSize={16} minSize={10} maxSize={25}>
                <FileTree
                  files={files || []}
                  onFileSelect={handleFileSelect}
                  onFileCreate={handleFileCreate}
                  onFileRename={handleFileRename}
                  onFileDelete={handleFileDelete}
                  onFileMove={handleFileMove}
                  selectedFileId={activeFileId}
                />
              </ResizablePanel>
              <ResizableHandle className="w-1 bg-border hover:bg-accent transition-colors" />
              <ResizablePanel defaultSize={54} minSize={30}>
                <div className="h-full flex flex-col">
                  <FileTabs
                    openFiles={openFiles || []}
                    activeFileId={activeFileId}
                    onFileSelect={handleFileSelect}
                    onFileClose={handleFileClose}
                  />
                  <div className="flex-1">
                    <CodeEditor onCodeChange={setCurrentCode} platform={currentPlatform} />
                  </div>
                </div>
              </ResizablePanel>
              <ResizableHandle className="w-1 bg-border hover:bg-accent transition-colors" />
              <ResizablePanel defaultSize={15} minSize={10}>
                <AIChat currentCode={currentCode} />
              </ResizablePanel>
              <ResizableHandle className="w-1 bg-border hover:bg-accent transition-colors" />
              <ResizablePanel defaultSize={15} minSize={10}>
                <EducationPanel />
              </ResizablePanel>
            </ResizablePanelGroup>
          </div>
          <ConsolePanel
            collapsed={consoleCollapsed}
            onToggle={() => setConsoleCollapsed(!consoleCollapsed)}
            currentCode={currentCode}
            currentFile={activeFileId ? (openFiles || []).find(f => f.id === activeFileId)?.name : undefined}
            files={files || []}
            onCodeChange={setCurrentCode}
          />
          <SearchInFilesPanel
            files={files || []}
            onFileSelect={handleFileSelect}
            isOpen={showSearchInFiles}
            onClose={() => setShowSearchInFiles(false)}
          />
          <div className="w-full border-t border-border mt-2">
            <ExtraTabs user={demoUser} />
          </div>
        </div>
      </div>

      {/* Modals and overlays */}
      <Suspense fallback={null}>
        {showTemplates && (
          <TemplatesDrawer
            onSelectTemplate={handleTemplateSelect}
            onClose={() => setShowTemplates(false)}
            currentPlatform={currentPlatform}
          />
        )}
      </Suspense>
      <Suspense fallback={null}>
        <PreviewModal
          open={showPreview}
          onClose={() => setShowPreview(false)}
          code={currentCode}
        />
      </Suspense>
      <Suspense fallback={null}>
        <NewProjectModal
          open={showNewProject}
          onClose={() => setShowNewProject(false)}
          onCreateProject={handleCreateProject}
        />
      </Suspense>
      <Suspense fallback={null}>
        {showTranslation && (
          <TranslationPanel
            isOpen={showTranslation}
            onClose={() => setShowTranslation(false)}
            currentCode={currentCode}
            currentPlatform={currentPlatform}
          />
        )}
      </Suspense>
      <Suspense fallback={null}>
        {showAvatarToolkit && (
          <AvatarToolkit
            isOpen={showAvatarToolkit}
            onClose={() => setShowAvatarToolkit(false)}
          />
        )}
      </Suspense>
      <Suspense fallback={<LoadingSpinner />}>
        {showVisualScripting && (
          <Dialog open={showVisualScripting} onOpenChange={setShowVisualScripting}>
            <DialogContent className="max-w-[95vw] max-h-[90vh] w-full h-[85vh] p-0">
              <DialogHeader className="px-4 py-2 border-b">
                <DialogTitle className="flex items-center gap-2">
                  <svg className="h-5 w-5 text-primary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                    <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 10V3L4 14h7v7l9-11h-7z" />
                  </svg>
                  Visual Scripting
                </DialogTitle>
              </DialogHeader>
              <div className="flex-1 min-h-0">
                <VisualScriptingCanvas
                  platform={currentPlatform === 'uefn' ? 'uefn' : currentPlatform === 'spatial' ? 'spatial' : 'roblox'}
                  onCodeGenerated={(code) => {
                    setCurrentCode(code);
                    handleCodeChange(code);
                  }}
                />
              </div>
            </DialogContent>
          </Dialog>
        )}
      </Suspense>
      <Suspense fallback={null}>
        {showAssetLibrary && (
          <AssetLibrary
            isOpen={showAssetLibrary}
            onClose={() => setShowAssetLibrary(false)}
          />
        )}
      </Suspense>
      <Suspense fallback={<LoadingSpinner />}>
        {showLivePreview && (
          <Dialog open={showLivePreview} onOpenChange={setShowLivePreview}>
            <DialogContent className="max-w-[95vw] max-h-[90vh] w-full h-[85vh] p-0">
              <LivePreview
                code={currentCode}
                onClose={() => setShowLivePreview(false)}
              />
            </DialogContent>
          </Dialog>
        )}
      </Suspense>
      <Suspense fallback={null}>
        <WelcomeDialog />
      </Suspense>
      <FileSearchModal
        open={showFileSearch}
        onClose={() => setShowFileSearch(false)}
        files={files || []}
        onFileSelect={handleFileSelect}
      />
      <CommandPalette
        open={showCommandPalette}
        onClose={() => setShowCommandPalette(false)}
        commands={createDefaultCommands({
          onNewProject: () => setShowNewProject(true),
          onTemplates: () => setShowTemplates(true),
          onPreview: () => setShowPreview(true),
          onExport: async () => {
            const blob = new Blob([currentCode], { type: 'text/plain' });
            const url = URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = url;
            a.download = 'script.lua';
            document.body.appendChild(a);
            a.click();
            document.body.removeChild(a);
            URL.revokeObjectURL(url);
            toast.success('Script exported!');
          },
          onCopy: async () => {
            try {
              await navigator.clipboard.writeText(currentCode);
              toast.success('Code copied to clipboard!');
            } catch (error) {
              toast.error('Failed to copy code');
            }
          },
        })}
      />
      {!user && (
        <Button
          variant="secondary"
          className="fixed top-4 right-4 z-50"
          onClick={() => setShowPassportLogin(true)}
        >
          Sign In
        </Button>
      )}
      {user && (
        <div className="fixed top-4 right-4 z-50 flex items-center gap-2 bg-card px-3 py-1 rounded shadow">
          <img src={user.avatarUrl} alt={user.login} className="h-6 w-6 rounded-full" />
          <span className="text-xs font-medium">{user.login}</span>
          <Button variant="ghost" size="sm" onClick={handleSignOut}>
            Sign Out
          </Button>
        </div>
      )}
      <Suspense fallback={null}>
        <PassportLogin
          open={showPassportLogin}
          onClose={() => setShowPassportLogin(false)}
          onLoginSuccess={handleLoginSuccess}
        />
      </Suspense>
      <Toaster position="bottom-right" theme="dark" />
    </div>
  );
}

export default App;