import { useEffect, useRef, useState } from 'react';
import { fetchMindSpacePageDraftPreview } from '../api/client';
import { bindIframeDocumentHeightSync } from '../utils/iframeContentHeight';
import { applyPageChangeHighlight } from '../utils/mindspacePageChangeHighlight';

export type MindSpacePreviewChangeHighlight = {
  revision: number;
  previousTitle: string;
  previousContent: string;
};

export function MindSpacePageDraftPreviewFrame({
  pageId,
  title,
  summary,
  content,
  templateId,
  reloadKey = 0,
  liveUpdate = true,
  minHeight = 680,
  maxHeight = 12000,
  className = 'mindspace-page-preview-frame',
  changeHighlight = null,
  onFrameReady,
}: {
  pageId: string;
  title: string;
  summary: string;
  content: string;
  templateId: string;
  reloadKey?: number;
  liveUpdate?: boolean;
  minHeight?: number;
  maxHeight?: number;
  className?: string;
  changeHighlight?: MindSpacePreviewChangeHighlight | null;
  onFrameReady?: (iframe: HTMLIFrameElement | null) => void;
}) {
  const iframeRef = useRef<HTMLIFrameElement>(null);
  const [srcdoc, setSrcdoc] = useState('');
  const [height, setHeight] = useState(minHeight);
  const [initialLoading, setInitialLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const requestRef = useRef(0);
  const hasRenderedRef = useRef(false);
  const appliedHighlightRevisionRef = useRef<number | null>(null);

  useEffect(() => {
    const requestId = requestRef.current + 1;
    requestRef.current = requestId;
    if (!hasRenderedRef.current) setInitialLoading(true);
    setError(null);

    const timer = window.setTimeout(() => {
      void fetchMindSpacePageDraftPreview(pageId, { title, summary, content, templateId })
        .then((html) => {
          if (requestRef.current !== requestId) return;
          setSrcdoc(html);
          hasRenderedRef.current = true;
          setInitialLoading(false);
        })
        .catch((err) => {
          if (requestRef.current !== requestId) return;
          setError(err instanceof Error ? err.message : '预览加载失败');
          setInitialLoading(false);
        });
    }, hasRenderedRef.current ? 450 : 120);

    return () => window.clearTimeout(timer);
  }, liveUpdate
    ? [pageId, title, summary, content, templateId, reloadKey]
    : [pageId, reloadKey, templateId]);

  useEffect(() => {
    setHeight(minHeight);
  }, [srcdoc, reloadKey, minHeight]);

  useEffect(() => {
    onFrameReady?.(iframeRef.current);
    return () => {
      onFrameReady?.(null);
    };
  }, [onFrameReady, srcdoc, reloadKey]);

  useEffect(() => {
    const iframe = iframeRef.current;
    if (!iframe || !srcdoc) return;

    const applyHeight = (nextHeight: number) => {
      setHeight(nextHeight);

      if (
        changeHighlight &&
        appliedHighlightRevisionRef.current !== changeHighlight.revision
      ) {
        try {
          const doc = iframe.contentDocument;
          if (!doc) return;
          appliedHighlightRevisionRef.current = changeHighlight.revision;
          applyPageChangeHighlight(doc, {
            previousTitle: changeHighlight.previousTitle,
            nextTitle: title,
            previousContent: changeHighlight.previousContent,
            nextContent: content,
          });
        } catch {
          // ignore highlight errors in sandboxed preview
        }
      }
    };

    return bindIframeDocumentHeightSync(iframe, {
      minHeight,
      maxHeight,
      onHeight: applyHeight,
    });
  }, [changeHighlight, content, maxHeight, minHeight, srcdoc, title]);

  if (error) {
    return <div className="mindspace-state mindspace-error">{error}</div>;
  }

  return (
    <>
      {initialLoading && !srcdoc ? (
        <div className="mindspace-state mindspace-page-preview-loading">正在加载预览…</div>
      ) : null}
      <iframe
        ref={iframeRef}
        title={`${title || '页面'} 预览`}
        srcDoc={srcdoc}
        sandbox="allow-same-origin allow-downloads"
        className={className}
        style={{ height: `${height}px`, visibility: srcdoc ? 'visible' : 'hidden' }}
      />
    </>
  );
}
