import { useState, useCallback, useEffect, useMemo, useRef } from 'react';
import { Folder, Trash2, Pencil, MoreVertical, MessageSquare, Scissors, Copy, Check, Play, Download } from 'lucide-react';
import { getIcon } from 'material-file-icons';
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuSeparator,
  DropdownMenuSub,
  DropdownMenuSubTrigger,
  DropdownMenuSubContent,
  DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
import {
  ContextMenu,
  ContextMenuContent,
  ContextMenuItem,
  ContextMenuSeparator,
  ContextMenuSub,
  ContextMenuSubTrigger,
  ContextMenuSubContent,
  ContextMenuTrigger,
} from '@/components/ui/context-menu';
import { cardStyle } from '@/components/Card';
import type { DirEntry, TaskSummary } from 'apps/FileBrowser';

export type FileItemProps = {
  entry: DirEntry;
  viewMode: 'grid' | 'list';
  selected: boolean;
  anySelected: boolean;
  selectedCount: number;
  isCut: boolean;
  onOpen: (entry: DirEntry) => void;
  onDelete: (entry: DirEntry) => void;
  onRename: (entry: DirEntry, newName: string) => void;
  onChat: (entry: DirEntry) => void;
  onDownload: (entry: DirEntry) => void;
  onSelect: (entry: DirEntry, ev: React.MouseEvent) => void;
  onCut: () => void;
  onCopy: () => void;
  forceRename: boolean;
  onRenamingChange: (name: string | null) => void;
  matchingTasks: TaskSummary[];
  onRunTask: (task: TaskSummary, entry: DirEntry) => void;
};

function formatSize(bytes: number): string {
  if (bytes < 1024) return `${bytes} B`;
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
  return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
}

function formatDate(ms: number): string {
  return new Date(ms).toLocaleDateString(undefined, {
    month: 'short',
    day: 'numeric',
    year: 'numeric',
  });
}

type MenuItemsProps = {
  entry: DirEntry;
  multiSelected: boolean;
  onDelete: (e: DirEntry) => void;
  onStartRename: () => void;
  onChat: (e: DirEntry) => void;
  onDownload: (e: DirEntry) => void;
  onCut: () => void;
  onCopy: () => void;
  matchingTasks: TaskSummary[];
  onRunTask: (task: TaskSummary, entry: DirEntry) => void;
};

const DropdownMenuItems = ({
  entry,
  multiSelected,
  onDelete,
  onStartRename,
  onChat,
  onDownload,
  onCut,
  onCopy,
  matchingTasks,
  onRunTask,
}: MenuItemsProps) => (
  <>
    <DropdownMenuItem onClick={() => onChat(entry)} className="cursor-pointer">
      <MessageSquare className="mr-2 h-4 w-4" />
      Chat...
    </DropdownMenuItem>
    <DropdownMenuItem onClick={() => onDownload(entry)} className="cursor-pointer">
      <Download className="mr-2 h-4 w-4" />
      Download
    </DropdownMenuItem>
    {matchingTasks.length > 0 && (
      <DropdownMenuSub>
        <DropdownMenuSubTrigger className="cursor-pointer">
          <Play className="mr-2 h-4 w-4" />
          Run Task
        </DropdownMenuSubTrigger>
        <DropdownMenuSubContent className="z-[600]">
          {matchingTasks.map((task) => (
            <DropdownMenuItem key={task.dirName} onClick={() => onRunTask(task, entry)} className="cursor-pointer">
              {task.name}
            </DropdownMenuItem>
          ))}
        </DropdownMenuSubContent>
      </DropdownMenuSub>
    )}
    <DropdownMenuSeparator />
    <DropdownMenuItem onClick={onCut} className="cursor-pointer">
      <Scissors className="mr-2 h-4 w-4" />
      Cut
    </DropdownMenuItem>
    <DropdownMenuItem onClick={onCopy} className="cursor-pointer">
      <Copy className="mr-2 h-4 w-4" />
      Copy
    </DropdownMenuItem>
    {!multiSelected && (
      <DropdownMenuItem onClick={onStartRename} className="cursor-pointer">
        <Pencil className="mr-2 h-4 w-4" />
        Rename
      </DropdownMenuItem>
    )}
    <DropdownMenuSeparator />
    <DropdownMenuItem onClick={() => onDelete(entry)} className="text-red-600 cursor-pointer">
      <Trash2 className="mr-2 h-4 w-4" />
      Delete
    </DropdownMenuItem>
  </>
);

