'use client';

import { useState, useEffect, useCallback, useRef, Suspense, useMemo } from 'react';
import { useSearchParams, useRouter } from 'next/navigation';
import { motion, AnimatePresence } from 'framer-motion';
import {
  Code, Play, RefreshCw, AlertTriangle, CheckCircle, Copy,
  ChevronDown, ChevronRight, Terminal, Eye, EyeOff, Settings,
  FileCode, Layout, Database, Boxes, Zap, Ghost, ArrowLeft,
  Search, Filter, Clock, XCircle, Maximize2, Minimize2, Braces,
  GitCompare, Sparkles, Wand2, Save, RotateCcw, Loader2, History,
  ChevronUp, Layers
} from 'lucide-react';
import Link from 'next/link';
import dynamic from 'next/dynamic';
import { VOCAB } from '@/lib/white-label/constants';

// Dynamically import Monaco Editor to avoid SSR issues
const MonacoEditor = dynamic(() => import('@monaco-editor/react'), { 
  ssr: false,
  loading: () => (
    <div className="h-full flex items-center justify-center bg-black/50">
      <Loader2 className="w-6 h-6 text-brand animate-spin" />
    </div>
  )
});

interface Artifact {
  id: string;
  taskId: string;
  type: string;
  path: string;
  contentPreview: string;
  contentLength: number;
  checksum: string;
  version: number;
  deployed: boolean;
  createdAt: string;
  task: {
    id: string;
    status: string;
    prompt: string;
    project: { id: string; name: string; slug: string } | null;
  };
}

interface FullArtifact {
  id: string;
  taskId: string;
  type: string;
  path: string;
  content: string;
  checksum: string;
  version: number;
  deployed: boolean;
  createdAt: string;
}

interface ConsoleMessage {
  type: 'log' | 'error' | 'warn' | 'info';
  message: string;
  timestamp: Date;
}

interface MockTemplate {
  name: string;
  icon: React.ReactNode;
  data: Record<string, unknown>;
}

const TYPE_ICONS: Record<string, React.ReactNode> = {
  'prisma_model': <Database className="w-4 h-4" />,
  'api_route': <Zap className="w-4 h-4" />,
  'ui_component': <Layout className="w-4 h-4" />,
  'page': <FileCode className="w-4 h-4" />,
  'type': <Braces className="w-4 h-4" />,
  'util': <Boxes className="w-4 h-4" />,
};

const TYPE_COLORS: Record<string, string> = {
  'prisma_model': 'text-brand-secondary-light bg-brand-secondary/20',
  'api_route': 'text-brand bg-brand-deep/20',
  'ui_component': 'text-green-400 bg-green-500/20',
  'page': 'text-yellow-400 bg-yellow-500/20',
  'type': 'text-blue-400 bg-blue-500/20',
  'util': 'text-gray-400 bg-gray-500/20',
};

// Mock data templates for quick testing
const MOCK_TEMPLATES: MockTemplate[] = [
  {
    name: 'User Profile',
    icon: <Sparkles className="w-3 h-3" />,
    data: {
      user: {
        id: '1',
        name: 'Scott Mitchell',
        email: 'scott@ghostfoundry.ai',
        avatar: 'https://ui-avatars.com/api/?name=Scott+Mitchell&background=6366f1&color=fff',
        role: 'admin'
      }
    }
  },
  {
    name: 'Product Item',
    icon: <Boxes className="w-3 h-3" />,
    data: {
      product: {
        id: '123',
        name: 'Ghost Operator Pro',
        price: 299.99,
        description: 'Enterprise AI automation suite',
        image: 'https://ui-avatars.com/api/?name=GO&background=06b6d4&color=fff',
        inStock: true
      }
    }
  },
  {
    name: 'Task Card',
    icon: <FileCode className="w-3 h-3" />,
    data: {
      task: {
        id: 'task-001',
        title: 'Build authentication flow',
        status: 'in_progress',
        priority: 'high',
        assignee: 'Tes',
        dueDate: '2026-03-15'
      }
    }
  },
  {
    name: 'Notification',
    icon: <Zap className="w-3 h-3" />,
    data: {
      notification: {
        type: 'success',
        title: 'Deployment Complete',
        message: 'Your component has been deployed to production.',
        timestamp: new Date().toISOString()
      }
    }
  },
  {
    name: 'List Data',
    icon: <Layers className="w-3 h-3" />,
    data: {
      items: [
        { id: '1', name: 'Item Alpha', status: 'active' },
        { id: '2', name: 'Item Beta', status: 'pending' },
        { id: '3', name: 'Item Gamma', status: 'completed' }
      ]
    }
  }
];

