import { useState, useCallback, memo } from 'react';
import { Button } from '@/components/ui/button';
import { ScrollArea } from '@/components/ui/scroll-area';
import { Input } from '@/components/ui/input';
import {
  File,
  Folder,
  FolderOpen,
  Plus,
  DotsThree,
  Trash,
  PencilSimple,
} from '@phosphor-icons/react';
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
import { toast } from 'sonner';

export interface FileNode {
  id: string;
  name: string;
  type: 'file' | 'folder';
  children?: FileNode[];
  content?: string;
}

interface FileTreeProps {
  files: FileNode[];
  onFileSelect: (file: FileNode) => void;
  onFileCreate: (name: string, parentId?: string) => void;
  onFileRename: (id: string, newName: string) => void;
  onFileDelete: (id: string) => void;
  onFileMove?: (fileId: string, targetParentId: string) => void;
  selectedFileId?: string;
}

export function FileTree({
  files,
  onFileSelect,
  onFileCreate,
  onFileRename,
  onFileDelete,
  onFileMove,
  selectedFileId,
}: FileTreeProps) {
  const [expandedFolders, setExpandedFolders] = useState<Set<string>>(new Set(['root']));
  const [editingId, setEditingId] = useState<string | null>(null);
  const [editingName, setEditingName] = useState('');
  const [draggedId, setDraggedId] = useState<string | null>(null);
  const [dropTargetId, setDropTargetId] = useState<string | null>(null);

  const toggleFolder = useCallback((id: string) => {
    setExpandedFolders((prev) => {
      const next = new Set(prev);
      if (next.has(id)) {
        next.delete(id);
      } else {
        next.add(id);
      }
      return next;
    });
  }, []);

  const startRename = useCallback((node: FileNode) => {
    setEditingId(node.id);
    setEditingName(node.name);
  }, []);

  const finishRename = useCallback((id: string) => {
    if (editingName.trim()) {
      onFileRename(id, editingName.trim());
    }
    setEditingId(null);
    setEditingName('');
  }, [editingName, onFileRename]);

  const handleDelete = useCallback((node: FileNode) => {
    if (confirm(`Are you sure you want to delete "${node.name}"?`)) {
      onFileDelete(node.id);
    }
  }, [onFileDelete]);

  const handleDragStart = useCallback((e: React.DragEvent, node: FileNode) => {
    e.stopPropagation();
    setDraggedId(node.id);
    e.dataTransfer.effectAllowed = 'move';
  }, []);

  const handleDragOver = useCallback((e: React.DragEvent, node: FileNode) => {
    e.preventDefault();
    e.stopPropagation();

    // Only allow dropping on folders
    if (node.type === 'folder' && draggedId !== node.id) {
      e.dataTransfer.dropEffect = 'move';
      setDropTargetId(node.id);
    }
  }, [draggedId]);

  const handleDragLeave = useCallback((e: React.DragEvent) => {
    e.preventDefault();
    e.stopPropagation();
    setDropTargetId(null);
  }, []);

  const handleDrop = useCallback((e: React.DragEvent, targetNode: FileNode) => {
    e.preventDefault();
    e.stopPropagation();

    if (!draggedId || !onFileMove || targetNode.type !== 'folder') {
      setDraggedId(null);
      setDropTargetId(null);
      return;
    }

    // Prevent dropping on itself or its children
    if (draggedId === targetNode.id) {
      setDraggedId(null);
      setDropTargetId(null);
      return;
    }

    onFileMove(draggedId, targetNode.id);
    toast.success('File moved');
    setDraggedId(null);
    setDropTargetId(null);
  }, [draggedId, onFileMove]);

  const handleDragEnd = useCallback(() => {
    setDraggedId(null);
    setDropTargetId(null);
  }, []);

  const renderNode = (node: FileNode, depth: number = 0) => {
    const isExpanded = expandedFolders.has(node.id);
    const isSelected = selectedFileId === node.id;
    const isEditing = editingId === node.id;
    const isDragging = draggedId === node.id;
    const isDropTarget = dropTargetId === node.id;

    return (
      <div key={node.id}>
        <div
          role={node.type === 'folder' ? 'button' : 'button'}
          tabIndex={0}
          aria-label={node.type === 'folder' ? `${isExpanded ? 'Collapse' : 'Expand'} folder ${node.name}` : `Open file ${node.name}`}
          aria-expanded={node.type === 'folder' ? isExpanded : undefined}
          draggable={!isEditing}
          onDragStart={(e) => handleDragStart(e, node)}
          onDragOver={(e) => handleDragOver(e, node)}
          onDragLeave={handleDragLeave}
          onDrop={(e) => handleDrop(e, node)}
          onDragEnd={handleDragEnd}
          onKeyDown={(e) => {
            if (e.key === 'Enter' || e.key === ' ') {
              e.preventDefault();
              if (node.type === 'folder') {
                toggleFolder(node.id);
              } else {
                onFileSelect(node);
              }
            }
          }}
          className={`flex items-center gap-1 px-2 py-1.5 md:py-1 hover:bg-muted/60 cursor-pointer group rounded-sm transition-colors touch-manipulation focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-1 ${
            isSelected ? 'bg-accent/30 text-accent font-semibold' : 'text-foreground'
          } ${isDragging ? 'opacity-50' : ''} ${isDropTarget && node.type === 'folder' ? 'bg-blue-500/20 border-2 border-blue-500 border-dashed' : ''}`}
          style={{ paddingLeft: `${depth * 10 + 8}px` }}
          onClick={() => {
            if (node.type === 'folder') {
              toggleFolder(node.id);
            } else {
              onFileSelect(node);
            }
          }}
        >
          {node.type === 'folder' ? (
            isExpanded ? (
              <FolderOpen size={16} className="flex-shrink-0 opacity-80 md:w-[15px] md:h-[15px]" />
            ) : (
              <Folder size={16} className="flex-shrink-0 opacity-80 md:w-[15px] md:h-[15px]" />
            )
          ) : (
            <File size={16} className="flex-shrink-0 opacity-80 md:w-[15px] md:h-[15px]" />
          )}

          {isEditing ? (
            <Input
              value={editingName}
              onChange={(e) => setEditingName(e.target.value)}
              onBlur={() => finishRename(node.id)}
              onKeyDown={(e) => {
                if (e.key === 'Enter') finishRename(node.id);
                if (e.key === 'Escape') setEditingId(null);
              }}
              className="h-6 text-xs px-1 py-0.5"
              autoFocus
              onClick={(e) => e.stopPropagation()}
            />
          ) : (
            <span className="text-xs flex-1 truncate select-none" title={node.name}>{node.name}</span>
          )}

          <DropdownMenu>
            <DropdownMenuTrigger asChild onClick={(e) => e.stopPropagation()}>
              <Button
                variant="ghost"
                size="icon"
                className="h-6 w-6 md:h-5 md:w-5 opacity-50 md:opacity-0 group-hover:opacity-100 touch-manipulation"
              >
                <DotsThree size={16} className="md:w-[13px] md:h-[13px]" />
              </Button>
            </DropdownMenuTrigger>
            <DropdownMenuContent align="end">
              <DropdownMenuItem onClick={() => startRename(node)}>
                <PencilSimple className="mr-2" />
                Rename
              </DropdownMenuItem>
              <DropdownMenuItem
                onClick={() => handleDelete(node)}
                className="text-destructive"
              >
                <Trash className="mr-2" />
                Delete
              </DropdownMenuItem>
            </DropdownMenuContent>
          </DropdownMenu>
        </div>

        {node.type === 'folder' && isExpanded && node.children && (
          <div>{node.children.map((child) => renderNode(child, depth + 1))}</div>
        )}
      </div>
    );
  };

  return (
    <div className="flex flex-col h-full bg-card border-r border-border min-w-[180px] max-w-[260px]">
      <div className="flex items-center justify-between px-2 py-1.5 border-b border-border bg-card/80">
        <span className="text-xs font-bold tracking-wide uppercase text-muted-foreground">Explorer</span>
        <Button
          variant="ghost"
          size="icon"
          className="h-6 w-6"
          title="New File"
          aria-label="Create new file"
          onClick={() => {
            const name = prompt('Enter file name:');
            if (name) {
              onFileCreate(name);
            }
          }}
        >
          <Plus size={14} aria-hidden="true" />
        </Button>
      </div>
      <ScrollArea className="flex-1">
        <div className="py-1">{files.map((node) => renderNode(node))}</div>
      </ScrollArea>
    </div>
  );
}
