import React, { type DragEvent } from 'react';
import { parseTagTransferPayload } from '../tagTransfer';
import { createDocumentEntryKey } from '../../app/entryKey';
import type { Document } from '../../types/documents';
import type { DocumentsViewProps } from '../panel/DocumentsPanel';
import type { DocumentViewLogic } from './useDocumentViewLogic';
import type { Identifier } from '../../types/identifiers';

interface UseDocumentItemLogicProps extends DocumentsViewProps {
    doc: Document;
    viewLogic: DocumentViewLogic;
    onEntryPointer?: (entry: any, event: any) => void;
}

export const useDocumentItemLogic = (props: UseDocumentItemLogicProps) => {
    const {
        doc,
        viewLogic,
        draggingDocumentIdsSet,
        onDocumentActivate,
        onDocumentDragStart,
        onDocumentDragEnd,
        onDocumentTagDragStart,
        onDocumentTagDragEnd,
        onDocumentTagDragOver,
        onDocumentTagDragLeave,
        onDocumentTagAttach,
        onDocumentRename,
    } = props;

    const {
        selectedDocumentIdsSet,
        totalSelectionCount,
        documentRename: {
            editingId: editingDocumentId,
            draftValue: documentDraft,
            setDraftValue: setDocumentDraft,
            beginEditing: beginDocumentEditing,
            cancelEditing: cancelDocumentEditing,
            submitEditing: submitDocumentEditing,
            savingId: savingDocumentId,
            attachInputRef: attachDocumentInputRef,
        },
        handleEntrySelection,
    } = viewLogic;

    const isSelected = selectedDocumentIdsSet?.has(doc.id);
    const isDraggingDoc = draggingDocumentIdsSet?.has(doc.id);
    const isEditingDoc = editingDocumentId === doc.id;
    const documentDraftValue = isEditingDoc ? documentDraft : doc.title;
    const trimmedDocumentDraft = isEditingDoc ? documentDraft.trim() : '';
    const isDocumentSaving = savingDocumentId === doc.id;
    const canSubmitDocument =
        isEditingDoc && trimmedDocumentDraft.length > 0 && trimmedDocumentDraft !== doc.title;
    const allowInlineDocumentEdit = onDocumentRename && isSelected && totalSelectionCount === 1;

    const handlers = {
        onClick: (event: React.MouseEvent) => {
            if (props.onEntryPointer) {
                props.onEntryPointer({ type: 'document', id: doc.id, key: createDocumentEntryKey(doc.id), document: doc }, event);
            } else {
                const key = createDocumentEntryKey(doc.id);
                handleEntrySelection(key, event);
            }
        },
        onDoubleClick: (event: React.MouseEvent) => onDocumentActivate?.(doc, event),
        onDragStart: (event: DragEvent<HTMLElement>) => onDocumentDragStart?.(event, doc),
        onDragEnd: (event: DragEvent<HTMLElement>) => onDocumentDragEnd?.(event),
        onDragOver: (event: DragEvent<HTMLElement>) => onDocumentTagDragOver?.(event, doc.id),
        onDragLeave: onDocumentTagDragLeave,
        onTagDragStart: (event: DragEvent<HTMLElement>, tagId: Identifier) => onDocumentTagDragStart?.(event, doc.id, tagId),
        onTagDragEnd: (event: DragEvent<HTMLElement>) => onDocumentTagDragEnd?.(event),
        onDrop: (event: DragEvent<HTMLElement>) => {
            event.preventDefault();
            event.stopPropagation();
            const payload = parseTagTransferPayload(event);
            if (payload && payload.id && onDocumentTagAttach) {
                onDocumentTagAttach(doc.id, payload.id);
            }
        },
        onRenameChange: setDocumentDraft,
        onRenameSubmit: () => submitDocumentEditing(doc),
        onRenameCancel: (event?: React.SyntheticEvent) => cancelDocumentEditing(event),
        onRenameBegin: (event: React.SyntheticEvent) => {
            if (!allowInlineDocumentEdit) return;
            event.preventDefault();
            event.stopPropagation();
            beginDocumentEditing(doc);
        },
    };

    return {
        isSelected,
        isDraggingDoc,
        isEditingDoc,
        documentDraftValue,
        isDocumentSaving,
        canSubmitDocument,
        allowInlineDocumentEdit,
        attachDocumentInputRef,
        handlers,
    };
};
