import { useMemo } from 'react';
import type { DragEvent } from 'react';
import { TAG_FILTER_UNTAGGED } from '../app/workspaceUtils';
import type { StatusMessage } from '../hooks/documents/store/useDocumentsStore';
import type { Identifier } from '../types/identifiers';

interface FolderTreeNode {
  id: Identifier;
  name?: string;
  hasChildren?: boolean;
  loaded?: boolean;
  expanded?: boolean;
  children: Identifier[];
  [key: string]: unknown;
}

type FolderNodeMap = Map<Identifier, FolderTreeNode>;

type FolderToggleHandler = (folderId: Identifier) => void | Promise<void>;
type FolderDropHandler = (
  event: DragEvent<HTMLElement>,
  folderId: Identifier,
) => void | Promise<void>;

interface FolderClickHandlers {
  onToggle: FolderToggleHandler;
  onSelect: (folderId: Identifier | null) => void;
  onDrop: FolderDropHandler;
  onDragOver: (event: DragEvent<HTMLElement>, folderId: Identifier) => void;
  onDragLeave: (event: DragEvent<HTMLElement>) => void;
}

interface TagOption {
  id?: Identifier;
  label?: string;
  color?: string | null;
  [key: string]: unknown;
}

interface CorrespondentOption {
  id?: Identifier;
  name?: string;
  [key: string]: unknown;
}

interface TenantOption {
  id?: Identifier;
  name?: string;
  [key: string]: unknown;
}

interface UploadQueueItem {
  id: string;
  name?: string;
  size?: number | null;
  folderId?: Identifier | 'root';
  status?: string;
  error?: unknown;
  code?: number | null;
  document?: unknown;
  conflictDocumentId?: Identifier | null;
  [key: string]: unknown;
}

type UploadFilesHandler = (
  files: FileList | File[] | Iterable<File>,
  targetFolderId: Identifier | 'root',
) => void | Promise<void>;

interface UseSidebarPropsArgs {
  folderNodes: FolderNodeMap;
  folderClickHandlers: FolderClickHandlers;
  handleFolderDelete: (folderId: Identifier) => void | Promise<void>;
  handleFolderRename: (folderId: Identifier, name: string) => void | Promise<void>;
  selectedFolder: Identifier | null;
  handleFolderDragStart: (event: DragEvent<HTMLElement>, folderId: Identifier) => void;
  handleFolderDragEnd: (event: DragEvent<HTMLElement>) => void;
  draggedFolderId: Identifier | null;
  handlePromptCreateFolder?: (parentId?: Identifier | null) => void;
  creatingFolder: boolean;
  tags: TagOption[];
  handleTagCreate: (payload: { label?: string }) => void | Promise<void>;
  correspondents: CorrespondentOption[];
  handleCorrespondentCreate: (payload: { name?: string }) =>
    | Promise<CorrespondentOption | null | void>
    | CorrespondentOption
    | null
    | void;
  appStatus: string;
  previewActive: boolean;
  handleLogout: () => void | Promise<void>;
  status: StatusMessage | null;
  tenantName: string | null;
  tenantOptions: TenantOption[];
  currentTenantId: Identifier | null;
  handleTenantSelect: (tenant: TenantOption | null, options?: { refreshOnly?: boolean }) => void | Promise<void>;
  openSettings?: () => void;
  handleFileSelection?: UploadFilesHandler;
  uploadQueue?: UploadQueueItem[];
}