const ContextMenuItems = ({
  entry,
  multiSelected,
  onDelete,
  onStartRename,
  onChat,
  onDownload,
  onCut,
  onCopy,
  matchingTasks,
  onRunTask,
}: MenuItemsProps) => (
  <>
    <ContextMenuItem onClick={() => onChat(entry)} className="cursor-pointer">
      <MessageSquare className="mr-2 h-4 w-4" />
      Chat...
    </ContextMenuItem>
    <ContextMenuItem onClick={() => onDownload(entry)} className="cursor-pointer">
      <Download className="mr-2 h-4 w-4" />
      Download
    </ContextMenuItem>
    {matchingTasks.length > 0 && (
      <ContextMenuSub>
        <ContextMenuSubTrigger className="cursor-pointer">
          <Play className="mr-2 h-4 w-4" />
          Run Task
        </ContextMenuSubTrigger>
        <ContextMenuSubContent className="z-[600]">
          {matchingTasks.map((task) => (
            <ContextMenuItem key={task.dirName} onClick={() => onRunTask(task, entry)} className="cursor-pointer">
              {task.name}
            </ContextMenuItem>
          ))}
        </ContextMenuSubContent>
      </ContextMenuSub>
    )}
    <ContextMenuSeparator />
    <ContextMenuItem onClick={onCut} className="cursor-pointer">
      <Scissors className="mr-2 h-4 w-4" />
      Cut
    </ContextMenuItem>
    <ContextMenuItem onClick={onCopy} className="cursor-pointer">
      <Copy className="mr-2 h-4 w-4" />
      Copy
    </ContextMenuItem>
    {!multiSelected && (
      <ContextMenuItem onClick={onStartRename} className="cursor-pointer">
        <Pencil className="mr-2 h-4 w-4" />
        Rename
      </ContextMenuItem>
    )}
    <ContextMenuSeparator />
    <ContextMenuItem onClick={() => onDelete(entry)} className="text-red-600 cursor-pointer">
      <Trash2 className="mr-2 h-4 w-4" />
      Delete
    </ContextMenuItem>
  </>
);

const EllipsisMenu = (props: MenuItemsProps) => (
  <div onClick={(ev) => ev.stopPropagation()}>
    <DropdownMenu>
      <DropdownMenuTrigger asChild>
        <button className="p-1 rounded hover:bg-duck-dark/10 cursor-pointer">
          <MoreVertical className="h-4 w-4 text-duck-dark/60" />
        </button>
      </DropdownMenuTrigger>
      <DropdownMenuContent align="end" className="z-[600]" onCloseAutoFocus={(ev) => ev.preventDefault()}>
        <DropdownMenuItems {...props} />
      </DropdownMenuContent>
    </DropdownMenu>
  </div>
);

const InlineRenameInput = ({
  initialName,
  onCommit,
  onCancel,
}: {
  initialName: string;
  onCommit: (name: string) => void;
  onCancel: () => void;
}) => {
  const [value, setValue] = useState(initialName);

  const mountRef = useCallback((node: HTMLInputElement | null) => {
    if (!node) return;
    requestAnimationFrame(() => {
      node.focus();
      const dotIndex = initialName.lastIndexOf('.');
      if (dotIndex > 0) {
        node.setSelectionRange(0, dotIndex);
      } else {
        node.select();
      }
    });
  }, []);

  const commit = () => {
    const trimmed = value.trim();
    if (trimmed && trimmed !== initialName) {
      onCommit(trimmed);
    } else {
      onCancel();
    }
  };

  return (
    <input
      ref={mountRef}
      value={value}
      onChange={(ev) => setValue(ev.target.value)}
      onBlur={commit}
      onKeyDown={(ev) => {
        if (ev.key === 'Enter') commit();
        if (ev.key === 'Escape') onCancel();
      }}
      onClick={(ev) => ev.stopPropagation()}
      className="text-sm font-medium text-duck-dark bg-background border border-duck-teal/50 rounded px-1 py-0.5 outline-none w-full text-center"
    />
  );
};