function SandboxContent() {
  const searchParams = useSearchParams();
  const router = useRouter();
  const artifactIdFromUrl = searchParams.get('artifact');
  
  // State
  const [artifacts, setArtifacts] = useState<Artifact[]>([]);
  const [selectedArtifact, setSelectedArtifact] = useState<FullArtifact | null>(null);
  const [loading, setLoading] = useState(true);
  const [loadingArtifact, setLoadingArtifact] = useState(false);
  const [error, setError] = useState<string | null>(null);
  
  // Code editing state
  const [editedCode, setEditedCode] = useState<string>('');
  const [hasChanges, setHasChanges] = useState(false);
  const [autoPreview, setAutoPreview] = useState(true);
  
  // Filter state
  const [typeFilter, setTypeFilter] = useState<string>('');
  const [searchQuery, setSearchQuery] = useState('');
  
  // View state
  const [showSidebar, setShowSidebar] = useState(true);
  const [showConsole, setShowConsole] = useState(true);
  const [showPreview, setShowPreview] = useState(true);
  const [showDiff, setShowDiff] = useState(false);
  const [showMockTemplates, setShowMockTemplates] = useState(false);
  const [consoleMessages, setConsoleMessages] = useState<ConsoleMessage[]>([]);
  const [propsJson, setPropsJson] = useState('{}');
  const [propsError, setPropsError] = useState<string | null>(null);
  const [previewKey, setPreviewKey] = useState(0);
  const [isFullscreen, setIsFullscreen] = useState(false);
  
  // Preview state
  const [previewHtml, setPreviewHtml] = useState<string>('');
  const [previewError, setPreviewError] = useState<string | null>(null);
  const iframeRef = useRef<HTMLIFrameElement>(null);
  const previewTimeoutRef = useRef<NodeJS.Timeout | null>(null);

  // Version history for diff
  const [versionHistory, setVersionHistory] = useState<{ version: number; content: string; timestamp: string }[]>([]);
  const [selectedVersion, setSelectedVersion] = useState<number | null>(null);

  // Fetch artifacts list
  const fetchArtifacts = useCallback(async () => {
    try {
      setLoading(true);
      const params = new URLSearchParams();
      if (typeFilter) params.set('type', typeFilter);
      params.set('limit', '100');
      
      const res = await fetch(`/api/dark-factory/artifacts?${params}`);
      if (!res.ok) throw new Error('Failed to fetch artifacts');
      
      const data = await res.json();
      setArtifacts(data.artifacts);
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to load artifacts');
    } finally {
      setLoading(false);
    }
  }, [typeFilter]);

  // Fetch single artifact
  const fetchArtifact = useCallback(async (id: string) => {
    try {
      setLoadingArtifact(true);
      setPreviewError(null);
      setShowDiff(false);
      setSelectedVersion(null);
      
      const res = await fetch(`/api/dark-factory/artifacts/${id}`);
      if (!res.ok) throw new Error('Failed to fetch artifact');
      
      const data = await res.json();
      setSelectedArtifact(data);
      setEditedCode(data.content);
      setHasChanges(false);
      
      // Build mock version history
      const history = [];
      for (let v = data.version; v >= 1; v--) {
        history.push({
          version: v,
          content: v === data.version ? data.content : `// Version ${v} - Previous version content\n${data.content.slice(0, 200)}...`,
          timestamp: new Date(new Date(data.createdAt).getTime() - (data.version - v) * 3600000).toISOString()
        });
      }
      setVersionHistory(history);
      
      // Update URL without navigation
      router.push(`/ghost-control/dark-factory/sandbox?artifact=${id}`, { scroll: false });
      
      // Log to console
      addConsoleMessage('info', `Loaded artifact: ${data.path}`);
      
      // Generate preview if it's a UI component
      if (data.type === 'ui_component' || data.type === 'page') {
        generatePreview(data.content);
      }
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to load artifact');
    } finally {
      setLoadingArtifact(false);
    }
  }, [router]);

  // Add console message
  const addConsoleMessage = (type: ConsoleMessage['type'], message: string) => {
    setConsoleMessages(prev => [...prev, { type, message, timestamp: new Date() }]);
  };

  // Analyze component complexity
  // Check for truly unsupported patterns (very minimal now - most things should try to render)
  const isComplexComponent = (code: string): boolean => {
    // Only block components that definitely won't work:
    // 1. Server components with 'use server' actions
    const hasServerActions = code.includes("'use server'") || code.includes('"use server"');
    // 2. Dynamic imports
    const hasDynamicImports = code.includes('import(') || code.includes('dynamic(');
    // 3. Next.js specific server features
    const hasServerFeatures = code.includes('cookies()') || code.includes('headers()');
    
    return hasServerActions || hasDynamicImports || hasServerFeatures;
  };

  // Generate preview HTML for component
  const generatePreview = useCallback((code: string) => {
    try {
      // Check if component is too complex for in-browser preview
      if (isComplexComponent(code)) {
        setPreviewError('This component uses advanced features (async operations, multiple sub-components, or complex hooks) that require a full build environment. The code is displayed on the left for review.');
        addConsoleMessage('warn', 'Complex component detected - preview requires full build environment');
        return;
      }

      // Parse props
      let props = {};
      try {
        props = JSON.parse(propsJson);
        setPropsError(null);
      } catch (e) {
        setPropsError('Invalid JSON in props');
        return;
      }

      // Pre-process code: strip imports, TypeScript syntax, and directives
      const preprocessCode = (sourceCode: string): string => {
        let code = sourceCode;
        
        // Strip 'use client' / 'use server' directives
        code = code.replace(/['"]use (client|server)['"];?\s*\n/g, '');
        
        // Strip import statements (handle multi-line by removing complete import statements)
        // Match import ... from '...' or import '...'
        code = code.replace(/import\s*\{[^}]*\}\s*from\s*['"][^'"]+['"];?/g, '');
        code = code.replace(/import\s+\w+\s*,?\s*\{[^}]*\}\s*from\s*['"][^'"]+['"];?/g, '');
        code = code.replace(/import\s+\*\s+as\s+\w+\s+from\s*['"][^'"]+['"];?/g, '');
        code = code.replace(/import\s+\w+\s+from\s*['"][^'"]+['"];?/g, '');
        code = code.replace(/import\s*['"][^'"]+['"];?/g, '');
        
        // Remove interface blocks (simple approach - entire line starting with interface until closing })
        code = code.replace(/^(export\s+)?interface\s+\w+[^{]*\{[\s\S]*?\n\}/gm, '');
        
        // Remove simple type aliases
        code = code.replace(/^(export\s+)?type\s+\w+\s*=\s*[^;]+;/gm, '');
        
        // Remove React.FC<Props> type annotations
        code = code.replace(/:\s*React\.(FC|FunctionComponent|ComponentType)<[^>]+>\s*=/g, ' =');
        
        // Remove generic type parameters from hooks: useState<Type>() -> useState()
        code = code.replace(/(useState|useRef|useCallback|useMemo|useReducer|useContext|createContext)<[^>]+>\(/g, '$1(');
        
        // Remove type annotations ONLY from function/arrow parameter declarations
        // Be very conservative - only match common patterns like (x: string) or (x: number)
        // Avoid matching object properties like { key: value }
        
        // Match arrow function parameters: (param: Type) =>
        // Only when followed by =>
        code = code.replace(/\(([^)]+)\)\s*=>/g, (match, params) => {
          // Strip type annotations from each param
          // Match param: Type where Type can be complex but ends at , or )
          const cleanParams = params.replace(/(\w+)\s*:\s*[^,)]+/g, '$1');
          return '(' + cleanParams + ') =>';
        });
        
        // Remove return type annotations from arrow functions: ): Type =>
        code = code.replace(/\)\s*:\s*\w+[\w\[\]<>,\s|&]*\s*=>/g, ') =>');
        
        // Convert export default
        code = code.replace(/export\s+default\s+function\s+(\w+)/g, 'function $1');
        code = code.replace(/export\s+default\s+/g, 'const __ExportedComponent__ = ');
        
        // Strip other exports
        code = code.replace(/export\s+(const|let|var|function|class)\s+/g, '$1 ');
        
        return code;
      };

      const processedCode = preprocessCode(code);
      
      // Escape for embedding in HTML - use base64 to avoid ALL escaping issues
      const base64Code = Buffer.from(processedCode, 'utf-8').toString('base64');

      // Create a sandboxed HTML page with the component
      // Using Babel with TypeScript preset to handle all TS syntax
      const html = `
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
  <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"></script>
  <script src="https://cdn.tailwindcss.com"></script>
  <style>
    body { 
      background: #0C1222; 
      color: white; 
      font-family: system-ui, sans-serif;
      padding: 1rem;
      margin: 0;
    }
    .error-boundary {
      background: #450a0a;
      border: 1px solid #dc2626;
      padding: 1rem;
      border-radius: 8px;
      color: #fca5a5;
    }
    .error-boundary pre {
      white-space: pre-wrap;
      word-break: break-word;
      margin-top: 0.5rem;
      font-size: 12px;
    }
  </style>
</head>
<body>
  <div id="root"></div>
  <script>
    // Setup mocks and helpers before Babel compilation
    window.__SANDBOX_SETUP__ = function() {
      // Mock common Next.js imports
      window.Link = function Link(props) {
        return React.createElement('a', { href: props.href, className: props.className, style: props.style }, props.children);
      };
      
      window.Image = function NextImage(props) {
        const style = props.fill 
          ? { position: 'absolute', width: '100%', height: '100%', objectFit: 'cover', ...props.style }
          : props.style;
        return React.createElement('img', { 
          src: props.src, 
          alt: props.alt || '', 
          className: props.className,
          style: style,
          width: props.width,
          height: props.height
        });
      };
      
      // Mock framer-motion
      window.motion = new Proxy({}, {
        get: function(target, prop) {
          return function MotionComponent(props) {
            const { initial, animate, exit, transition, whileHover, whileTap, variants, ...rest } = props;
            return React.createElement(prop, rest);
          };
        }
      });
      window.AnimatePresence = function(props) { return props.children; };
      window.useInView = function() { return [null, true]; };
      
      // Mock Next.js hooks
      window.useRouter = function() { 
        return { push: function(){}, replace: function(){}, back: function(){}, pathname: '/' }; 
      };
      window.usePathname = function() { return '/'; };
      window.useSearchParams = function() { return new URLSearchParams(); };
      
      // Mock fetch API - returns success for sandbox testing
      var originalFetch = window.fetch;
      window.fetch = function(url, options) {
        console.log('[Sandbox] Mock fetch:', url);
        return Promise.resolve({
          ok: true,
          status: 200,
          json: function() { 
            return Promise.resolve({ success: true, data: {}, message: 'Mock response' }); 
          },
          text: function() { return Promise.resolve('Mock response'); }
        });
      };
      
      // Ensure localStorage works (it should in iframe, but add safety wrapper)
      if (!window.localStorage) {
        var store = {};
        window.localStorage = {
          getItem: function(key) { return store[key] || null; },
          setItem: function(key, value) { store[key] = String(value); },
          removeItem: function(key) { delete store[key]; },
          clear: function() { store = {}; }
        };
      }
      
      // Mock React hooks that might cause issues
      const originalUseEffect = React.useEffect;
      React.useEffect = function(fn, deps) {
        // Run effects immediately in sandbox for simpler components
        try { 
          const cleanup = fn(); 
          // Store cleanup function if returned (for component unmount)
          if (typeof cleanup === 'function') {
            window.__SANDBOX_CLEANUPS__ = window.__SANDBOX_CLEANUPS__ || [];
            window.__SANDBOX_CLEANUPS__.push(cleanup);
          }
        } catch(e) { 
          console.warn('[Sandbox] Effect error:', e.message); 
        }
      };
      
      // Mock lucide-react icons - create a factory
      window.__createIcon = function(name) {
        return function IconComponent(props) {
          const { className, size, ...rest } = props || {};
          const sizeVal = size || 24;
          return React.createElement('span', {
            className: className,
            style: { 
              display: 'inline-flex', 
              alignItems: 'center', 
              justifyContent: 'center',
              width: sizeVal,
              height: sizeVal,
              fontSize: Math.max(10, sizeVal - 8)
            },
            ...rest
          }, '[' + name + ']');
        };
      };
      
      // Define all common icons
      var iconNames = [
        'Ghost', 'ArrowRight', 'ArrowLeft', 'CheckCircle', 'XCircle', 'Loader2', 'Plus', 'Minus',
        'Search', 'Settings', 'User', 'Menu', 'X', 'ChevronRight', 'ChevronLeft', 'ChevronDown', 'ChevronUp',
        'Star', 'Heart', 'Mail', 'Phone', 'MapPin', 'Calendar', 'Clock', 'AlertTriangle', 'Info',
        'Edit', 'Trash2', 'Save', 'Download', 'Upload', 'File', 'Folder', 'Code', 'Database',
        'Zap', 'Layout', 'Box', 'Boxes', 'Brain', 'Sparkles', 'Activity', 'BarChart', 'PieChart',
        'TrendingUp', 'TrendingDown', 'DollarSign', 'CreditCard', 'Shield', 'Lock', 'Unlock',
        'Eye', 'EyeOff', 'Bell', 'MessageSquare', 'Send', 'Mic', 'Volume2', 'VolumeX', 'Volume1', 'Play', 'Pause',
        'History', 'Palette', 'Delete', 'Undo', 'Redo', 'RotateCw',
        'SkipForward', 'SkipBack', 'Maximize', 'Minimize', 'RefreshCw', 'RotateCcw', 'Copy',
        'Clipboard', 'ExternalLink', 'Link2', 'Unlink', 'Globe', 'Home', 'Building', 'Users',
        'UserPlus', 'UserMinus', 'UserCheck', 'LogIn', 'LogOut', 'Key', 'Hash', 'AtSign',
        'Percent', 'Tag', 'Bookmark', 'Flag', 'Award', 'Gift', 'Coffee', 'Sun', 'Moon', 'Cloud',
        'Wifi', 'WifiOff', 'Battery', 'BatteryCharging', 'Power', 'Cpu', 'HardDrive', 'Server',
        'Terminal', 'Monitor', 'Smartphone', 'Tablet', 'Laptop', 'Watch', 'Headphones', 'Speaker',
        'Camera', 'ImageIcon', 'Video', 'Film', 'Music', 'Radio', 'Tv', 'Cast', 'Airplay',
        'Printer', 'Scan', 'QrCode', 'Fingerprint', 'Share', 'Share2', 'Forward', 'Reply',
        'Archive', 'Inbox', 'Paperclip', 'FileText', 'FileImage', 'FileVideo', 'FileAudio',
        'FilePlus', 'FileMinus', 'FileCheck', 'FileX', 'FolderPlus', 'FolderMinus', 'FolderOpen',
        'HelpCircle', 'AlertCircle', 'CheckCircle2', 'XOctagon', 'AlertOctagon', 'Ban', 'Slash',
        'Circle', 'Square', 'Triangle', 'Pentagon', 'Hexagon', 'Octagon', 'Diamond', 'Crown',
        'Target', 'Crosshair', 'Compass', 'Navigation', 'Map', 'Milestone', 'Signpost',
        'Bot', 'Wand2', 'Workflow', 'GitBranch', 'GitCommit', 'GitMerge', 'GitPullRequest',
        'Package', 'Layers', 'Grid', 'List', 'Table', 'Columns', 'Rows', 'LayoutGrid',
        'LayoutList', 'LayoutDashboard', 'PanelLeft', 'PanelRight', 'SidebarOpen', 'SidebarClose',
        'Maximize2', 'Minimize2', 'Move', 'GripVertical', 'GripHorizontal', 'MoreHorizontal', 'MoreVertical'
      ];
      
      iconNames.forEach(function(name) {
        window[name] = window.__createIcon(name);
      });
      
      // Mock cn utility
      window.cn = function() {
        return Array.from(arguments).filter(Boolean).join(' ');
      };
    };
    
    // Intercept console methods
    var originalConsole = { log: console.log, error: console.error, warn: console.warn, info: console.info };
    ['log', 'error', 'warn', 'info'].forEach(function(method) {
      console[method] = function() {
        var args = Array.from(arguments);
        originalConsole[method].apply(console, args);
        window.parent.postMessage({ 
          type: 'console', 
          method: method, 
          message: args.map(function(a) { return typeof a === 'object' ? JSON.stringify(a) : String(a); }).join(' ')
        }, '*');
      };
    });

    // Error handler
    window.onerror = function(msg, url, line, col, error) {
      var errorMsg = msg;
      if (line && line > 0) {
        errorMsg += ' (line ' + line + ')';
      }
      if (error && error.stack) {
        console.error('Stack:', error.stack);
      }
      window.parent.postMessage({ type: 'error', message: errorMsg }, '*');
      return true;
    };
    
    // Unhandled promise rejection handler
    window.onunhandledrejection = function(event) {
      window.parent.postMessage({ type: 'error', message: 'Promise rejection: ' + (event.reason?.message || event.reason || 'Unknown') }, '*');
    };
    
    // Run setup
    window.__SANDBOX_SETUP__();
  </script>
  
  <script>
    // Store base64 code and props for Babel script to use
    window.__SANDBOX_CODE__ = '${base64Code}';
    window.__SANDBOX_PROPS__ = ${JSON.stringify(props)};
    
    // Error boundary class (plain JS - defined before Babel processes)
    window.ErrorBoundary = (function() {
      function ErrorBoundary(props) {
        this.props = props;
        this.state = { hasError: false, error: null };
      }
      ErrorBoundary.prototype = Object.create(React.Component.prototype);
      ErrorBoundary.prototype.constructor = ErrorBoundary;
      ErrorBoundary.getDerivedStateFromError = function(error) {
        return { hasError: true, error: error };
      };
      ErrorBoundary.prototype.componentDidCatch = function(error) {
        window.parent.postMessage({ type: 'error', message: error.message }, '*');
      };
      ErrorBoundary.prototype.render = function() {
        if (this.state.hasError) {
          return React.createElement('div', { className: 'error-boundary' },
            React.createElement('h3', { style: { margin: 0, marginBottom: '8px' } }, 'Component Error'),
            React.createElement('pre', null, this.state.error ? this.state.error.message : 'Unknown error')
          );
        }
        return this.props.children;
      };
      return ErrorBoundary;
    })();
  </script>
  
  <script>
    // Transform and execute user code with Babel 6
    (function() {
      try {
        var userCode = atob(window.__SANDBOX_CODE__);
        console.log('User code length:', userCode.length);
        
        // Transform with Babel 6 (uses es2015 and react presets)
        var compiledCode;
        try {
          var result = Babel.transform(userCode, {
            presets: ['es2015', 'es2016', 'es2017', 'stage-2', 'react']
          });
          compiledCode = result.code;
          console.log('Babel compilation successful');
        } catch (babelError) {
          var errorMsg = 'JSX compilation error: ' + (babelError.message || String(babelError));
          console.error('Babel error:', babelError);
          window.parent.postMessage({ type: 'error', message: errorMsg }, '*');
          document.getElementById('root').innerHTML = '<div class="error-boundary"><h3>Compilation Error</h3><pre>' + errorMsg + '</pre></div>';
          return;
        }
        
        // Execute the compiled code
        try {
          eval(compiledCode);
        } catch (execError) {
          var errorMsg = 'Runtime error: ' + (execError.message || execError);
          console.error('Runtime error:', execError);
          window.parent.postMessage({ type: 'error', message: errorMsg }, '*');
          document.getElementById('root').innerHTML = '<div class="error-boundary"><h3>Runtime Error</h3><pre>' + errorMsg + '</pre></div>';
          return;
        }
        
        // Find the exported component
        var ExportedComponent = null;
        if (typeof window.__ExportedComponent__ !== 'undefined') {
          ExportedComponent = window.__ExportedComponent__;
        } else {
          var possibleComponents = Object.keys(window).filter(function(key) {
            if (!/^[A-Z]/.test(key)) return false;
            return typeof window[key] === 'function';
          });
          if (possibleComponents.length > 0) {
            ExportedComponent = window[possibleComponents[possibleComponents.length - 1]];
          }
        }
        
        var componentProps = window.__SANDBOX_PROPS__;
        var rootElement = document.getElementById('root');
        
        if (rootElement && ExportedComponent) {
          var root = ReactDOM.createRoot(rootElement);
          root.render(
            React.createElement(window.ErrorBoundary, null,
              React.createElement(ExportedComponent, componentProps)
            )
          );
          window.parent.postMessage({ type: 'success', message: 'Component rendered successfully' }, '*');
        } else {
          rootElement.innerHTML = '<div class="error-boundary"><h3>No Component Found</h3></div>';
          window.parent.postMessage({ type: 'error', message: 'No exportable component found' }, '*');
        }
        
      } catch (e) {
        var errorMsg = 'Sandbox error: ' + (e.message || e);
        console.error(errorMsg, e);
        window.parent.postMessage({ type: 'error', message: errorMsg }, '*');
        document.getElementById('root').innerHTML = '<div class="error-boundary"><h3>Sandbox Error</h3><pre>' + errorMsg + '</pre></div>';
      }
    })();
  </script>
</body>
</html>
`;

      setPreviewHtml(html);
      setPreviewError(null);
      setPreviewKey(prev => prev + 1);
      addConsoleMessage('info', 'Preview generated');
    } catch (err) {
      setPreviewError(err instanceof Error ? err.message : 'Failed to generate preview');
      addConsoleMessage('error', `Preview error: ${err instanceof Error ? err.message : 'Unknown error'}`);
    }
  }, [propsJson]);

  // Listen for messages from iframe
  useEffect(() => {
    const handleMessage = (event: MessageEvent) => {
      if (event.data?.type === 'console') {
        addConsoleMessage(event.data.method, event.data.message);
      } else if (event.data?.type === 'error') {
        addConsoleMessage('error', event.data.message);
      } else if (event.data?.type === 'success') {
        addConsoleMessage('info', event.data.message);
      }
    };
    
    window.addEventListener('message', handleMessage);
    return () => window.removeEventListener('message', handleMessage);
  }, []);

  // Initial load
  useEffect(() => {
    fetchArtifacts();
  }, [fetchArtifacts]);

  // Load artifact from URL
  useEffect(() => {
    if (artifactIdFromUrl && !selectedArtifact) {
      fetchArtifact(artifactIdFromUrl);
    }
  }, [artifactIdFromUrl, selectedArtifact, fetchArtifact]);

  // Hot reload: debounced preview update on code change
  useEffect(() => {
    if (!autoPreview || !selectedArtifact) return;
    if (selectedArtifact.type !== 'ui_component' && selectedArtifact.type !== 'page') return;
    
    if (previewTimeoutRef.current) {
      clearTimeout(previewTimeoutRef.current);
    }
    
    previewTimeoutRef.current = setTimeout(() => {
      if (editedCode !== selectedArtifact.content || hasChanges) {
        generatePreview(editedCode);
      }
    }, 800); // 800ms debounce
    
    return () => {
      if (previewTimeoutRef.current) {
        clearTimeout(previewTimeoutRef.current);
      }
    };
  }, [editedCode, autoPreview, selectedArtifact, generatePreview, hasChanges]);

  // Filter artifacts
  const filteredArtifacts = artifacts.filter(a => {
    if (searchQuery) {
      const query = searchQuery.toLowerCase();
      return a.path.toLowerCase().includes(query) || 
             a.task.prompt.toLowerCase().includes(query) ||
             a.task.project?.name.toLowerCase().includes(query);
    }
    return true;
  });

  // Copy to clipboard
  const copyToClipboard = (text: string) => {
    navigator.clipboard.writeText(text);
    addConsoleMessage('info', 'Copied to clipboard');
  };

  // Handle code change
  const handleCodeChange = (value: string | undefined) => {
    if (value !== undefined) {
      setEditedCode(value);
      setHasChanges(value !== selectedArtifact?.content);
    }
  };

  // Reset code to original
  const resetCode = () => {
    if (selectedArtifact) {
      setEditedCode(selectedArtifact.content);
      setHasChanges(false);
      addConsoleMessage('info', 'Code reset to original');
    }
  };

  // Apply mock template
  const applyMockTemplate = (template: MockTemplate) => {
    setPropsJson(JSON.stringify(template.data, null, 2));
    setShowMockTemplates(false);
    addConsoleMessage('info', `Applied mock template: ${template.name}`);
    if (autoPreview && selectedArtifact && (selectedArtifact.type === 'ui_component' || selectedArtifact.type === 'page')) {
      setTimeout(() => generatePreview(editedCode), 100);
    }
  };

  // Generate simple diff
  const generateDiff = useMemo(() => {
    if (!selectedVersion || !selectedArtifact) return null;
    const versionContent = versionHistory.find(v => v.version === selectedVersion)?.content || '';
    const currentLines = editedCode.split('\n');
    const versionLines = versionContent.split('\n');
    const maxLines = Math.max(currentLines.length, versionLines.length);
    
    const diff: { type: 'same' | 'added' | 'removed' | 'modified'; line: number; current: string; version: string }[] = [];
    
    for (let i = 0; i < maxLines; i++) {
      const current = currentLines[i] || '';
      const version = versionLines[i] || '';
      
      if (current === version) {
        diff.push({ type: 'same', line: i + 1, current, version });
      } else if (!version) {
        diff.push({ type: 'added', line: i + 1, current, version });
      } else if (!current) {
        diff.push({ type: 'removed', line: i + 1, current, version });
      } else {
        diff.push({ type: 'modified', line: i + 1, current, version });
      }
    }
    
    return diff.filter(d => d.type !== 'same');
  }, [selectedVersion, editedCode, versionHistory, selectedArtifact]);

  // Manual refresh preview
  const refreshPreview = () => {
    if (selectedArtifact && (selectedArtifact.type === 'ui_component' || selectedArtifact.type === 'page')) {
      generatePreview(editedCode);
    }
  };

  // Get file extension for Monaco language
  const getMonacoLanguage = (path: string, type: string): string => {
    if (path.endsWith('.tsx') || path.endsWith('.ts')) return 'typescript';
    if (path.endsWith('.jsx') || path.endsWith('.js')) return 'javascript';
    if (path.endsWith('.css')) return 'css';
    if (path.endsWith('.json')) return 'json';
    if (path.endsWith('.prisma')) return 'prisma';
    if (type === 'prisma_model') return 'prisma';
    return 'typescript';
  };

  return (
    <div className="h-screen bg-brand-bg flex flex-col overflow-hidden">
      {/* Header */}
      <header className="flex-shrink-0 border-b border-white/10 bg-black/30 backdrop-blur-xl z-50">
        <div className="px-4 py-3 flex items-center justify-between">
          <div className="flex items-center gap-4">
            <Link href="/ghost-control/dark-factory" className="flex items-center gap-2 text-gray-400 hover:text-white transition-colors" prefetch={false}>
              <ArrowLeft className="w-5 h-5" />
              <span className="hidden sm:inline">Back to {VOCAB.factory}</span>
            </Link>
            <div className="h-6 w-px bg-white/20" />
            <div className="flex items-center gap-2">
              <Ghost className="w-6 h-6 text-brand" />
              <h1 className="text-lg font-semibold text-white">Component Sandbox</h1>
              <span className="px-2 py-0.5 text-xs bg-brand-deep/20 text-brand rounded-full">v2</span>
            </div>
          </div>
          
          <div className="flex items-center gap-2">
            {/* Hot Reload Toggle */}
            <button
              onClick={() => setAutoPreview(!autoPreview)}
              className={`flex items-center gap-1 px-2 py-1 rounded-lg text-xs transition-colors ${
                autoPreview ? 'bg-green-500/20 text-green-400' : 'bg-gray-500/20 text-gray-400'
              }`}
              title={autoPreview ? 'Hot reload enabled' : 'Hot reload disabled'}
            >
              <Zap className="w-3 h-3" />
              <span className="hidden sm:inline">Hot Reload</span>
            </button>
            
            <div className="h-4 w-px bg-white/20" />
            
            <button
              onClick={() => setShowSidebar(!showSidebar)}
              className={`p-2 rounded-lg transition-colors ${showSidebar ? 'bg-brand-deep/20 text-brand' : 'text-gray-400 hover:text-white'}`}
            >
              <FileCode className="w-5 h-5" />
            </button>
            <button
              onClick={() => setShowPreview(!showPreview)}
              className={`p-2 rounded-lg transition-colors ${showPreview ? 'bg-brand-secondary/20 text-brand-secondary-light' : 'text-gray-400 hover:text-white'}`}
            >
              {showPreview ? <Eye className="w-5 h-5" /> : <EyeOff className="w-5 h-5" />}
            </button>
            <button
              onClick={() => setShowConsole(!showConsole)}
              className={`p-2 rounded-lg transition-colors ${showConsole ? 'bg-green-500/20 text-green-400' : 'text-gray-400 hover:text-white'}`}
            >
              <Terminal className="w-5 h-5" />
            </button>
            <button
              onClick={() => setShowDiff(!showDiff)}
              className={`p-2 rounded-lg transition-colors ${showDiff ? 'bg-orange-500/20 text-orange-400' : 'text-gray-400 hover:text-white'}`}
              title="Visual Diff"
            >
              <GitCompare className="w-5 h-5" />
            </button>
          </div>
        </div>
      </header>

      {/* Main content */}
      <div className="flex-1 flex overflow-hidden">
        {/* Sidebar - Artifact list */}
        <AnimatePresence>
          {showSidebar && (
            <motion.aside
              initial={{ width: 0, opacity: 0 }}
              animate={{ width: 320, opacity: 1 }}
              exit={{ width: 0, opacity: 0 }}
              className="border-r border-white/10 bg-black/20 flex flex-col overflow-hidden"
            >
              {/* Search & Filter */}
              <div className="p-3 border-b border-white/10 space-y-2">
                <div className="relative">
                  <Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-500" />
                  <input
                    type="text"
                    placeholder="Search artifacts..."
                    value={searchQuery}
                    onChange={e => setSearchQuery(e.target.value)}
                    className="w-full pl-9 pr-3 py-2 bg-white/5 border border-white/10 rounded-lg text-sm text-white placeholder-gray-500 focus:outline-none focus:border-brand-deep/50"
                  />
                </div>
                <select
                  value={typeFilter}
                  onChange={e => setTypeFilter(e.target.value)}
                  className="w-full px-3 py-2 bg-white/5 border border-white/10 rounded-lg text-sm text-white focus:outline-none focus:border-brand-deep/50"
                >
                  <option value="">All Types</option>
                  <option value="ui_component">UI Components</option>
                  <option value="page">Pages</option>
                  <option value="api_route">API Routes</option>
                  <option value="prisma_model">Database Models</option>
                  <option value="type">Types</option>
                  <option value="util">Utilities</option>
                </select>
              </div>
              
              {/* Artifact list */}
              <div className="flex-1 overflow-y-auto">
                {loading ? (
                  <div className="flex items-center justify-center py-8">
                    <RefreshCw className="w-6 h-6 text-brand animate-spin" />
                  </div>
                ) : filteredArtifacts.length === 0 ? (
                  <div className="text-center py-8 text-gray-500">
                    <Code className="w-8 h-8 mx-auto mb-2 opacity-50" />
                    <p>No artifacts found</p>
                  </div>
                ) : (
                  <div className="p-2 space-y-1">
                    {filteredArtifacts.map(artifact => (
                      <button
                        key={artifact.id}
                        onClick={() => fetchArtifact(artifact.id)}
                        className={`w-full text-left p-3 rounded-lg transition-all ${
                          selectedArtifact?.id === artifact.id
                            ? 'bg-brand-deep/20 border border-brand-deep/50'
                            : 'hover:bg-white/5 border border-transparent'
                        }`}
                      >
                        <div className="flex items-start gap-2">
                          <span className={`p-1.5 rounded ${TYPE_COLORS[artifact.type] || 'text-gray-400 bg-gray-500/20'}`}>
                            {TYPE_ICONS[artifact.type] || <Code className="w-4 h-4" />}
                          </span>
                          <div className="flex-1 min-w-0">
                            <p className="text-sm font-medium text-white truncate">
                              {artifact.path.split('/').pop()}
                            </p>
                            <p className="text-xs text-gray-500 truncate">{artifact.path}</p>
                            {artifact.task.project && (
                              <p className="text-xs text-brand mt-1">{artifact.task.project.name}</p>
                            )}
                          </div>
                        </div>
                      </button>
                    ))}
                  </div>
                )}
              </div>
            </motion.aside>
          )}
        </AnimatePresence>

        {/* Main panel */}
        <div className="flex-1 flex flex-col overflow-hidden min-h-0">
          {selectedArtifact ? (
            <>
              {/* Artifact info bar */}
              <div className="px-4 py-2 border-b border-white/10 bg-black/20 flex items-center justify-between">
                <div className="flex items-center gap-3">
                  <span className={`px-2 py-1 rounded text-xs font-medium ${TYPE_COLORS[selectedArtifact.type] || 'text-gray-400 bg-gray-500/20'}`}>
                    {selectedArtifact.type.replace('_', ' ')}
                  </span>
                  <span className="text-sm text-white font-mono">{selectedArtifact.path}</span>
                  <span className="text-xs text-gray-500">v{selectedArtifact.version}</span>
                  {selectedArtifact.deployed && (
                    <span className="text-xs text-green-400 bg-green-500/20 px-2 py-0.5 rounded">Deployed</span>
                  )}
                  {hasChanges && (
                    <span className="text-xs text-orange-400 bg-orange-500/20 px-2 py-0.5 rounded flex items-center gap-1">
                      <span className="w-1.5 h-1.5 bg-orange-400 rounded-full animate-pulse" />
                      Modified
                    </span>
                  )}
                </div>
                <div className="flex items-center gap-2">
                  {hasChanges && (
                    <button
                      onClick={resetCode}
                      className="flex items-center gap-1 p-2 text-gray-400 hover:text-white transition-colors"
                      title="Reset to original"
                    >
                      <RotateCcw className="w-4 h-4" />
                    </button>
                  )}
                  <button
                    onClick={() => copyToClipboard(editedCode)}
                    className="p-2 text-gray-400 hover:text-white transition-colors"
                    title="Copy code"
                  >
                    <Copy className="w-4 h-4" />
                  </button>
                  {(selectedArtifact.type === 'ui_component' || selectedArtifact.type === 'page') && (
                    <button
                      onClick={refreshPreview}
                      className="p-2 text-gray-400 hover:text-white transition-colors"
                      title="Refresh preview"
                    >
                      <RefreshCw className="w-4 h-4" />
                    </button>
                  )}
                </div>
              </div>

              {/* Code & Preview split */}
              <div className="flex-1 flex overflow-hidden min-h-0">
                {/* Code view with Monaco */}
                <div className={`${showPreview && (selectedArtifact.type === 'ui_component' || selectedArtifact.type === 'page') ? 'w-1/2' : 'w-full'} h-full overflow-hidden flex flex-col border-r border-white/10`}>
                  <div className="flex-1 min-h-0 overflow-hidden">
                    <MonacoEditor
                      height="100%"
                      language={getMonacoLanguage(selectedArtifact.path, selectedArtifact.type)}
                      value={editedCode}
                      onChange={handleCodeChange}
                      theme="vs-dark"
                      options={{
                        minimap: { enabled: false },
                        fontSize: 13,
                        lineNumbers: 'on',
                        scrollBeyondLastLine: false,
                        wordWrap: 'on',
                        automaticLayout: true,
                        tabSize: 2,
                        folding: true,
                        renderLineHighlight: 'line',
                        padding: { top: 16, bottom: 16 },
                      }}
                    />
                  </div>
                </div>

                {/* Preview pane */}
                {showPreview && (selectedArtifact.type === 'ui_component' || selectedArtifact.type === 'page') && (
                  <div className="w-1/2 h-full flex flex-col overflow-hidden">
                    {/* Props editor with templates */}
                    <div className="p-3 border-b border-white/10 bg-black/30 flex-shrink-0">
                      <div className="flex items-center justify-between mb-2">
                        <div className="flex items-center gap-2">
                          <span className="text-xs font-medium text-gray-400">Props (JSON)</span>
                          <button
                            onClick={() => setShowMockTemplates(!showMockTemplates)}
                            className="flex items-center gap-1 px-2 py-0.5 text-xs bg-brand-secondary/20 text-brand-secondary-light rounded hover:bg-brand-secondary/30 transition-colors"
                          >
                            <Wand2 className="w-3 h-3" />
                            Templates
                            <ChevronDown className={`w-3 h-3 transition-transform ${showMockTemplates ? 'rotate-180' : ''}`} />
                          </button>
                        </div>
                        <button
                          onClick={refreshPreview}
                          className="flex items-center gap-1 px-2 py-1 text-xs bg-brand-deep/20 text-brand rounded hover:bg-brand-deep/30 transition-colors"
                        >
                          <Play className="w-3 h-3" />
                          Run
                        </button>
                      </div>
                      
                      {/* Mock templates dropdown */}
                      <AnimatePresence>
                        {showMockTemplates && (
                          <motion.div
                            initial={{ height: 0, opacity: 0 }}
                            animate={{ height: 'auto', opacity: 1 }}
                            exit={{ height: 0, opacity: 0 }}
                            className="mb-2 overflow-hidden"
                          >
                            <div className="flex flex-wrap gap-1">
                              {MOCK_TEMPLATES.map(template => (
                                <button
                                  key={template.name}
                                  onClick={() => applyMockTemplate(template)}
                                  className="flex items-center gap-1 px-2 py-1 text-xs bg-white/5 text-gray-300 rounded hover:bg-white/10 transition-colors"
                                >
                                  {template.icon}
                                  {template.name}
                                </button>
                              ))}
                            </div>
                          </motion.div>
                        )}
                      </AnimatePresence>
                      
                      <textarea
                        value={propsJson}
                        onChange={e => setPropsJson(e.target.value)}
                        className={`w-full px-3 py-2 bg-black/50 border rounded-lg text-xs font-mono text-white resize-none focus:outline-none ${
                          propsError ? 'border-red-500/50' : 'border-white/10 focus:border-brand-deep/50'
                        }`}
                        rows={3}
                        placeholder='{"prop1": "value1"}'
                      />
                      {propsError && <p className="text-xs text-red-400 mt-1">{propsError}</p>}
                    </div>
                    
                    {/* Preview iframe */}
                    <div className="flex-1 min-h-[200px] relative bg-brand-bg">
                      {previewError ? (
                        <div className="absolute inset-0 flex items-center justify-center">
                          <div className="text-center p-8">
                            <AlertTriangle className="w-12 h-12 text-red-400 mx-auto mb-4" />
                            <p className="text-red-400 text-sm">{previewError}</p>
                          </div>
                        </div>
                      ) : previewHtml ? (
                        <iframe
                          key={previewKey}
                          ref={iframeRef}
                          srcDoc={previewHtml}
                          className="w-full h-full border-0"
                          sandbox="allow-scripts allow-same-origin"
                          title="Component Preview"
                        />
                      ) : (
                        <div className="absolute inset-0 flex items-center justify-center">
                          <div className="text-center text-gray-500">
                            <Eye className="w-12 h-12 mx-auto mb-4 opacity-50" />
                            <p>Click "Run" to preview component</p>
                            <p className="text-xs mt-2">Or enable Hot Reload for auto-preview</p>
                          </div>
                        </div>
                      )}
                    </div>
                  </div>
                )}
              </div>
            </>
          ) : (
            <div className="flex-1 flex items-center justify-center">
              <div className="text-center">
                <Ghost className="w-16 h-16 text-brand/30 mx-auto mb-4" />
                <h2 className="text-xl font-semibold text-white mb-2">Select an Artifact</h2>
                <p className="text-gray-500">Choose a component from the sidebar to preview</p>
              </div>
            </div>
          )}

          {/* Visual Diff Panel */}
          <AnimatePresence>
            {showDiff && selectedArtifact && (
              <motion.div
                initial={{ height: 0 }}
                animate={{ height: 250 }}
                exit={{ height: 0 }}
                className="border-t border-white/10 bg-black/40 overflow-hidden flex flex-col"
              >
                <div className="px-4 py-2 border-b border-white/10 flex items-center justify-between">
                  <div className="flex items-center gap-2">
                    <GitCompare className="w-4 h-4 text-orange-400" />
                    <span className="text-sm font-medium text-white">Visual Diff</span>
                  </div>
                  <div className="flex items-center gap-2">
                    <span className="text-xs text-gray-400">Compare with:</span>
                    <select
                      value={selectedVersion || ''}
                      onChange={e => setSelectedVersion(e.target.value ? Number(e.target.value) : null)}
                      className="px-2 py-1 text-xs bg-white/5 border border-white/10 rounded text-white focus:outline-none"
                    >
                      <option value="">Select version</option>
                      {versionHistory.filter(v => v.version !== selectedArtifact.version).map(v => (
                        <option key={v.version} value={v.version}>
                          v{v.version} - {new Date(v.timestamp).toLocaleString()}
                        </option>
                      ))}
                    </select>
                  </div>
                </div>
                <div className="flex-1 overflow-y-auto p-2 font-mono text-xs">
                  {!selectedVersion ? (
                    <div className="text-gray-500 text-center py-4">
                      <History className="w-6 h-6 mx-auto mb-2 opacity-50" />
                      Select a version to compare
                    </div>
                  ) : generateDiff && generateDiff.length === 0 ? (
                    <div className="text-green-400 text-center py-4">
                      <CheckCircle className="w-6 h-6 mx-auto mb-2" />
                      No differences found
                    </div>
                  ) : (
                    <div className="space-y-1">
                      {generateDiff?.map((d, i) => (
                        <div
                          key={i}
                          className={`px-2 py-1 rounded flex items-start gap-2 ${
                            d.type === 'added' ? 'bg-green-500/10 text-green-400' :
                            d.type === 'removed' ? 'bg-red-500/10 text-red-400' :
                            'bg-yellow-500/10 text-yellow-400'
                          }`}
                        >
                          <span className="text-gray-500 w-8 text-right">{d.line}</span>
                          <span className="w-4">
                            {d.type === 'added' ? '+' : d.type === 'removed' ? '-' : '~'}
                          </span>
                          <span className="flex-1 truncate">
                            {d.type === 'removed' ? d.version : d.current}
                          </span>
                        </div>
                      ))}
                    </div>
                  )}
                </div>
              </motion.div>
            )}
          </AnimatePresence>

          {/* Console */}
          <AnimatePresence>
            {showConsole && (
              <motion.div
                initial={{ height: 0 }}
                animate={{ height: 180 }}
                exit={{ height: 0 }}
                className="border-t border-white/10 bg-black/40 overflow-hidden flex flex-col"
              >
                <div className="px-4 py-2 border-b border-white/10 flex items-center justify-between">
                  <div className="flex items-center gap-2">
                    <Terminal className="w-4 h-4 text-green-400" />
                    <span className="text-sm font-medium text-white">Console</span>
                    <span className="text-xs text-gray-500">({consoleMessages.length})</span>
                  </div>
                  <button
                    onClick={() => setConsoleMessages([])}
                    className="text-xs text-gray-400 hover:text-white transition-colors"
                  >
                    Clear
                  </button>
                </div>
                <div className="flex-1 overflow-y-auto p-2 font-mono text-xs space-y-1">
                  {consoleMessages.length === 0 ? (
                    <div className="text-gray-500 text-center py-4">No console output</div>
                  ) : (
                    consoleMessages.map((msg, i) => (
                      <div
                        key={i}
                        className={`px-2 py-1 rounded ${
                          msg.type === 'error' ? 'bg-red-500/10 text-red-400' :
                          msg.type === 'warn' ? 'bg-yellow-500/10 text-yellow-400' :
                          msg.type === 'info' ? 'bg-blue-500/10 text-blue-400' :
                          'bg-white/5 text-gray-300'
                        }`}
                      >
                        <span className="text-gray-500">[{msg.timestamp.toLocaleTimeString()}]</span>{' '}
                        <span className="uppercase text-xs opacity-60">{msg.type}</span>{' '}
                        {msg.message}
                      </div>
                    ))
                  )}
                </div>
              </motion.div>
            )}
          </AnimatePresence>
        </div>
      </div>
    </div>
  );
}

export default function SandboxPage() {
  return (
    <Suspense fallback={
      <div className="min-h-screen bg-brand-bg flex items-center justify-center">
        <RefreshCw className="w-8 h-8 text-brand animate-spin" />
      </div>
    }>
      <SandboxContent />
    </Suspense>
  );
}
