import { useEffect, useRef, useState } from 'react';
import {
  Folder,
  File,
  FileText,
  HardDrive,
  Image as ImageIcon,
  ChevronRight,
  Home,
  RefreshCw,
  Upload,
  FolderPlus,
  ArrowLeft,
  Loader2,
  MoreVertical,
  Check,
  Trash2,
} from 'lucide-react';
import {
  createFolder,
  deletePath,
  humanFileSize,
  joinPath,
  listDirectory,
  normalizePath,
  putFileContents,
  splitPath,
  stat,
  type EntryInfo,
} from '../webdav';
import { toast } from 'sonner';
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogDescription,
} from './ui/dialog';

const TEXT_EXTS  = new Set(['txt','cfg','ini','bas','asm','seq','rel','prg','log','csv','s','lst','md','markdown','json','xml','svg','html','htm']);
const IMAGE_EXTS = new Set(['png','jpg','jpeg','gif','bmp','webp']);
const DISK_EXTS  = new Set(['d64','d71','d81','d82','g64','g71','t64','tap','crt','nib']);

function EntryIcon({ entry }: { entry: EntryInfo }) {
  if (entry.type === 'folder') return <Folder    className="w-5 h-5 text-blue-500 flex-shrink-0" />;
  const ext = entry.name.split('.').pop()?.toLowerCase() ?? '';
  if (IMAGE_EXTS.has(ext)) return <ImageIcon  className="w-5 h-5 text-purple-500 flex-shrink-0" />;
  if (DISK_EXTS.has(ext))  return <HardDrive  className="w-5 h-5 text-amber-500 flex-shrink-0" />;
  if (TEXT_EXTS.has(ext))  return <FileText   className="w-5 h-5 text-green-600 flex-shrink-0" />;
  return                           <File       className="w-5 h-5 text-neutral-400 flex-shrink-0" />;
}

interface FileBrowserProps {
  currentPath: string;
  onSelect: (path: string) => void;
  onClose: () => void;
}

