import { useMemo, useCallback, useRef, useEffect, useState } from 'react';
import { useEditorStore } from '../../store/editorStore';
import { useProjectStore } from '../../store/projectStore';
import { useCollaborationStore, Collaborator } from '../../store/collaborationStore';
import { useProjectSocket } from '../../hooks/useWebSocket';
import { useParams } from 'react-router-dom';
import { getBlocksForFramework } from '../../blocks/registry';
import { compileWeb } from '../../compilers/web';
import { compileElectron } from '../../compilers/electron';
import { compileMaui } from '../../compilers/maui';
import { compileNodeJS } from '../../compilers/nodejs';
import { SyntaxHighlight } from './SyntaxHighlight';
import {
  Download, Copy, FileCode,
  Eye, Code2, SplitSquareHorizontal
} from 'lucide-react';
import { saveAs } from 'file-saver';
import JSZip from 'jszip';
import { getColor } from '../Collaboration/CollaboratorAvatars';

export default function CodeView() {
  const { id } = useParams<{ id: string }>();
  const { currentProject } = useProjectStore();
  const { activeFileId, fileTree, viewMode, setViewMode, visualElements, activeFileContent, setActiveFileContent } = useEditorStore();
  const collaborators = useCollaborationStore((s) => s.collaborators);
  const { emitCursorMove, emitFileChanged } = useProjectSocket(id);
  const editorRef = useRef<HTMLDivElement>(null);
  const [isEditing, setIsEditing] = useState(false);

  const compiledCode = useMemo(() => {
    if (!currentProject) return '';
    if (isEditing) return activeFileContent;

    const activeFile = fileTree.find(f => f.id === activeFileId);
    const blocks = getBlocksForFramework(currentProject.framework);
    const compilerOptions = {
      blocks, fileTree, visualElements, activeFile,
      projectName: currentProject.name,
    };

    switch (currentProject.framework) {
      case 'web': return compileWeb(compilerOptions);
      case 'electron': return compileElectron(compilerOptions);
      case 'maui': return compileMaui(compilerOptions);
      case 'nodejs': return compileNodeJS(compilerOptions);
      default: return '// Select a framework to generate code';
    }
  }, [currentProject, activeFileId, fileTree, visualElements, isEditing, activeFileContent]);

  const collaboratorCursors = useMemo(() => {
    if (!activeFileId) return [];
    return collaborators.filter((c) => c.activeFileId === activeFileId && c.cursor && c.cursor.line != null);
  }, [collaborators, activeFileId]);

  const lines = useMemo(() => compiledCode.split('\n'), [compiledCode]);

  const handleEditorClick = useCallback((e: React.MouseEvent) => {
    const rect = editorRef.current?.getBoundingClientRect();
    if (!rect) return;
    const lineHeight = 20;
    const line = Math.floor((e.clientY - rect.top + editorRef.current!.scrollTop) / lineHeight);
    const ch = Math.min(0, 0);
    if (activeFileId) {
      emitCursorMove(activeFileId, { line: Math.max(0, line), ch });
    }
  }, [activeFileId, emitCursorMove]);

  const fileChangeTimer = useRef<number>();
  const cursorThrottle = useRef<number>();
  const handleTextChange = useCallback((e: React.ChangeEvent<HTMLTextAreaElement>) => {
    const content = e.target.value;
    setActiveFileContent(content);
    // Debounce file_changed to 300ms to avoid flooding when typing
    if (activeFileId) {
      clearTimeout(fileChangeTimer.current);
      fileChangeTimer.current = window.setTimeout(() => {
        emitFileChanged(activeFileId, content);
      }, 300);
    }
    // Track cursor position
    const textarea = e.target;
    const pos = textarea.selectionStart;
    const before = content.substring(0, pos);
    const line = before.split('\n').length - 1;
    const ch = before.length - before.lastIndexOf('\n') - 1;
    clearTimeout(cursorThrottle.current);
    cursorThrottle.current = window.setTimeout(() => {
      if (activeFileId) emitCursorMove(activeFileId, { line, ch });
    }, 100);
  }, [activeFileId, emitCursorMove, emitFileChanged, setActiveFileContent]);

  const handleDownload = useCallback(async () => {
    if (!currentProject) return;
    const zip = new JSZip();
    const addFilesToZip = (files: any[], currentPath: string = '') => {
      for (const file of files) {
        if (file.type === 'folder') {
          if (file.children) addFilesToZip(file.children, currentPath + file.name + '/');
        } else {
          zip.file(currentPath + file.name, file.content || '');
        }
      }
    };
    addFilesToZip(fileTree);
    const blob = await zip.generateAsync({ type: 'blob' });
    saveAs(blob, `${currentProject.name}.zip`);
  }, [currentProject, fileTree]);

  const handleCopy = useCallback(() => {
    navigator.clipboard.writeText(compiledCode);
  }, [compiledCode]);

  const scriptFileName = useMemo(() => {
    const scriptFile = fileTree.find(f => f.type === 'js' || f.type === 'typescript');
    return scriptFile?.name || fileTree.find(f => f.id === activeFileId)?.name || 'output';
  }, [fileTree, activeFileId]);

  return (
    <div className="flex flex-col h-full">
      {/* Code Toolbar */}
      <div className="h-10 glass border-b border-surface-700 flex items-center justify-between px-4">
        <div className="flex items-center gap-2">
          <FileCode className="w-4 h-4 text-primary-400" />
          <span className="text-sm font-medium text-white">{scriptFileName}</span>
          <span className="badge-web">{currentProject?.framework || 'web'}</span>
        </div>
        <div className="flex items-center gap-2">
          {!isEditing && (
            <div className="flex bg-surface-800 rounded-lg p-0.5">
              <button onClick={() => setViewMode('design')}
                className={`px-2 py-1 rounded-md text-xs ${viewMode === 'design' ? 'bg-primary-600 text-white' : 'text-surface-400'}`}>
                <Code2 className="w-3.5 h-3.5" />
              </button>
              <button onClick={() => setViewMode('split')}
                className={`px-2 py-1 rounded-md text-xs ${viewMode === 'split' ? 'bg-primary-600 text-white' : 'text-surface-400'}`}>
                <SplitSquareHorizontal className="w-3.5 h-3.5" />
              </button>
            </div>
          )}
          <button onClick={() => setIsEditing(!isEditing)}
            className={`btn-ghost px-2 py-1 text-xs ${isEditing ? 'text-primary-400 bg-primary-500/10' : ''}`}
            title={isEditing ? 'View compiled code' : 'Edit source directly'}>
            <Code2 className="w-3.5 h-3.5" />
            {isEditing ? 'Compiled' : 'Edit'}
          </button>
          <div className="w-px h-4 bg-surface-700" />
          <button onClick={handleCopy} className="btn-ghost p-1.5" title="Copy to clipboard">
            <Copy className="w-3.5 h-3.5" />
          </button>
          <button onClick={handleDownload} className="btn-ghost p-1.5" title="Download project as ZIP">
            <Download className="w-3.5 h-3.5" />
          </button>
        </div>
      </div>

      {/* Code Content */}
      <div className="flex-1 overflow-auto">
        {isEditing ? (
          <div className="relative h-full">
            <textarea
              value={activeFileContent}
              onChange={handleTextChange}
              className="w-full h-full bg-transparent text-transparent caret-white resize-none font-mono text-sm leading-5 p-4 absolute inset-0 z-10 outline-none"
              spellCheck={false}
            />
            <div className="pointer-events-none p-4">
              <SyntaxHighlight code={activeFileContent} language={getLanguage(currentProject?.framework || 'web', fileTree.find(f => f.id === activeFileId)?.type)} />
            </div>
            {collaboratorCursors.length > 0 && (
              <div className="absolute inset-0 pointer-events-none z-20">
                {collaboratorCursors.map((c) => (
                  <div
                    key={c.userId}
                    className="absolute left-0 w-0.5 h-5"
                    style={{
                      top: `${c.cursor!.line * 20 + 16}px`,
                      backgroundColor: getColor(c.userId),
                    }}
                  >
                    <span
                      className="absolute left-0.5 -top-4 text-[9px] px-1 py-0.5 rounded-r whitespace-nowrap text-white font-bold"
                      style={{ backgroundColor: getColor(c.userId) }}
                    >
                      {c.username}
                    </span>
                  </div>
                ))}
              </div>
            )}
          </div>
        ) : (
          <div ref={editorRef} onClick={handleEditorClick} className="relative">
            {compiledCode ? (
              <>
                <SyntaxHighlight code={compiledCode} language={getLanguage(currentProject?.framework || 'web', fileTree.find(f => f.id === activeFileId)?.type)} />
                {collaboratorCursors.length > 0 && (
                  <div className="absolute inset-0 pointer-events-none top-0 left-0">
                    {collaboratorCursors.map((c) => (
                      <div
                        key={c.userId}
                        className="absolute left-0 w-0.5 h-5"
                        style={{
                          top: `${c.cursor!.line * 20 + 16}px`,
                          backgroundColor: getColor(c.userId),
                        }}
                      >
                        <span
                          className="absolute left-0.5 -top-4 text-[9px] px-1 py-0.5 rounded-r whitespace-nowrap text-white font-bold"
                          style={{ backgroundColor: getColor(c.userId) }}
                        >
                          {c.username}
                        </span>
                      </div>
                    ))}
                  </div>
                )}
              </>
            ) : (
              <div className="flex items-center justify-center h-full text-surface-500 text-sm">
                <div className="text-center">
                  <Code2 className="w-12 h-12 mx-auto mb-3 opacity-30" />
                  <p>Add blocks to see generated code</p>
                </div>
              </div>
            )}
          </div>
        )}
      </div>
    </div>
  );
}

function getLanguage(framework: string, fileType?: string): string {
  if (fileType) {
    if (fileType === 'js' || fileType === 'javascript') return 'javascript';
    if (fileType === 'ts' || fileType === 'typescript') return 'typescript';
    if (fileType === 'html' || fileType === 'xaml') return 'xml';
    if (fileType === 'csharp' || fileType === 'cs') return 'csharp';
    if (fileType === 'css') return 'css';
    if (fileType === 'json') return 'json';
  }
  switch (framework) {
    case 'web': return 'javascript';
    case 'electron': return 'typescript';
    case 'maui': return 'xml';
    case 'nodejs': return 'javascript';
    default: return 'javascript';
  }
}