interface SidebarHookResult {
  folderNodes: FolderNodeMap;
  onToggle: FolderClickHandlers['onToggle'];
  onSelect: FolderClickHandlers['onSelect'];
  onDrop: FolderClickHandlers['onDrop'];
  onDragOver: FolderClickHandlers['onDragOver'];
  onDragLeave: FolderClickHandlers['onDragLeave'];
  onDeleteFolder: UseSidebarPropsArgs['handleFolderDelete'];
  onRenameFolder: UseSidebarPropsArgs['handleFolderRename'];
  selectedFolder: Identifier | null;
  onFolderDragStart: UseSidebarPropsArgs['handleFolderDragStart'];
  onFolderDragEnd: UseSidebarPropsArgs['handleFolderDragEnd'];
  draggedFolderId: Identifier | null;
  onCreateFolder: UseSidebarPropsArgs['handlePromptCreateFolder'];
  creatingFolder: boolean;
  tags: TagOption[];
  untaggedFilterId: typeof TAG_FILTER_UNTAGGED;
  onCreateTag: (label: string) => void;
  correspondents: CorrespondentOption[];
  onCreateCorrespondent: (name: string) => void;
  appStatus: string;
  previewActive: boolean;
  onLogout: UseSidebarPropsArgs['handleLogout'];
  status: StatusMessage | null;
  tenantName: string | null;
  tenants: TenantOption[];
  activeTenantId: Identifier | null;
  onSelectTenant: UseSidebarPropsArgs['handleTenantSelect'];
  onOpenSettings: UseSidebarPropsArgs['openSettings'];
  onUploadFiles: (files: FileList | File[] | Iterable<File>, targetFolderId?: Identifier | 'root') => void;
  uploadQueue?: UploadQueueItem[];
}

const useSidebarProps = ({
  folderNodes,
  folderClickHandlers,
  handleFolderDelete,
  handleFolderRename,
  selectedFolder,
  handleFolderDragStart,
  handleFolderDragEnd,
  draggedFolderId,
  handlePromptCreateFolder,
  creatingFolder,
  tags,
  handleTagCreate,
  correspondents,
  handleCorrespondentCreate,
  appStatus,
  previewActive,
  handleLogout,
  status,
  tenantName,
  tenantOptions,
  currentTenantId,
  handleTenantSelect,
  openSettings,
  handleFileSelection,
  uploadQueue,
}: UseSidebarPropsArgs): SidebarHookResult =>
  useMemo(
    () => ({
      folderNodes,
      onToggle: folderClickHandlers.onToggle,
      onSelect: folderClickHandlers.onSelect,
      onDrop: folderClickHandlers.onDrop,
      onDragOver: folderClickHandlers.onDragOver,
      onDragLeave: folderClickHandlers.onDragLeave,
      onDeleteFolder: handleFolderDelete,
      onRenameFolder: handleFolderRename,
      selectedFolder,
      onFolderDragStart: handleFolderDragStart,
      onFolderDragEnd: handleFolderDragEnd,
      draggedFolderId,
      onCreateFolder: (parentId) => handlePromptCreateFolder?.(parentId),
      creatingFolder,
      tags,
      untaggedFilterId: TAG_FILTER_UNTAGGED,
      onCreateTag: (label) => handleTagCreate({ label }),
      correspondents,
      onCreateCorrespondent: (name) => handleCorrespondentCreate({ name }),
      appStatus,
      previewActive,
      onLogout: handleLogout,
      status,
      tenantName,
      tenants: tenantOptions,
      activeTenantId: currentTenantId,
      onSelectTenant: handleTenantSelect,
      onOpenSettings: openSettings,
      onUploadFiles: (files, targetFolderId) => {
        if (!handleFileSelection) {
          return;
        }
        if (!files) {
          return;
        }
        const normalizedFiles = Array.isArray(files) ? files : Array.from(files);
        if (normalizedFiles.length === 0) {
          return;
        }
        const folderId = targetFolderId ?? selectedFolder ?? 'root';
        handleFileSelection(normalizedFiles, folderId);
      },
      uploadQueue,
    }),
    [
      handleFileSelection,
      uploadQueue,
      appStatus,
      correspondents,
      creatingFolder,
      currentTenantId,
      folderClickHandlers,
      folderNodes,
      handleCorrespondentCreate,
      handleFolderDragEnd,
      handleFolderDragStart,
      handleFolderDelete,
      handleFolderRename,
      handleLogout,
      handlePromptCreateFolder,
      handleTagCreate,
      handleTenantSelect,
      openSettings,
      previewActive,
      draggedFolderId,
      selectedFolder,
      status,
      tags,
      tenantName,
      tenantOptions,
    ],
  );

export default useSidebarProps;
