import { useCallback, useEffect, useRef, useState } from 'react';

export interface DetailDocument {
  id?: string;
  [key: string]: unknown;
}

interface UseDetailPanelOptions {
  documentLookup: Map<string, DetailDocument>;
  orderedSelectedDocuments: DetailDocument[];
}

interface OpenDetailPanelArgs {
  documentId?: string;
  document?: DetailDocument | null;
  documentIds?: Array<string>;
  documents?: DetailDocument[];
}

export const useDetailPanel = ({
  documentLookup,
  orderedSelectedDocuments,
}: UseDetailPanelOptions) => {
  const [detailPanelOpen, setDetailPanelOpen] = useState(false);
  const [detailPanelDocId, setDetailPanelDocId] = useState<string | null>(null);
  const [detailPanelDocument, setDetailPanelDocument] = useState<DetailDocument | null>(null);
  const latestOrderedDocsRef = useRef<DetailDocument[]>([]);

  useEffect(() => {
    latestOrderedDocsRef.current = orderedSelectedDocuments;
    if (detailPanelOpen && orderedSelectedDocuments.length) {
      const nextDoc = orderedSelectedDocuments[orderedSelectedDocuments.length - 1];
      if (nextDoc?.id) {
        setDetailPanelDocId(nextDoc.id);
        setDetailPanelDocument(nextDoc);
      }
    }
  }, [orderedSelectedDocuments, detailPanelOpen]);

  useEffect(() => {
    if (!detailPanelDocId) {
      if (!detailPanelOpen) {
        setDetailPanelDocument(null);
      }
      return;
    }
    const resolved = documentLookup.get(detailPanelDocId);
    if (resolved && resolved !== detailPanelDocument) {
      setDetailPanelDocument(resolved);
    }
  }, [detailPanelDocId, documentLookup, detailPanelDocument, detailPanelOpen]);

  const openDetailPanel = useCallback(
    ({ documentId, document, documentIds, documents }: OpenDetailPanelArgs = {}) => {
      let targetDoc = document || null;
      let targetId = documentId ?? document?.id ?? null;

      if (!targetDoc && Array.isArray(documents) && documents.length) {
        targetDoc = documents[documents.length - 1];
        targetId = targetDoc?.id ?? targetId;
      }

      if (!targetDoc && Array.isArray(documentIds) && documentIds.length) {
        targetId = documentIds[documentIds.length - 1];
      }

      if (!targetDoc && targetId != null) {
        targetDoc = documentLookup.get(String(targetId)) || null;
      }

      if (!targetDoc) {
        const fallbackDocs = latestOrderedDocsRef.current;
        const fallbackDoc = Array.isArray(fallbackDocs) && fallbackDocs.length
          ? fallbackDocs[fallbackDocs.length - 1]
          : null;
        if (fallbackDoc) {
          targetDoc = fallbackDoc;
          targetId = fallbackDoc.id;
        }
      }

      if (!targetDoc && targetId == null) {
        return;
      }

      setDetailPanelDocId(targetDoc?.id ?? targetId ?? null);
      setDetailPanelDocument(targetDoc || null);
      setDetailPanelOpen(Boolean(targetDoc || targetId));
    },
    [documentLookup],
  );

  const closeDetailPanel = useCallback(() => {
    setDetailPanelOpen(false);
  }, []);

  return {
    detailPanelOpen,
    detailPanelDocument,
    openDetailPanel,
    closeDetailPanel,
    setDetailPanelOpen,
  };
};

export default useDetailPanel;
