import { useCallback, useMemo, useRef } from 'react';
import type { JSX } from 'react';
import DocumentInfoPanel from '../documents/DocumentInfoPanel';
import PdfViewer from './PdfViewer';
import MediaViewer from './MediaViewer';

import type { Document } from '../types/documents';

interface DocumentLink {
  url?: string;
  mimeType?: string;
  filename?: string;
}

interface ContentTabConfig {
  id?: string;
  label?: string;
  enabled?: boolean;
  forceDisplay?: boolean;
  loadContent?: (options?: { signal?: AbortSignal }) => unknown | Promise<unknown>;
  loadingMessage?: string;
  emptyMessage?: string;
  unavailableMessage?: string;
  errorMessage?: string;
  [key: string]: unknown;
}

type LayoutMode = 'split' | 'stacked' | (string & {});

interface DocumentViewerLayoutProps {
  document?: Document | null;
  documentLink?: DocumentLink | null;
  summaryProps?: Record<string, unknown>;
  metadataPayload?: unknown;
  contentTabConfig?: ContentTabConfig | null;
  resetKey?: string | null;
  classNamePrefix?: string;
  defaultTabId?: string;
  infoPanelProps?: Record<string, unknown>;
  previewLoadingMessage?: string;
  layoutMode?: LayoutMode;
}

const DocumentViewerLayout = ({
  document,
  documentLink,
  summaryProps = {},
  metadataPayload,
  contentTabConfig,
  resetKey,
  classNamePrefix = 'document-viewer',
  defaultTabId = 'details',
  infoPanelProps = {},
  previewLoadingMessage = 'Preparing preview…',
  layoutMode = 'split',
}: DocumentViewerLayoutProps): JSX.Element => {
  const isStacked = layoutMode === 'stacked';
  const viewportRef = useRef<HTMLDivElement>(null);

  const previewContent = useMemo(() => {
    if (!document || !documentLink?.url) {
      return null;
    }

    const normalizedMimeType = (documentLink.mimeType
      || document.mime_type
      || '')
      .toLowerCase();
    const normalizedFilename = documentLink.filename
      || document.filename
      || document.original_name
      || '';
    const isPdf = normalizedMimeType === 'application/pdf'
      || normalizedMimeType === 'application/x-pdf';

    if (isPdf) {
      const documentTitle = document.title
        || document.filename
        || document.original_name;
      return (
        <PdfViewer
          src={documentLink.url}
          title={documentTitle ? `Preview of ${documentTitle}` : undefined}
          viewportRef={viewportRef}
        />
      );
    }

    return (
      <MediaViewer
        src={documentLink.url}
        mimeType={normalizedMimeType}
        filename={normalizedFilename}
        alt={`Preview of ${document.title}`}
      />
    );
  }, [document, documentLink, viewportRef]);

  const renderViewportPane = useCallback(() => (
    <div className="document-viewer__viewport" ref={viewportRef}>
      {!documentLink?.url ? (
        <div className="document-viewer__message">{previewLoadingMessage}</div>
      ) : (
        previewContent
      )}
    </div>
  ), [previewContent, documentLink?.url, previewLoadingMessage, viewportRef]);

  const viewportPane = renderViewportPane();

  const stackedLeadingTabs = useMemo(() => (
    isStacked
      ? [
        {
          id: 'preview',
          label: 'Preview',
          render: () => renderViewportPane(),
        },
      ]
      : []
  ), [isStacked, renderViewportPane]);

  const resolvedDefaultTabId = isStacked ? 'preview' : defaultTabId;
  const summaryPlacement = 'tabs';
  const tabsPlacement = 'bottom';
  const summaryLayout = 'compact';

  const detailsPane = (
    <div className="document-viewer__details-pane">
      <div className="document-viewer__details">
        <DocumentInfoPanel
          document={document}
          summaryProps={summaryProps}
          metadataPayload={metadataPayload}
          contentConfig={contentTabConfig}
          defaultTabId={resolvedDefaultTabId}
          classNamePrefix={classNamePrefix}
          hideTabNavWhenSingle={false}
          resetKey={resetKey || document?.id}
          summaryPlacement={summaryPlacement}
          summaryLayout={summaryLayout}
          leadingTabs={stackedLeadingTabs}
          tabsPlacement={tabsPlacement}
          {...infoPanelProps}
        />
      </div>
    </div>
  );

  if (isStacked) {
    return detailsPane;
  }

  return (
    <>
      {detailsPane}
      {viewportPane}
    </>
  );
};

export default DocumentViewerLayout;
