import React, { useEffect, useMemo, useState } from 'react';
import DocumentSummarySection from './DocumentSummarySection';
import { buildDocumentMetadataItems, extractDocumentMetadataPayload } from './documentMetadata';

const DocumentInfoPanel = ({
  document,
  summaryProps = {},
  metadataItems: metadataItemsProp,
  metadataPayload: metadataPayloadProp,
  metadataTabLabel = 'Metadata',
  detailsTabLabel = 'Details',
  contentConfig: contentConfigProp = null,
  activeTab: controlledActiveTab,
  onTabChange,
  defaultTabId = 'details',
  resetKey = null,
  classNamePrefix = 'document-info',
  hideTabNavWhenSingle = true,
}) => {
  const base = classNamePrefix;

  const metadataItems = useMemo(() => {
    if (Array.isArray(metadataItemsProp) && metadataItemsProp.length) {
      return metadataItemsProp;
    }
    return buildDocumentMetadataItems(document);
  }, [metadataItemsProp, document]);

  const metadataPayload = useMemo(() => {
    if (metadataPayloadProp !== undefined) {
      return metadataPayloadProp;
    }
    return extractDocumentMetadataPayload(document);
  }, [metadataPayloadProp, document]);

  const contentConfig = contentConfigProp || null;
  const contentEnabled = Boolean(contentConfig && (contentConfig.enabled ?? true));
  const showContentTab = Boolean(contentConfig && ((contentConfig.forceDisplay ?? contentEnabled)));

  const [contentState, setContentState] = useState(() => {
    if (!contentConfig) {
      return null;
    }
    if (!contentEnabled || typeof contentConfig.loadContent !== 'function') {
      return { status: contentEnabled ? 'idle' : 'unavailable', data: null, error: null };
    }
    return { status: 'idle', data: null, error: null };
  });

  useEffect(() => {
    if (!contentConfig || !showContentTab) {
      setContentState(null);
      return undefined;
    }

    if (!contentEnabled || typeof contentConfig.loadContent !== 'function') {
      setContentState({ status: contentEnabled ? 'idle' : 'unavailable', data: null, error: null });
      return undefined;
    }

    let cancelled = false;
    const controller = new AbortController();

    setContentState({ status: 'loading', data: null, error: null });

    Promise.resolve(contentConfig.loadContent({ signal: controller.signal }))
      .then((result) => {
        if (cancelled) {
          return;
        }
        if (result && result.length) {
          setContentState({ status: 'loaded', data: result, error: null });
        } else {
          setContentState({ status: 'empty', data: '', error: null });
        }
      })
      .catch((error) => {
        if (cancelled || error?.name === 'AbortError') {
          return;
        }
        setContentState({
          status: 'error',
          data: null,
          error,
        });
      });

    return () => {
      cancelled = true;
      controller.abort();
      contentConfig.onCancel?.();
    };
  }, [contentConfig, contentEnabled, showContentTab, document?.id, resetKey]);

  const visibleTabs = useMemo(() => {
    const tabsList = [];

    tabsList.push({
      id: 'details',
      label: detailsTabLabel,
      render: () => (
        <section className={`${base}__section`}>
          {metadataItems.length ? (
            <dl className={`${base}__section-list`}>
              {metadataItems.map(({ label, value }) => (
                <div className={`${base}__section-item`} key={label}>
                  <dt>{label}</dt>
                  <dd>{value || '—'}</dd>
                </div>
              ))}
            </dl>
          ) : (
            <p className={`${base}__section-placeholder`}>No details available.</p>
          )}
        </section>
      ),
    });

    if (showContentTab && contentConfig) {
      tabsList.push({
        id: contentConfig.id || 'content',
        label: contentConfig.label || 'Content',
        render: () => {
          const messageClass = `${base}__message`;
          const errorClass = `${base}__message ${base}__message--error`;
          const objectClass = `${base}__object ${base}__object--ocr-text`;

          if (!contentEnabled || !contentConfig.loadContent) {
            return (
              <div className={messageClass}>
                {contentConfig.unavailableMessage || 'Content not available.'}
              </div>
            );
          }

          if (!contentState) {
            return (
              <div className={messageClass}>
                {contentConfig.emptyMessage || 'No content available.'}
              </div>
            );
          }

          switch (contentState.status) {
            case 'loading':
              return (
                <div className={messageClass}>
                  {contentConfig.loadingMessage || 'Loading content…'}
                </div>
              );
            case 'error': {
              const errorMessage =
                contentConfig.errorMessage
                || (contentState.error instanceof Error ? contentState.error.message : null)
                || 'Failed to load content.';
              return <div className={errorClass}>{errorMessage}</div>;
            }
            case 'empty':
              return (
                <div className={messageClass}>
                  {contentConfig.emptyMessage || 'No content available.'}
                </div>
              );
            case 'loaded':
              return (
                <pre className={objectClass}>{contentState.data}</pre>
              );
            case 'unavailable':
              return (
                <div className={messageClass}>
                  {contentConfig.unavailableMessage || 'Content not available.'}
                </div>
              );
            default:
              return (
                <div className={messageClass}>
                  {contentConfig.emptyMessage || 'No content available.'}
                </div>
              );
          }
        },
      });
    }

    if (metadataPayload) {
      tabsList.push({
        id: 'metadata',
        label: metadataTabLabel,
        render: () => (
          <section className={`${base}__section ${base}__section--metadata-json`}>
            <pre className={`${base}__metadata-json`}>
              {JSON.stringify(metadataPayload, null, 2)}
            </pre>
          </section>
        ),
      });
    }

    return tabsList;
  }, [
    base,
    detailsTabLabel,
    metadataItems,
    contentConfig,
    contentEnabled,
    contentState,
    metadataPayload,
    metadataTabLabel,
    showContentTab,
  ]);

  const fallbackTabId = useMemo(() => {
    if (!visibleTabs.length) {
      return null;
    }
    if (defaultTabId && visibleTabs.some((tab) => tab.id === defaultTabId)) {
      return defaultTabId;
    }
    return visibleTabs[0].id;
  }, [visibleTabs, defaultTabId]);

  const renderTabContent = (tab, context = {}) => {
    if (!tab) {
      return null;
    }
    if (typeof tab.render === 'function') {
      return tab.render(context);
    }
    if (tab.component) {
      const TabComponent = tab.component;
      return <TabComponent {...context} />;
    }
    return React.isValidElement(tab.render) ? tab.render : null;
  };

  const isControlled = controlledActiveTab !== undefined && controlledActiveTab !== null;
  const [uncontrolledTab, setUncontrolledTab] = useState(
    isControlled ? controlledActiveTab : fallbackTabId,
  );

  useEffect(() => {
    if (!isControlled) {
      setUncontrolledTab(fallbackTabId);
    }
  }, [fallbackTabId, resetKey, isControlled]);

  useEffect(() => {
    if (isControlled && controlledActiveTab && !visibleTabs.some((tab) => tab.id === controlledActiveTab)) {
      const nextTab = fallbackTabId;
      if (nextTab && nextTab !== controlledActiveTab) {
        onTabChange?.(nextTab);
      }
    }
  }, [isControlled, controlledActiveTab, visibleTabs, fallbackTabId, onTabChange]);

  const activeTabId = isControlled ? controlledActiveTab : uncontrolledTab;

  const handleTabSelect = (tabId) => {
    if (!visibleTabs.some((tab) => tab.id === tabId)) {
      return;
    }
    if (!isControlled) {
      setUncontrolledTab(tabId);
    }
    if (tabId !== activeTabId) {
      onTabChange?.(tabId);
    }
  };

  const singleTab = visibleTabs.length === 1 ? visibleTabs[0] : null;
  const shouldHideNav = hideTabNavWhenSingle && singleTab;

  return (
    <>
      <DocumentSummarySection
        document={document}
        {...summaryProps}
      />
      {shouldHideNav ? (
        <div className={`${base}__tabpanes ${base}__tabpanes--single`}>
          <div className={`${base}__tabpanel`}>
            {renderTabContent(singleTab, { document })}
          </div>
        </div>
      ) : (
        <div className={`${base}__tabs-wrapper`}>
          <div className={`${base}__tabs`} role="tablist" aria-label="Document details">
            {visibleTabs.map((tab) => (
              <button
                key={tab.id}
                type="button"
                role="tab"
                aria-selected={tab.id === activeTabId}
                className={`${base}__tab${tab.id === activeTabId ? ' is-active' : ''}`}
                onClick={() => handleTabSelect(tab.id)}
              >
                {tab.label}
              </button>
            ))}
          </div>
          <div className={`${base}__tabpanes`}>
            {visibleTabs.map((tab) => (
              tab.id === activeTabId ? (
                <div key={tab.id} role="tabpanel" className={`${base}__tabpanel`}>
                  {renderTabContent(tab, { document })}
                </div>
              ) : null
            ))}
          </div>
        </div>
      )}
    </>
  );
};

export default DocumentInfoPanel;
