import { useCallback } from 'react';
import { useStatusToast } from '../../lib/context/StatusToastContext';

import {
  queueDocumentReanalysis,
  trashDocument,
  updateDocument,
} from '../../lib/api/apiClient';
import type { DocumentId, FolderId as FolderIdentifier } from '../../types/identifiers';
import type { Document, MessageOptions } from '../../types/documents';
import { useDocumentTagMutations } from './useDocumentTagMutations';
import { useDocumentMoveMutations } from './useDocumentMoveMutations';
import type {
  DocumentsState,
  FolderState,
  SelectionState,
  TagsState,
  ActionsState,
  Tag,
} from '../types/workspaceTypes';

type FolderId = FolderIdentifier | 'root';
type NullableFolderId = FolderId | null;


interface DocumentTagExtras {
  option?: Tag | null;
  input?: { value?: string } | null;
}

import useNotifyApiError from '../../hooks/useNotifyApiError';

interface UseDocumentMutationsArgs {
  documentsState: DocumentsState;
  folderState: FolderState;
  selectionState: SelectionState;
  tagsState: TagsState;
  actions: ActionsState;
  previewDocumentId?: DocumentId | null;
}

interface UseDocumentMutationsResult {
  moveDocumentsToFolder: (
    documentIds: Array<DocumentId | Document>,
    targetFolderId?: NullableFolderId,
  ) => Promise<void>;
  handleThumbnailRegeneration: (documentId: DocumentId) => Promise<void>;
  handleDocumentsDelete: (
    documentIds: DocumentId[],
    options?: MessageOptions,
  ) => Promise<boolean>;
  handleDocumentTagAdd: (
    document: Document,
    label: string,
    extras?: DocumentTagExtras | null,
  ) => Promise<void>;
  handleDocumentTagAttach: (documentId: DocumentId, tagId: DocumentId) => Promise<boolean>;
  handleDocumentTitleUpdate: (documentId: DocumentId, nextTitle: string) => Promise<boolean>;
  handleDocumentIssuedUpdate: (
    documentId: DocumentId,
    nextIssuedDate: number | null,
  ) => Promise<boolean>;
  handleDocumentTagDetach: (
    documentId?: DocumentId,
    tagId?: DocumentId,
  ) => Promise<boolean>;
}

const useDocumentMutations = ({
  documentsState,
  folderState,
  selectionState,
  tagsState,
  actions,
  previewDocumentId,
}: UseDocumentMutationsArgs): UseDocumentMutationsResult => {
  const { showToast } = useStatusToast();
  const notifyApiError = useNotifyApiError();

  const { moveDocumentsToFolder } = useDocumentMoveMutations({
    documentsState,
    folderState,
    selectionState,
  });

  const {
    handleDocumentTagAdd,
    handleDocumentTagAttach,
    handleDocumentTagDetach,
  } = useDocumentTagMutations({
    tagsState,
    documentsState: { updateDocumentCaches: documentsState.updateDocumentCaches },
  });

  const handleThumbnailRegeneration = useCallback(
    async (documentId: DocumentId) => {
      try {
        await queueDocumentReanalysis(documentId);
        showToast('Analysis queued.', 'info');
        // Close preview if it's the current one to allow refresh?
        if (previewDocumentId === documentId) {
          actions.closeDocumentPreview();
        }
      } catch (error) {
        notifyApiError(error, 'Failed to queue analysis.');
      }
    },
    [actions, notifyApiError, previewDocumentId, showToast],
  );

  const handleDocumentsDelete = useCallback(
    async (documentIds: DocumentId[], { showMessage = true }: MessageOptions = {}) => {
      if (!documentIds?.length) return false;

      // Optimistic update could happen here but usually we wait for standardized confirmation
      // However workspace expects mutation here.
      try {
        // We use trashDocument for soft delete
        // If we want hard delete we need deleteDocument
        // Assuming trash for now as it makes sense for "Delete" action in UI unless specified
        await Promise.all(documentIds.map((id) => trashDocument(id)));

        // Remove from local state
        documentsState.removeDocumentsFromCaches(documentIds);

        if (showMessage) {
          const count = documentIds.length;
          const suffix = count === 1 ? '' : 's';
          showToast(`${count} document${suffix} deleted.`, 'success');
        }
        return true;
      } catch (error) {
        const message = (error as Record<string, any>)?.response?.data?.error || 'Failed to delete documents.';
        notifyApiError(error, message);
        return false;
      }
    },
    [
      documentsState,
      notifyApiError,
      showToast,
    ],
  );

  const handleDocumentTitleUpdate = useCallback(
    async (documentId: DocumentId, nextTitle: string) => {
      const trimmed = nextTitle?.trim?.() || '';
      if (!trimmed) {
        showToast('Document title cannot be empty.', 'error');
        return false;
      }
      try {
        const data = await updateDocument(documentId, { title: trimmed });
        const updatedDocument = documentsState.extractDocumentFromResponse?.(data);

        if (updatedDocument && documentsState.ingestDocuments) {
          documentsState.ingestDocuments([updatedDocument]);
        } else {
          documentsState.updateDocumentCaches(documentId, (doc) => {
            if (updatedDocument) {
              return { ...doc, ...updatedDocument };
            }
            return { ...doc, title: trimmed };
          });
        }

        showToast('Document title updated.', 'success');
        return true;
      } catch (error) {
        const message = (error as Record<string, any>)?.response?.data?.error || 'Failed to update document title.';
        notifyApiError(error, message);
        return false;
      }
    },
    [
      documentsState,
      notifyApiError,
      showToast,
    ],
  );

  const handleDocumentIssuedUpdate = useCallback(
    async (documentId: DocumentId, nextIssuedDate: number | null) => {
      const payload = { issued_at: nextIssuedDate || null };
      try {
        const data = await updateDocument(documentId, payload);
        const updatedDocument = documentsState.extractDocumentFromResponse?.(data);

        if (updatedDocument && documentsState.ingestDocuments) {
          documentsState.ingestDocuments([updatedDocument]);
        } else {
          documentsState.updateDocumentCaches(documentId, (doc) => {
            if (updatedDocument) {
              return { ...doc, ...updatedDocument };
            }
            return { ...doc, issued_at: payload.issued_at };
          });
        }

        const message = payload.issued_at ? 'Issued date updated.' : 'Issued date cleared.';
        showToast(message, 'success');
        return true;
      } catch (error) {
        const message = (error as Record<string, any>)?.response?.data?.error || 'Failed to update issued date.';
        notifyApiError(error, message);
        return false;
      }
    },
    [
      documentsState,
      notifyApiError,
      showToast,
    ],
  );

  // handleFolderDelete is removed from here

  return {
    moveDocumentsToFolder,
    handleThumbnailRegeneration,
    handleDocumentsDelete,
    handleDocumentTagAdd,
    handleDocumentTagAttach,
    handleDocumentTitleUpdate,
    handleDocumentIssuedUpdate,
    handleDocumentTagDetach,
  };
};

export default useDocumentMutations;