const Checkbox = ({
  checked,
  anySelected,
  onClick,
}: {
  checked: boolean;
  anySelected: boolean;
  onClick: (ev: React.MouseEvent) => void;
}) => (
  <button
    onClick={(ev) => {
      ev.stopPropagation();
      onClick(ev);
    }}
    className={`flex items-center justify-center h-5 w-5 rounded border-2 transition-all cursor-pointer ${
      checked ? 'bg-duck-teal border-duck-teal text-white' : 'border-duck-dark/30 bg-background/80 hover:border-duck-teal/50'
    } ${anySelected ? 'opacity-100' : 'opacity-0 group-hover:opacity-100'}`}
  >
    {checked && <Check className="h-3 w-3" />}
  </button>
);

const MaterialFileIcon = ({ name, className }: { name: string; className?: string }) => {
  const svg = useMemo(() => getIcon(name).svg, [name]);
  return <span className={className} dangerouslySetInnerHTML={{ __html: svg }} />;
};

export const FileItem = ({
  entry,
  viewMode,
  selected,
  anySelected,
  selectedCount,
  isCut,
  onOpen,
  onDelete,
  onRename,
  onChat,
  onDownload,
  onSelect,
  onCut,
  onCopy,
  forceRename,
  onRenamingChange,
  matchingTasks,
  onRunTask,
}: FileItemProps) => {
  const [renaming, setRenaming] = useState(false);
  const clickTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
  const isDir = entry.type === 'directory';

  const icon = isDir ? (
    <Folder className="h-5 w-5 text-duck-yellow fill-duck-yellow/30" />
  ) : (
    <MaterialFileIcon name={entry.name} className="inline-flex h-5 w-5" />
  );
  const iconLarge = isDir ? (
    <Folder className="h-10 w-10 text-duck-yellow fill-duck-yellow/30" />
  ) : (
    <MaterialFileIcon name={entry.name} className="inline-flex h-10 w-10" />
  );

  useEffect(() => {
    return () => {
      if (clickTimer.current) clearTimeout(clickTimer.current);
    };
  }, []);

  useEffect(() => {
    if (forceRename) {
      setRenaming(true);
      onRenamingChange(null);
    }
  }, [forceRename]);

  const handleCommitRename = (newName: string) => {
    setRenaming(false);
    onRename(entry, newName);
  };

  const handleClick = (ev: React.MouseEvent) => {
    if (renaming) return;
    // Modifier clicks select immediately (intentional multi-select)
    if (ev.ctrlKey || ev.metaKey || ev.shiftKey) {
      onSelect(entry, ev);
      return;
    }
    // Delay plain click so double-click doesn't trigger selection + layout shift
    const syntheticEv = { ctrlKey: false, shiftKey: false, metaKey: false } as React.MouseEvent;
    clickTimer.current = setTimeout(() => {
      clickTimer.current = null;
      onSelect(entry, syntheticEv);
    }, 200);
  };

  const handleDoubleClick = () => {
    if (renaming) return;
    if (clickTimer.current) {
      clearTimeout(clickTimer.current);
      clickTimer.current = null;
    }
    onOpen(entry);
  };

  const handleContextMenu = (ev: React.MouseEvent) => {
    ev.stopPropagation();
    if (!selected) {
      onSelect(entry, { ...ev, ctrlKey: false, shiftKey: false, metaKey: false } as React.MouseEvent);
    }
  };

  const menuProps: MenuItemsProps = {
    entry,
    multiSelected: selectedCount > 1,
    onDelete,
    onStartRename: () => setRenaming(true),
    onChat,
    onDownload,
    onCut,
    onCopy,
    matchingTasks,
    onRunTask,
  };

  const cutOpacity = isCut ? 'opacity-50' : '';

  if (viewMode === 'list') {
    return (
      <ContextMenu>
        <ContextMenuTrigger asChild onContextMenu={handleContextMenu}>
          <div
            data-file-item
            className={`group flex items-center gap-3 px-3 py-2 hover:bg-duck-teal/5 data-[state=open]:bg-duck-teal/5 cursor-pointer border-b border-duck-dark/5 last:border-b-0 transition-colors ${
              selected ? 'bg-duck-teal/10 border-duck-teal/50' : ''
            } ${cutOpacity} select-none`}
            onClick={handleClick}
            onDoubleClick={handleDoubleClick}
            onPointerDown={(ev) => ev.stopPropagation()}
          >
            <Checkbox checked={selected} anySelected={anySelected} onClick={(ev) => onSelect(entry, ev)} />
            <span className="shrink-0">{icon}</span>
            <div className="flex-1 min-w-0">
              {renaming ? (
                <InlineRenameInput
                  initialName={entry.name}
                  onCommit={handleCommitRename}
                  onCancel={() => setRenaming(false)}
                />
              ) : (
                <span className="text-sm font-medium text-duck-dark truncate block">{entry.name}</span>
              )}
            </div>
            <span className="hidden md:inline text-xs text-duck-dark/50 shrink-0 w-20 text-right">
              {isDir ? '--' : formatSize(entry.size)}
            </span>
            <span className="hidden md:inline text-xs text-duck-dark/50 shrink-0 w-28 text-right">
              {formatDate(entry.modifiedAt)}
            </span>
            <div className="file-item-ellipsis opacity-0 group-hover:opacity-100 data-[state=open]:opacity-100 transition-opacity shrink-0">
              <EllipsisMenu {...menuProps} />
            </div>
          </div>
        </ContextMenuTrigger>
        <ContextMenuContent className="z-[600]">
          <ContextMenuItems {...menuProps} />
        </ContextMenuContent>
      </ContextMenu>
    );
  }

  return (
    <ContextMenu>
      <ContextMenuTrigger asChild onContextMenu={handleContextMenu}>
        <div
          data-file-item
          className={`group relative rounded-lg border-2 p-4 flex flex-col items-center gap-2 hover:border-duck-teal/50 data-[state=open]:border-duck-teal/50 transition-colors cursor-pointer ${
            selected ? 'border-duck-teal/50 bg-duck-teal/10' : 'border-duck-dark/20'
          } ${cutOpacity} select-none`}
          style={
            selected
              ? undefined
              : cardStyle({
                  backgroundColor: 'rgba(255, 255, 255, 0.85)',
                  backgroundImage: `
                    linear-gradient(to right, rgba(20, 83, 45, 0.06) 1px, transparent 1px),
                    linear-gradient(to bottom, rgba(20, 83, 45, 0.06) 1px, transparent 1px)
                  `,
                })
          }
          onClick={handleClick}
          onDoubleClick={handleDoubleClick}
          onPointerDown={(ev) => ev.stopPropagation()}
        >
          <div className="absolute top-1 left-1">
            <Checkbox checked={selected} anySelected={anySelected} onClick={(ev) => onSelect(entry, ev)} />
          </div>

          <div className="file-item-ellipsis absolute top-1 right-1 opacity-0 group-hover:opacity-100 transition-opacity">
            <EllipsisMenu {...menuProps} />
          </div>

          {iconLarge}

          {renaming ? (
            <InlineRenameInput
              initialName={entry.name}
              onCommit={handleCommitRename}
              onCancel={() => setRenaming(false)}
            />
          ) : (
            <span className="text-sm font-medium text-duck-dark text-center truncate w-full">{entry.name}</span>
          )}

          <span className="text-xs text-duck-dark/50">
            {isDir ? 'Folder' : formatSize(entry.size)}
            {' · '}
            {formatDate(entry.modifiedAt)}
          </span>
        </div>
      </ContextMenuTrigger>
      <ContextMenuContent className="z-[600]">
        <ContextMenuItems {...menuProps} />
      </ContextMenuContent>
    </ContextMenu>
  );
};
