import { useFileStore } from '../../stores/fileStore';
import { FileNode } from '../../lib/db';
import { useState, useMemo, useEffect, useRef } from 'react';
import { 
  Folder01Icon, 
  File01Icon, 
  MoreVerticalIcon, 
  FolderAddIcon,
  FileAddIcon,
  ArrowDown01Icon,
  ArrowRight01Icon,
  DragDropVerticalIcon,
  Copy01Icon
} from 'hugeicons-react';
import * as HugeIcons from 'hugeicons-react';
import IconPicker from './IconPicker';

import {
  DndContext, 
  closestCenter,
  KeyboardSensor,
  PointerSensor,
  useSensor,
  useSensors,
  DragEndEvent,
} from '@dnd-kit/core';
import {
  SortableContext,
  sortableKeyboardCoordinates,
  verticalListSortingStrategy,
  useSortable,
} from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';

export default function TreeView() {
  const { files, loadFiles, createNode, reorderNodes, moveNode, copySelectedContents } = useFileStore();
  
  const sensors = useSensors(
    useSensor(PointerSensor),
    useSensor(KeyboardSensor, {
      coordinateGetter: sortableKeyboardCoordinates,
    })
  );

  // Pre-calculate tree structure for O(N) rendering instead of O(N^2)
  const rootNodes = useMemo(() => files.filter(f => !f.parentId).sort((a,b) => a.orderIndex - b.orderIndex), [files]);
  const childrenMap = useMemo(() => {
    const map: Record<string, FileNode[]> = {};
    files.forEach(f => {
      if (f.parentId) {
        if (!map[f.parentId]) map[f.parentId] = [];
        map[f.parentId].push(f);
      }
    });
    // Sort each child group
    Object.keys(map).forEach(key => {
      map[key].sort((a,b) => a.orderIndex - b.orderIndex);
    });
    return map;
  }, [files]);

  const handleDragEnd = async (event: DragEndEvent) => {
    const { active, over } = event;
    if (!over || active.id === over.id) return;

    if (over.id.toString().startsWith('empty-')) {
       const targetId = over.id.toString().replace('empty-', '');
       
       let currentId: string | null = targetId;
       while (currentId) {
         if (currentId === active.id) return; 
         const p = files.find(f => f.id === currentId);
         currentId = p?.parentId || null; 
       }

       await moveNode(active.id.toString(), targetId);
       await loadFiles();
       return;
    }

    const overNode = files.find(f => f.id === over.id);
    if (!overNode) return;

    let targetParentId = overNode.parentId || null;
    let currentId = targetParentId;
    while (currentId) {
      if (currentId === active.id) return;
      const p = files.find(f => f.id === currentId);
      currentId = p?.parentId || null;
    }

    await reorderNodes(active.id.toString(), over.id.toString(), targetParentId);
    await loadFiles();
  };

  const handleCopyAll = () => {
    const text = copySelectedContents();
    if (text) {
      navigator.clipboard.writeText(text);
    }
  };

  const handleAdd = async (type: 'file' | 'folder') => {
    await createNode(type === 'file' ? 'New file' : 'New folder', type, null);
    await loadFiles();
  };

  return (
    <div className="tree-view" style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
      <div className="tree-actions" style={{ 
        padding: '12px 16px', 
        display: 'flex', 
        justifyContent: 'space-between',
        alignItems: 'center',
        borderBottom: '1px solid rgba(0,0,0,0.03)'
      }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
          <span style={{ fontSize: '10px', fontWeight: 700, opacity: 0.3, textTransform: 'uppercase' }}>Structure</span>
          <button 
            className="btn-icon-sm" 
            onClick={handleCopyAll} 
            title="Copy all selected contents"
            style={{ opacity: 0.5, cursor: 'pointer', border: 'none', background: 'transparent', padding: 0 }}
          >
            <Copy01Icon size={12} />
          </button>
        </div>
        <div style={{ display: 'flex', gap: '4px' }}>
          <button className="btn-icon-sm" onClick={() => handleAdd('file')} title="Add File">
            <FileAddIcon size={14} />
          </button>
          <button className="btn-icon-sm" onClick={() => handleAdd('folder')} title="Add Folder">
            <FolderAddIcon size={14} />
          </button>
        </div>
      </div>
      <div className="tree-scrollable" style={{ flex: 1, overflowY: 'auto', padding: '8px 0' }}>
        <DndContext 
          sensors={sensors}
          collisionDetection={closestCenter}
          onDragEnd={handleDragEnd}
        >
          <SortableContext 
            items={rootNodes.map(n => n.id)}
            strategy={verticalListSortingStrategy}
          >
            {rootNodes.map(node => (
              <SidebarItem 
                key={node.id} 
                node={node} 
                level={0} 
                childrenMap={childrenMap}
              />
            ))}
          </SortableContext>
        </DndContext>
      </div>
    </div>
  );
}

function SidebarItem({ 
  node, 
  level, 
  childrenMap 
}: { 
  node: FileNode; 
  level: number; 
  childrenMap: Record<string, FileNode[]> 
}) {
  const { 
    activeFileId, selectedIds, 
    toggleSelect, renameNode, deleteNode, duplicateNode, createNode, loadFiles, setNodeIcon, setNodeColor, copyNodeContents 
  } = useFileStore();
  
  const [isExpanded, setIsExpanded] = useState(true);
  const [isEditing, setIsEditing] = useState(false);
  const [editName, setEditName] = useState(node.name);
  const [showMenu, setShowMenu] = useState(false);
  const [showIconPicker, setShowIconPicker] = useState(false);
  const containerRef = useRef<HTMLDivElement>(null);

  const {
    attributes,
    listeners,
    setNodeRef,
    transform,
    transition,
    isDragging
  } = useSortable({ id: node.id });

  const style = {
    transform: CSS.Transform.toString(transform),
    transition,
    opacity: isDragging ? 0.5 : 1,
  };

  useEffect(() => {
    if (!showMenu && !showIconPicker) return;
    
    const handleEvents = (e: any) => {
      // Close on Escape
      if (e.key === 'Escape') {
        setShowMenu(false);
        setShowIconPicker(false);
      }
      // Close on Outside Click
      if (e.type === 'mousedown' && containerRef.current && !containerRef.current.contains(e.target as Node)) {
        setShowMenu(false);
        setShowIconPicker(false);
      }
    };

    document.addEventListener('keydown', handleEvents);
    document.addEventListener('mousedown', handleEvents);
    return () => {
      document.removeEventListener('keydown', handleEvents);
      document.removeEventListener('mousedown', handleEvents);
    };
  }, [showMenu, showIconPicker]);

  const children = childrenMap[node.id] || [];
  const isSelected = selectedIds.includes(node.id);
  const isActive = activeFileId === node.id;

  const handleClick = (e: any) => {
    e.stopPropagation();
    if (node.type === 'folder') {
      setIsExpanded(!isExpanded);
    }
    toggleSelect(node.id, e.ctrlKey || e.metaKey || e.shiftKey);
  };

  const handleRename = async () => {
    if (editName.trim() !== '' && editName !== node.name) {
      await renameNode(node.id, editName);
    }
    setIsEditing(false);
  };

  const handleMenuAction = async (action: string, e: any) => {
    e.stopPropagation();
    setShowMenu(false);
    
    switch (action) {
      case 'addFile':
        setIsExpanded(true);
        await createNode('New file', 'file', node.id);
        break;
      case 'addFolder':
        setIsExpanded(true);
        await createNode('New folder', 'folder', node.id);
        break;
      case 'rename':
        setIsEditing(true);
        break;
      case 'duplicate':
        await duplicateNode(node.id);
        break;
      case 'delete':
        await deleteNode(node.id);
        break;
      case 'changeIcon':
        setShowIconPicker(true);
        break;
      case 'copyContents':
        const text = copyNodeContents(node.id);
        navigator.clipboard.writeText(text);
        break;
    }
    await loadFiles();
  };

  return (
    <div 
      ref={(nodeEl) => {
        setNodeRef(nodeEl);
        (containerRef as any).current = nodeEl;
      }} 
      className="tree-item-wrapper" 
      style={{ ...style, display: 'flex', flexDirection: 'column' }}
      {...attributes}
    >
      <div 
        className={`tree-item ${isSelected ? 'selected' : ''} ${isActive ? 'active' : ''}`}
        style={{ 
          paddingLeft: `${16 + level * 12}px`, 
          display: 'flex', 
          alignItems: 'center', 
          paddingTop: '4px',
          paddingBottom: '4px',
          paddingRight: '12px',
          cursor: 'pointer',
          position: 'relative',
          transition: 'all 0.2s ease',
          backgroundColor: isActive ? 'rgba(0,0,0,0.04)' : isSelected ? 'rgba(0,0,0,0.02)' : 'transparent',
          borderLeft: isActive ? '2px solid var(--accent-color)' : '2px solid transparent',
        }}
        onClick={handleClick}
      >
        <div 
          className="drag-handle" 
          {...listeners} 
          style={{ cursor: 'grab', opacity: 0.2, marginRight: 4, display: 'flex' }}
        >
          <DragDropVerticalIcon size={14} />
        </div>

        {node.type === 'folder' && (
          <div style={{ marginRight: 4, display: 'flex', opacity: 0.4 }}>
            {isExpanded ? <ArrowDown01Icon size={12} /> : <ArrowRight01Icon size={12} />}
          </div>
        )}

        <div style={{ marginRight: 8, display: 'flex', color: node.color ? node.color : (isActive ? 'var(--text-primary)' : 'var(--text-secondary)') }}>
          {node.icon && (HugeIcons as any)[node.icon] ? (
            (() => {
              const CustomIcon = (HugeIcons as any)[node.icon];
              return <CustomIcon size={16} />;
            })()
          ) : (
            node.type === 'folder' ? <Folder01Icon size={16} /> : <File01Icon size={16} />
          )}
        </div>
        
        {isEditing ? (
          <input 
            autoFocus 
            value={editName}
            onChange={e => setEditName(e.target.value)}
            onBlur={handleRename}
            onKeyDown={e => { if (e.key === 'Enter') handleRename(); }}
            style={{ 
              border: 'none', 
              outline: 'none', 
              background: 'rgba(0,0,0,0.03)', 
              flex: 1, 
              fontFamily: 'inherit',
              fontSize: '13px',
              padding: '2px 4px',
              borderRadius: '2px'
            }}
          />
        ) : (
          <span style={{
            flex: 1, 
            fontSize: '13px', 
            userSelect: 'none',
            whiteSpace: 'nowrap',
            overflow: 'hidden',
            textOverflow: 'ellipsis',
            opacity: isActive ? 1 : 0.8
          }}>
            {node.name}
          </span>
        )}

        <div className="item-actions" style={{ display: 'flex', alignItems: 'center', gap: '4px' }}>
           <button 
              className="more-btn"
              onClick={(e: any) => { e.stopPropagation(); setShowMenu(!showMenu); }}
              style={{ padding: '4px', opacity: 0, transition: 'opacity 0.2s ease' }}
           >
             <MoreVerticalIcon size={14} />
           </button>
        </div>
        
        {showMenu && (
          <div className="context-menu" style={{
            position: 'absolute', right: 8, top: 28, zIndex: 100,
            background: 'var(--bg-panel)', border: '1px solid var(--border-color)', 
            borderRadius: '6px', boxShadow: '0 10px 25px rgba(0,0,0,0.1)',
            display: 'flex', flexDirection: 'column', minWidth: 140, padding: 4
          }}>
            {node.type === 'folder' && <MenuButton onClick={(e: any) => handleMenuAction('addFile', e)}>New File</MenuButton>}
            {node.type === 'folder' && <MenuButton onClick={(e: any) => handleMenuAction('addFolder', e)}>New Folder</MenuButton>}
            <MenuButton onClick={(e: any) => handleMenuAction('rename', e)}>Rename</MenuButton>
            <MenuButton onClick={(e: any) => handleMenuAction('changeIcon', e)}>Change Icon</MenuButton>
            <MenuButton onClick={(e: any) => handleMenuAction('duplicate', e)}>Duplicate</MenuButton>
            <MenuButton onClick={(e: any) => handleMenuAction('copyContents', e)}>Copy Contents</MenuButton>
            <MenuButton onClick={(e: any) => handleMenuAction('delete', e)} danger>Delete</MenuButton>
          </div>
        )}
      </div>
      
      {node.type === 'folder' && isExpanded && children.length > 0 && (
        <div className="tree-children" style={{ borderLeft: '1px solid rgba(0,0,0,0.03)', marginLeft: `${18 + level * 12}px` }}>
          <SortableContext 
            items={children.map(c => c.id)}
            strategy={verticalListSortingStrategy}
          >
            {children.map(child => (
              <SidebarItem 
                key={child.id} 
                node={child} 
                level={level + 1} 
                childrenMap={childrenMap} 
              />
            ))}
          </SortableContext>
        </div>
      )}
      
      {node.type === 'folder' && isExpanded && children.length === 0 && (
        <div className="tree-children" style={{ borderLeft: '1px solid rgba(0,0,0,0.03)', marginLeft: `${18 + level * 12}px` }}>
          <SortableContext 
            items={[`empty-${node.id}`]}
            strategy={verticalListSortingStrategy}
          >
            <EmptyDropZone id={`empty-${node.id}`} />
          </SortableContext>
        </div>
      )}

      {showIconPicker && (
        <IconPicker 
          onSelect={async (iconName, color) => {
            await setNodeIcon(node.id, iconName);
            if (color) {
              await setNodeColor(node.id, color);
            }
          }} 
          onClose={() => setShowIconPicker(false)} 
        />
      )}
    </div>
  );
}

function EmptyDropZone({ id }: { id: string }) {
  const { setNodeRef } = useSortable({ id });
  return (
    <div 
      ref={setNodeRef} 
      style={{ padding: '4px 16px', fontSize: '11px', opacity: 0.4, fontStyle: 'italic', display: 'flex', alignItems: 'center', height: '24px' }}
    >
      Drop files here...
    </div>
  );
}

function MenuButton({ children, onClick, danger }: { children: any, onClick: any, danger?: boolean }) {
  return (
    <button 
      onClick={onClick} 
      style={{
        padding: '6px 10px', textAlign: 'left', fontSize: '12px',
        borderRadius: '4px', color: danger ? '#ff4d4f' : 'inherit',
        transition: 'background 0.2s ease',
        width: '100%'
      }}
      onMouseEnter={e => e.currentTarget.style.background = 'rgba(0,0,0,0.03)'}
      onMouseLeave={e => e.currentTarget.style.background = 'transparent'}
    >
      {children}
    </button>
  );
}