export default function FileBrowser({ currentPath, onSelect, onClose }: FileBrowserProps) {
  // Resolve the initial path: if `currentPath` is itself a file, jump
  // to its parent so we never try to list a file as if it were a folder.
  const [path, setPath] = useState<string | null>(null);
  const [entries, setEntries] = useState<EntryInfo[]>([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [showNewFolder, setShowNewFolder] = useState(false);
  const [newFolderName, setNewFolderName] = useState('');
  const [actionEntry, setActionEntry] = useState<EntryInfo | null>(null);
  const fileInputRef = useRef<HTMLInputElement>(null);

  // Resolve the initial path on mount.
  useEffect(() => {
    const initial = normalizePath(currentPath || '/');
    if (initial === '/') {
      setPath('/');
      return;
    }
    let cancelled = false;
    stat(initial)
      .then((info) => {
        if (cancelled) return;
        if (info && info.type === 'file') {
          setPath(splitPath(info.path).parent);
        } else if (info && info.type === 'folder') {
          setPath(info.path);
        } else {
          setPath(splitPath(initial).parent);
        }
      })
      .catch(() => {
        if (cancelled) return;
        setPath(splitPath(initial).parent);
      });
    return () => {
      cancelled = true;
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  const load = async (p: string) => {
    setLoading(true);
    setError(null);
    try {
      const items = await listDirectory(p);
      setEntries(items);
    } catch (e: any) {
      const msg = (e && e.message) || 'Failed to load directory';
      setError(msg);
      setEntries([]);
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    if (path === null) return;
    void load(path);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [path]);

  const navigateUp = () => {
    if (path === '/' || path === null) return;
    setPath(splitPath(path).parent);
  };

  const navigateToFolder = (folderName: string) => {
    if (path === null) return;
    setPath(joinPath(path, folderName));
  };

  const selectEntry = (entry: EntryInfo) => {
    if (entry.type !== 'file') return;
    onSelect(entry.path);
    onClose();
  };

  const selectCurrentFolder = () => {
    if (path === null) return;
    onSelect(path);
    onClose();
  };

  const refresh = () => {
    if (path !== null) void load(path);
  };

  const handleCreateFolder = async () => {
    const name = newFolderName.trim();
    if (!name || path === null) return;
    try {
      await createFolder(joinPath(path, name), true);
      setNewFolderName('');
      setShowNewFolder(false);
      toast.success(`Created folder "${name}"`);
      void load(path);
    } catch (e: any) {
      toast.error(`Failed to create folder: ${e?.message || e}`);
    }
  };

  const handleDelete = async (entry: EntryInfo) => {
    const ok = window.confirm(
      entry.type === 'folder'
        ? `Delete folder "${entry.name}" and all its contents?`
        : `Delete file "${entry.name}"?`,
    );
    if (!ok) return;
    setActionEntry(null);
    try {
      await deletePath(entry.path);
      toast.success(`Deleted ${entry.name}`);
      if (path !== null) void load(path);
    } catch (e: any) {
      toast.error(`Failed to delete: ${e?.message || e}`);
    }
  };

  const handleUpload = async (file: File) => {
    if (path === null) return;
    const target = joinPath(path, file.name);
    try {
      const buf = await file.arrayBuffer();
      await putFileContents(target, buf);
      toast.success(`Uploaded ${file.name}`);
      void load(path);
    } catch (e: any) {
      toast.error(`Failed to upload ${file.name}: ${e?.message || e}`);
    }
  };

  const onPickFiles = (e: React.ChangeEvent<HTMLInputElement>) => {
    const files = e.target.files;
    if (!files) return;
    Array.from(files).forEach((f) => void handleUpload(f));
    e.target.value = '';
  };

  const pathParts = (path ?? '').split('/').filter(Boolean);

  return (
    <div className="fixed inset-0 bg-black/50 z-50 flex items-end" onClick={onClose}>
      <div
        className="bg-white w-full max-h-[80vh] rounded-t-xl flex flex-col"
        onClick={(e) => e.stopPropagation()}
      >
        <div className="sticky top-0 bg-white border-b border-neutral-200 p-4">
          <div className="flex items-center justify-between mb-3 gap-2">
            <h3 className="font-medium">Browse Files</h3>
            <div className="flex items-center gap-1">
              <button
                onClick={() => void refresh()}
                className="p-2 rounded hover:bg-neutral-100"
                aria-label="Refresh"
                title="Refresh"
              >
                <RefreshCw className="w-4 h-4" />
              </button>
              <button
                onClick={() => setShowNewFolder((s) => !s)}
                className="p-2 rounded hover:bg-neutral-100"
                aria-label="New folder"
                title="New folder"
              >
                <FolderPlus className="w-4 h-4" />
              </button>
              <button
                onClick={() => fileInputRef.current?.click()}
                className="p-2 rounded hover:bg-neutral-100"
                aria-label="Upload"
                title="Upload file"
              >
                <Upload className="w-4 h-4" />
              </button>
              <input
                ref={fileInputRef}
                type="file"
                multiple
                className="hidden"
                onChange={onPickFiles}
              />
              <button onClick={onClose} className="text-sm text-blue-600 ml-1">
                Cancel
              </button>
            </div>
          </div>

          {showNewFolder && (
            <div className="mb-3 flex items-center gap-2">
              <input
                value={newFolderName}
                onChange={(e) => setNewFolderName(e.target.value)}
                onKeyDown={(e) => {
                  if (e.key === 'Enter') void handleCreateFolder();
                  if (e.key === 'Escape') {
                    setShowNewFolder(false);
                    setNewFolderName('');
                  }
                }}
                placeholder="New folder name"
                className="flex-1 px-2 py-1 text-sm border border-neutral-300 rounded"
                autoFocus
              />
              <button
                onClick={() => void handleCreateFolder()}
                className="px-2 py-1 text-sm bg-blue-600 text-white rounded"
              >
                Create
              </button>
            </div>
          )}

          <div className="flex items-center gap-2 text-sm text-neutral-600 overflow-x-auto">
            <button
              onClick={() => setPath('/')}
              className="flex-shrink-0 p-1 rounded hover:bg-neutral-100"
              title="Root"
            >
              <Home className="w-4 h-4" />
            </button>
            {pathParts.map((part, index) => (
              <div key={index} className="flex items-center gap-2 flex-shrink-0">
                <ChevronRight className="w-3 h-3" />
                <button
                  onClick={() => {
                    const newPath = '/' + pathParts.slice(0, index + 1).join('/');
                    setPath(newPath);
                  }}
                  className="hover:text-blue-600"
                >
                  {part}
                </button>
              </div>
            ))}
          </div>
        </div>

        <div className="overflow-y-auto flex-1">
          {path === null && (
            <div className="p-8 text-center text-neutral-500 text-sm flex flex-col items-center gap-2">
              <Loader2 className="w-6 h-6 animate-spin" />
              Resolving location…
            </div>
          )}

          {loading && (
            <div className="p-8 text-center text-neutral-500 text-sm flex flex-col items-center gap-2">
              <Loader2 className="w-6 h-6 animate-spin" />
              Loading…
            </div>
          )}

          {!loading && error && (
            <div className="p-4 text-sm">
              <div className="text-red-600 mb-2">Failed to load directory</div>
              <div className="text-neutral-500 text-xs break-all">{error}</div>
              <button
                onClick={() => path !== null && void load(path)}
                className="mt-3 inline-flex items-center gap-1 text-blue-600 text-sm"
              >
                <RefreshCw className="w-3 h-3" /> Retry
              </button>
            </div>
          )}

          {!loading && !error && path !== null && (
            <>
              {path !== '/' && (
                <button
                  onClick={navigateUp}
                  className="w-full px-4 py-3 flex items-center gap-3 hover:bg-neutral-50 border-b border-neutral-100 text-left"
                >
                  <div className="text-neutral-400">
                    <ArrowLeft className="w-5 h-5" />
                  </div>
                  <span className="text-neutral-600">..</span>
                </button>
              )}

              {entries.map((entry) => (
                <div
                  key={entry.path}
                  className="w-full px-4 py-3 flex items-center gap-3 hover:bg-neutral-50 border-b border-neutral-100"
                >
                  <button
                    onClick={() => {
                      if (entry.type === 'folder') {
                        navigateToFolder(entry.name);
                      } else {
                        selectEntry(entry);
                      }
                    }}
                    className="flex-1 flex items-center gap-3 text-left min-w-0"
                  >
                    <EntryIcon entry={entry} />
                    <div className="min-w-0 flex-1">
                      <div className="text-neutral-900 truncate">{entry.name}</div>
                      {entry.type === 'file' && (
                        <div className="text-xs text-neutral-500 truncate">
                          {humanFileSize(entry.size)}
                          {entry.lastModified
                            ? ` · ${entry.lastModified.toLocaleDateString()}`
                            : ''}
                        </div>
                      )}
                    </div>
                    {entry.type === 'folder' && (
                      <ChevronRight className="w-4 h-4 text-neutral-400" />
                    )}
                  </button>
                  <button
                    onClick={(e) => {
                      e.stopPropagation();
                      setActionEntry(entry);
                    }}
                    className="p-2 rounded hover:bg-neutral-100"
                    aria-label={`Actions for ${entry.name}`}
                    title="Actions"
                  >
                    <MoreVertical className="w-4 h-4" />
                  </button>
                </div>
              ))}

              {entries.length === 0 && (
                <div className="p-8 text-center text-neutral-500 text-sm">
                  Empty folder
                </div>
              )}
            </>
          )}
        </div>

        <div className="sticky bottom-0 bg-white border-t border-neutral-200 p-4">
          <button
            onClick={selectCurrentFolder}
            disabled={path === null}
            className="w-full py-2 px-4 bg-blue-600 text-white rounded-lg disabled:opacity-50 inline-flex items-center justify-center gap-2"
            title="Use the current folder as your selection"
          >
            <Check className="w-4 h-4" />
            Select Folder: {path ?? '/'}
          </button>
        </div>
      </div>

      {/* Action menu modal */}
      <Dialog
        open={actionEntry !== null}
        onOpenChange={(open) => !open && setActionEntry(null)}
      >
        <DialogContent className="max-w-sm">
          <DialogHeader>
            <DialogTitle className="truncate">{actionEntry?.name}</DialogTitle>
            <DialogDescription>
              {actionEntry?.type === 'folder' ? 'Folder' : 'File'}
              {actionEntry?.type === 'file' && actionEntry.size > 0
                ? ` · ${humanFileSize(actionEntry.size)}`
                : ''}
            </DialogDescription>
          </DialogHeader>
          <div className="flex flex-col gap-2">
            {actionEntry?.type === 'file' && (
              <button
                onClick={() => actionEntry && selectEntry(actionEntry)}
                className="w-full text-left px-4 py-3 rounded border border-neutral-200 hover:bg-blue-50 hover:border-blue-300 inline-flex items-center gap-3"
              >
                <Check className="w-4 h-4 text-blue-600" />
                <span>Select this file</span>
              </button>
            )}
            {actionEntry?.type === 'folder' && (
              <button
                onClick={() => {
                  if (actionEntry) navigateToFolder(actionEntry.name);
                  setActionEntry(null);
                }}
                className="w-full text-left px-4 py-3 rounded border border-neutral-200 hover:bg-blue-50 hover:border-blue-300 inline-flex items-center gap-3"
              >
                <Folder className="w-4 h-4 text-blue-600" />
                <span>Open this folder</span>
              </button>
            )}
            <button
              onClick={() => actionEntry && void handleDelete(actionEntry)}
              className="w-full text-left px-4 py-3 rounded border border-red-200 hover:bg-red-50 text-red-700 inline-flex items-center gap-3"
            >
              <Trash2 className="w-4 h-4" />
              <span>Delete</span>
            </button>
          </div>
        </DialogContent>
      </Dialog>
    </div>
  );
}
