import { useCallback, useEffect, useRef, useState } from 'react';
import { usePageDraftHistory, type PageDraftSnapshot } from '../hooks/usePageDraftHistory';
import {
  checkMindSpacePagePublication,
  deleteMindSpacePage,
  fixMindSpacePagePublication,
  getMindSpacePageDeletePreview,
  getMindSpacePage,
  getMindSpacePublicationStats,
  listPlazaCategories,
  offlineMindSpacePublication,
  publishMindSpacePage,
  publishPageToPlaza,
  redactMindSpacePage,
  updateMindSpacePage,
} from '../api/client';
import type {
  MindSpacePage,
  MindSpacePageDeletePreview,
  MindSpacePublication,
  MindSpacePublicationStats,
  MindSpacePublishCheck,
  MindSpaceQuota,
  MindSpaceRedactionChange,
  PlazaCategory,
  PlazaPostBrief,
} from '../types';
import { resolvePlazaPostUrl, resolvePublicPageUrl } from '../utils/publicUrl';
import { MindSpacePageDraftPreviewFrame, type MindSpacePreviewChangeHighlight } from './MindSpacePageDraftPreviewFrame';
import {
  MindSpacePageFullscreenPreview,
} from './MindSpacePageFullscreenPreview';
import { MindSpacePagePreviewPanel } from './MindSpacePagePreviewPanel';
import { MindSpaceModal } from './MindSpaceModal';
import { MindSpacePublishSuccess } from './MindSpacePublishSuccess';
import { ShareSheet } from './ShareSheet';
import { buildPageSharePayload, type SharePayload } from '../utils/shareChannels';

type AccessMode = MindSpacePublishCheck['accessMode'];

const TEMPLATE_LABELS: Record<string, string> = {
  editorial: '编辑长文',
  report: '分析报告',
  'knowledge-card': '知识卡片',
  profile: '个人介绍',
  'static-html': '静态 HTML',
};

const STATUS_LABELS: Record<string, string> = {
  draft: '草稿',
  reviewing: '待检查',
  risk_found: '发现风险',
  ready: '可发布',
  published: '已公开',
  protected: '受保护',
  expired: '已过期',
  offline: '已下线',
};

const ACCESS_MODE_LABELS: Record<AccessMode, string> = {
  public: '完全公开',
  password: '密码访问',
  private_link: '私密链接',
  time_limited: '限时访问',
  login_required: '仅登录用户',
  owner_only: '仅自己可见',
};

function slugFromTitle(title: string, pageId?: string) {
  const ascii = title
    .normalize('NFKC')
    .toLowerCase()
    .replace(/[^a-z0-9]+/g, '-')
    .replace(/^-+|-+$/g, '')
    .slice(0, pageId ? 54 : 64);
  const base = ascii || 'page';
  if (pageId) {
    return `${base}-${pageId.replace(/-/g, '').slice(0, 8)}`.slice(0, 64);
  }
  return base;
}

function localDateTimeValue(timestamp: number) {
  const date = new Date(timestamp);
  return new Date(date.getTime() - date.getTimezoneOffset() * 60_000)
    .toISOString()
    .slice(0, 16);
}

function truncateLabel(text: string, max = 48) {
  const value = String(text ?? '').replace(/\s+/g, ' ').trim();
  if (value.length <= max) return value;
  return `${value.slice(0, max - 1)}…`;
}

type Html2CanvasRenderer = (
  element: HTMLElement,
  options?: Record<string, unknown>,
) => Promise<HTMLCanvasElement>;

type Html2CanvasWindow = Window & { html2canvas?: Html2CanvasRenderer };

const HTML2CANVAS_CDN = 'https://cdn.jsdelivr.net/npm/html2canvas@1.4.1/dist/html2canvas.min.js';
const LONG_IMAGE_RENDER_SCALE = 2;
let html2CanvasLoader: Promise<Html2CanvasRenderer> | null = null;

async function loadHtml2CanvasRenderer(): Promise<Html2CanvasRenderer> {
  const existing = (window as Html2CanvasWindow).html2canvas;
  if (existing) return existing;
  if (html2CanvasLoader) return html2CanvasLoader;

  html2CanvasLoader = new Promise<Html2CanvasRenderer>((resolve, reject) => {
    const script = document.createElement('script');
    script.src = HTML2CANVAS_CDN;
    script.async = true;
    script.onload = () => {
      const loaded = (window as Html2CanvasWindow).html2canvas;
      if (!loaded) {
        reject(new Error('无法加载页面截图能力'));
        return;
      }
      resolve(loaded);
    };
    script.onerror = () => {
      reject(new Error('无法加载页面截图能力'));
    };
    document.body.appendChild(script);
  }).catch((error) => {
    html2CanvasLoader = null;
    throw error;
  });
  return html2CanvasLoader;
}

function blobToDataUrl(blob: Blob): Promise<string> {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => resolve(String(reader.result ?? ''));
    reader.onerror = () => reject(new Error('无法读取图片数据'));
    reader.readAsDataURL(blob);
  });
}

function downloadBlobAsFile(dataUrl: string, filename: string) {
  const link = document.createElement('a');
  link.href = dataUrl;
  link.download = filename;
  document.body.appendChild(link);
  link.click();
  link.remove();
}

function buildExportFilename(pageId: string, title: string) {
  const safeTitle = String(title ?? '')
    .trim()
    .replace(/[\\/*?:"<>|]/g, '-')
    .replace(/\s+/g, '-')
    .slice(0, 24);
  const suffix = safeTitle ? `-${safeTitle}` : '';
  const timestamp = new Date().toISOString().replace(/[T:]/g, '-').replace(/\..+/, '');
  return `mindspace-page-${pageId}${suffix}-${timestamp}.png`;
}

function ensureBlobFromCanvas(canvas: HTMLCanvasElement): Promise<Blob> {
  return new Promise((resolve, reject) => {
    canvas.toBlob((blob) => {
      if (!blob) {
        reject(new Error('图片生成失败'));
        return;
      }
      resolve(blob);
    }, 'image/png');
  });
}

async function exportIframeToPng(iframe: HTMLIFrameElement): Promise<string> {
  const renderer = await loadHtml2CanvasRenderer();
  const doc = iframe.contentDocument;
  if (!doc || !doc.body) {
    throw new Error('预览内容无法访问');
  }
  const width = Math.max(doc.documentElement?.scrollWidth ?? 0, doc.body.scrollWidth, 320);
  const height = Math.max(doc.documentElement?.scrollHeight ?? 0, doc.body.scrollHeight, 320);
  const canvas = await renderer(doc.body, {
    useCORS: true,
    scale: LONG_IMAGE_RENDER_SCALE,
    backgroundColor: '#ffffff',
    width,
    height,
    windowWidth: width,
    windowHeight: height,
    x: 0,
    y: 0,
    scrollX: 0,
    scrollY: 0,
  });
  const blob = await ensureBlobFromCanvas(canvas);
  return await blobToDataUrl(blob);
}

async function fetchPageThumbnailAsDataUrl(pageId: string): Promise<string> {
  const response = await fetch(`/api/mindspace/v1/pages/${encodeURIComponent(pageId)}/thumbnail?v=${Date.now()}`);
  if (!response.ok) {
    throw new Error('未生成页面封面图');
  }
  const blob = await response.blob();
  if (!blob || !blob.size) {
    throw new Error('未生成页面封面图');
  }
  return await blobToDataUrl(blob);
}

export function MindSpacePageDetail({
  pageId,
  onBack,
  onSaved,
  onContextUpdate,
  autoOpenPlaza = false,
  refreshTrigger = 0,
  onFullscreenPreviewChange,
}: {
  pageId: string;
  onBack: () => void;
  onSaved: (options?: { quota?: MindSpaceQuota; freedBytes?: number }) => Promise<void>;
  onContextUpdate?: (value: {
    page: MindSpacePage;
    title: string;
    summary: string;
    content: string;
  }) => void;
  autoOpenPlaza?: boolean;
  refreshTrigger?: number;
  onFullscreenPreviewChange?: (open: boolean) => void;
}) {
  const [page, setPage] = useState<MindSpacePage | null>(null);
  const {
    snapshot: draft,
    update: updateDraft,
    replace: replaceDraft,
    undo,
    redo,
    reset: resetDraft,
    canUndo,
    canRedo,
  } = usePageDraftHistory({ title: '', summary: '', content: '' });
  const { title, summary, content } = draft;
  const [templateId, setTemplateId] = useState('editorial');
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [previewKey, setPreviewKey] = useState(0);
  const [previewContent, setPreviewContent] = useState('');
  const [previewRefreshPending, setPreviewRefreshPending] = useState(false);
  const [fullscreenPreviewOpen, setFullscreenPreviewOpen] = useState(false);
  const [changeHighlight, setChangeHighlight] = useState<MindSpacePreviewChangeHighlight | null>(
    null,
  );
  const changeHighlightRevisionRef = useRef(0);
  const [publishOpen, setPublishOpen] = useState(false);
  const [urlSlug, setUrlSlug] = useState('');
  const [accessMode, setAccessMode] = useState<AccessMode>('public');
  const [accessPassword, setAccessPassword] = useState('');
  const [expiresAt, setExpiresAt] = useState('');
  const [publishCheck, setPublishCheck] = useState<MindSpacePublishCheck | null>(null);
  const [publishing, setPublishing] = useState(false);
  const [publicationStats, setPublicationStats] =
    useState<MindSpacePublicationStats | null>(null);
  const [deletingPage, setDeletingPage] = useState(false);
  const [deletePreviewOpen, setDeletePreviewOpen] = useState(false);
  const [deletePreview, setDeletePreview] = useState<MindSpacePageDeletePreview | null>(null);
  const [deletePreviewLoading, setDeletePreviewLoading] = useState(false);
  const [sharePayload, setSharePayload] = useState<SharePayload | null>(null);
  const [previewFrame, setPreviewFrame] = useState<HTMLIFrameElement | null>(null);
  const [isExportingImage, setIsExportingImage] = useState(false);
  const [exportFeedback, setExportFeedback] = useState<string | null>(null);
  const [plazaOpen, setPlazaOpen] = useState(false);
  const [plazaCategories, setPlazaCategories] = useState<PlazaCategory[]>([]);
  const [plazaCategoryId, setPlazaCategoryId] = useState('');
  const [plazaTags, setPlazaTags] = useState('');
  const [plazaCoverUrl, setPlazaCoverUrl] = useState('');
  const [plazaAllowComment, setPlazaAllowComment] = useState(true);
  const [plazaSubmitting, setPlazaSubmitting] = useState(false);
  const [plazaPost, setPlazaPost] = useState<PlazaPostBrief | null>(null);
  const [pushToPlaza, setPushToPlaza] = useState(false);
  const [fixNotice, setFixNotice] = useState<MindSpaceRedactionChange[] | null>(null);
  const [publishSuccess, setPublishSuccess] = useState<{
    publication: MindSpacePublication;
    plazaPost: PlazaPostBrief | null;
    pageTitle: string;
    pushedToPlaza: boolean;
  } | null>(null);

  const applyPageRecord = useCallback(
    (next: MindSpacePage, options?: { recordHistory?: boolean }) => {
      setPage(next);
      replaceDraft(
        {
          title: next.title,
          summary: next.summary,
          content: next.content ?? '',
        },
        { recordHistory: options?.recordHistory },
      );
      setTemplateId(next.templateId);
    },
    [replaceDraft],
  );

  const load = async () => {
    setLoading(true);
    setError(null);
    try {
      const next = await getMindSpacePage(pageId);
      setPage(next);
      resetDraft({
        title: next.title,
        summary: next.summary,
        content: next.content ?? '',
      });
      setPreviewContent(next.content ?? '');
      setPreviewRefreshPending(false);
      setPreviewKey((value) => value + 1);
      setTemplateId(next.templateId);
      setUrlSlug(next.publication?.urlSlug ?? slugFromTitle(next.title, next.id));
      setAccessMode(next.publication?.accessMode ?? 'public');
      setAccessPassword('');
      setExpiresAt(
        next.publication?.expiresAt
          ? localDateTimeValue(next.publication.expiresAt)
          : '',
      );
      setPublishCheck(null);
      setPublicationStats(
        next.publication
          ? await getMindSpacePublicationStats(next.publication.id).catch(() => null)
          : null,
      );
    } catch (err) {
      setError(err instanceof Error ? err.message : '页面加载失败');
    } finally {
      setLoading(false);
    }
  };

  const runPublishCheck = async (
    pageOverride?: MindSpacePage,
    options?: { managePublishing?: boolean },
  ) => {
    const targetPage = pageOverride ?? page;
    if (!targetPage) return;
    const managePublishing = options?.managePublishing ?? true;
    if (managePublishing) setPublishing(true);
    setError(null);
    try {
      setPublishCheck(
        await checkMindSpacePagePublication(targetPage.id, {
          pageVersionId: targetPage.currentVersionId,
          accessMode,
          urlSlug,
          password: accessPassword || undefined,
          expiresAt: expiresAt ? new Date(expiresAt).getTime() : null,
        }),
      );
    } catch (err) {
      setPublishCheck(null);
      setError(err instanceof Error ? err.message : '发布检查失败');
    } finally {
      if (managePublishing) setPublishing(false);
    }
  };

  const ensurePlazaCategories = async () => {
    if (plazaCategories.length > 0) return plazaCategories;
    const categories = await listPlazaCategories();
    setPlazaCategories(categories);
    if (!plazaCategoryId && categories[0]) {
      setPlazaCategoryId(categories[0].id);
    }
    return categories;
  };

  const publishToPlazaWithDefaults = async (publicationId: string) => {
    const categories = await ensurePlazaCategories();
    const categoryId = plazaCategoryId || categories[0]?.id;
    if (!categoryId) {
      throw new Error('暂无广场分类，无法推送到 Plaza');
    }
    const tags = plazaTags
      .split(/[,，]/)
      .map((item) => item.trim())
      .filter(Boolean)
      .slice(0, 5);
    const post = await publishPageToPlaza({
      publicationId,
      categoryId,
      tags,
      coverUrl: plazaCoverUrl.trim(),
      allowComment: plazaAllowComment,
    });
    setPlazaPost(post);
    return post;
  };

  const publish = async () => {
    if (!page || !publishCheck?.allowed) return;
    setPublishing(true);
    setError(null);
    try {
      const publication = await publishMindSpacePage(page.id, {
        pageVersionId: page.currentVersionId,
        accessMode,
        urlSlug: publishCheck.urlSlug,
        acknowledgedFindingIds: publishCheck.findings.map((finding) => finding.id),
        password: accessPassword || undefined,
        expiresAt: expiresAt ? new Date(expiresAt).getTime() : null,
      });
      let nextPlazaPost: PlazaPostBrief | null = plazaPost;
      if (pushToPlaza) {
        nextPlazaPost = await publishToPlazaWithDefaults(publication.id);
      }
      setPublishOpen(false);
      setFullscreenPreviewOpen(false);
      onFullscreenPreviewChange?.(false);
      setPublishSuccess({
        publication,
        plazaPost: nextPlazaPost,
        pageTitle: title || page.title,
        pushedToPlaza: pushToPlaza,
      });
      await onSaved();
    } catch (err) {
      setError(err instanceof Error ? err.message : pushToPlaza ? '发布或推送到 Plaza 失败' : '发布失败');
    } finally {
      setPublishing(false);
    }
  };

  const offlineFromSuccess = async () => {
    if (!publishSuccess) return;
    setPublishing(true);
    setError(null);
    try {
      await offlineMindSpacePublication(publishSuccess.publication.id);
      await onSaved();
      onBack();
    } catch (err) {
      setError(err instanceof Error ? err.message : '下线失败');
    } finally {
      setPublishing(false);
    }
  };

  const offline = async () => {
    if (!page?.publication) return;
    setPublishing(true);
    setError(null);
    try {
      await offlineMindSpacePublication(page.publication.id);
      setPlazaPost(null);
      await onSaved();
      await load();
    } catch (err) {
      setError(err instanceof Error ? err.message : '下线失败');
    } finally {
      setPublishing(false);
    }
  };

  const openPlazaPanel = async () => {
    setPlazaOpen(true);
    setError(null);
    try {
      await ensurePlazaCategories();
    } catch (err) {
      setError(err instanceof Error ? err.message : '加载广场分类失败');
    }
  };

  const submitPlaza = async () => {
    if (!page?.publication || !plazaCategoryId) return;
    setPlazaSubmitting(true);
    setError(null);
    try {
      await publishToPlazaWithDefaults(page.publication.id);
      setPlazaOpen(false);
    } catch (err) {
      setError(err instanceof Error ? err.message : '发布到广场失败');
    } finally {
      setPlazaSubmitting(false);
    }
  };

  const openDeleteDialog = async () => {
    if (!page) return;
    setDeletePreviewOpen(true);
    setDeletePreviewLoading(true);
    setDeletePreview(null);
    setError(null);
    try {
      setDeletePreview(await getMindSpacePageDeletePreview(page.id));
    } catch (err) {
      setDeletePreviewOpen(false);
      setError(err instanceof Error ? err.message : '无法加载删除预览');
    } finally {
      setDeletePreviewLoading(false);
    }
  };

  const closeDeleteDialog = () => {
    if (deletingPage) return;
    setDeletePreviewOpen(false);
    setDeletePreview(null);
  };

  const confirmDeletePage = async () => {
    if (!page || !deletePreview) return;
    setDeletingPage(true);
    setError(null);
    try {
      const result = await deleteMindSpacePage(page.id);
      setDeletePreviewOpen(false);
      setDeletePreview(null);
      await onSaved({ quota: result.quota, freedBytes: result.freedBytes });
      onBack();
    } catch (err) {
      setError(err instanceof Error ? err.message : '删除页面失败');
    } finally {
      setDeletingPage(false);
    }
  };

  const applySuggestedSlug = async (slug: string) => {
    setUrlSlug(slug);
    setPublishCheck(null);
    setFixNotice(null);
    if (!page) return;
    setPublishing(true);
    setError(null);
    try {
      setPublishCheck(
        await checkMindSpacePagePublication(page.id, {
          pageVersionId: page.currentVersionId,
          accessMode,
          urlSlug: slug,
          password: accessPassword || undefined,
          expiresAt: expiresAt ? new Date(expiresAt).getTime() : null,
        }),
      );
    } catch (err) {
      setPublishCheck(null);
      setError(err instanceof Error ? err.message : '发布检查失败');
    } finally {
      setPublishing(false);
    }
  };

  const publishBlockedBySlug = Boolean(publishCheck && !publishCheck.slugAvailable);
  const publishBlockedBySecurity = Boolean(
    publishCheck && publishCheck.findings.some((finding) => finding.blocking),
  );
  const publishWarningFindings =
    publishCheck?.findings.filter((finding) => !finding.blocking) ?? [];

  const triggerChangeHighlight = useCallback((previous: PageDraftSnapshot) => {
    changeHighlightRevisionRef.current += 1;
    setChangeHighlight({
      revision: changeHighlightRevisionRef.current,
      previousTitle: previous.title,
      previousContent: previous.content,
    });
  }, []);

  const markPreviewRefreshPending = useCallback(() => {
    setPreviewRefreshPending(true);
  }, []);

  const handleManualPreviewRefresh = useCallback((nextContent?: string) => {
    const html = nextContent ?? content;
    setPreviewContent(html);
    setPreviewRefreshPending(false);
    setPreviewKey((value) => value + 1);
  }, [content]);

  const syncPreviewAfterHistory = useCallback(
    (snapshot: PageDraftSnapshot) => {
      if (previewRefreshPending) return;
      setPreviewContent(snapshot.content);
      setPreviewKey((value) => value + 1);
    },
    [previewRefreshPending],
  );

  const handlePreviewContentChange = useCallback(
    (html: string) => {
      setPreviewContent(html);
      replaceDraft({ ...draft, content: html }, { recordHistory: true });
    },
    [draft, replaceDraft],
  );

  const refreshFromServer = useCallback(async () => {
    const currentPage = page;
    if (!currentPage) return;
    try {
      const next = await getMindSpacePage(pageId);
      const serverChanged =
        next.versionNo !== currentPage.versionNo || next.updatedAt !== currentPage.updatedAt;
      if (!serverChanged) return;

      const draftChanged =
        next.title !== title ||
        next.summary !== summary ||
        (next.content ?? '') !== content;

      if (draftChanged) {
        triggerChangeHighlight({ title, summary, content });
      }
      applyPageRecord(next, { recordHistory: true });
      if (draftChanged) {
        markPreviewRefreshPending();
      }
    } catch (err) {
      setError(err instanceof Error ? err.message : '页面刷新失败');
    }
  }, [applyPageRecord, content, markPreviewRefreshPending, page, pageId, summary, title, triggerChangeHighlight]);

  const applyOneClickFix = async () => {
    if (!page) return;
    setPublishing(true);
    setError(null);
    setFixNotice(null);
    try {
      let result;
      try {
        result = await fixMindSpacePagePublication(page.id, {
          pageVersionId: page.currentVersionId,
          expectedVersion: page.versionNo,
          title,
          summary,
          content,
        });
      } catch {
        result = await redactMindSpacePage(page.id, {
          pageVersionId: page.currentVersionId,
          expectedVersion: page.versionNo,
          title,
          summary,
          content,
        });
      }
      const updatedPage = result.page;
      applyPageRecord(updatedPage, { recordHistory: true });
      setFixNotice(result.changes);
      await runPublishCheck(updatedPage, { managePublishing: false });
    } catch (err) {
      setFixNotice(null);
      setError(err instanceof Error ? err.message : '一键修复失败');
    } finally {
      setPublishing(false);
    }
  };

  useEffect(() => {
    setPublishSuccess(null);
    void load();
  }, [pageId]);

  useEffect(() => {
    if (!refreshTrigger) return;
    void refreshFromServer();
  }, [refreshTrigger, refreshFromServer]);

  useEffect(() => {
    if (autoOpenPlaza && page?.publication && !plazaOpen) {
      void openPlazaPanel();
    }
  }, [autoOpenPlaza, page]);

  useEffect(() => {
    const handleKeyDown = (event: KeyboardEvent) => {
      const mod = event.metaKey || event.ctrlKey;
      if (!mod || event.altKey) return;
      const target = event.target;
      if (
        target instanceof HTMLInputElement ||
        target instanceof HTMLTextAreaElement ||
        target instanceof HTMLSelectElement
      ) {
        return;
      }
      if (event.key.toLowerCase() === 'z' && event.shiftKey) {
        const next = redo();
        if (next) {
          syncPreviewAfterHistory(next);
          event.preventDefault();
        }
        return;
      }
      if (event.key.toLowerCase() === 'z') {
        const previous = undo();
        if (previous) {
          syncPreviewAfterHistory(previous);
          event.preventDefault();
        }
      }
    };
    window.addEventListener('keydown', handleKeyDown);
    return () => window.removeEventListener('keydown', handleKeyDown);
  }, [redo, syncPreviewAfterHistory, undo]);

  useEffect(() => {
    if (!page || !onContextUpdate) return;
    onContextUpdate({ page, title, summary, content });
  }, [page, title, summary, content, onContextUpdate]);

  const openFullscreenPreview = () => {
    if (!page || page.contentFormat !== 'html' || !content.trim()) return;
    setPreviewContent(content);
    setPreviewRefreshPending(false);
    setPreviewKey((value) => value + 1);
    setFullscreenPreviewOpen(true);
    onFullscreenPreviewChange?.(true);
  };

  const closeFullscreenPreview = () => {
    setFullscreenPreviewOpen(false);
    onFullscreenPreviewChange?.(false);
    setPreviewKey((value) => value + 1);
    setPreviewRefreshPending(false);
  };

  const handleOpenShareSheet = () => {
    if (!page) return;
    const shareUrl = page.publication ? resolvePublicPageUrl(page.publication.publicUrl) : undefined;
    setSharePayload(buildPageSharePayload(page, shareUrl));
    setExportFeedback(null);
  };

  const handleExportPageImage = async () => {
    if (!page) return;
    setIsExportingImage(true);
    setExportFeedback(null);
    try {
      let dataUrl = '';
      let usedFallback = false;
      if (previewFrame) {
        try {
          dataUrl = await exportIframeToPng(previewFrame);
        } catch {
          usedFallback = true;
        }
      } else {
        usedFallback = true;
      }
      if (!dataUrl) {
        dataUrl = await fetchPageThumbnailAsDataUrl(page.id);
      }
      downloadBlobAsFile(dataUrl, buildExportFilename(page.id, page.title || 'page'));
      setExportFeedback(
        usedFallback
          ? '截图暂不可用，已使用页面封面图保存'
          : '已导出当前页面图片',
      );
      setTimeout(() => setExportFeedback(null), 2200);
    } catch (err) {
      setExportFeedback(err instanceof Error ? err.message : '导出图片失败');
    } finally {
      setIsExportingImage(false);
    }
  };

  const handlePreviewUndo = () => {
    const previous = undo();
    if (!previous) return false;
    if (previewRefreshPending) return true;
    handleManualPreviewRefresh(previous.content);
    return true;
  };

  const handlePreviewRedo = () => {
    const next = redo();
    if (!next) return false;
    if (previewRefreshPending) return true;
    handleManualPreviewRefresh(next.content);
    return true;
  };

  useEffect(() => {
    return () => {
      onFullscreenPreviewChange?.(false);
    };
  }, [onFullscreenPreviewChange]);

  const publicPageUrl = page?.publication
    ? resolvePublicPageUrl(page.publication.publicUrl)
    : '';

  if (loading) return <div className="mindspace-state">正在加载页面详情…</div>;
  if (!page) {
    return (
      <div className="mindspace-state mindspace-error">
        <span>{error ?? '页面不存在'}</span>
        <button type="button" onClick={onBack}>
          返回
        </button>
      </div>
    );
  }

  if (publishSuccess) {
    return (
      <MindSpacePublishSuccess
        pageTitle={publishSuccess.pageTitle}
        publication={publishSuccess.publication}
        plazaPost={publishSuccess.plazaPost}
        pushedToPlaza={publishSuccess.pushedToPlaza}
        offlineBusy={publishing}
        error={error}
        onOffline={offlineFromSuccess}
        onBack={onBack}
      />
    );
  }

  return (
    <>
    <section className="mindspace-page-detail">
      <div className="mindspace-section-heading">
        <div>
          <button type="button" className="mindspace-inline-back" onClick={onBack}>
            返回页面列表
          </button>
          <p className="mindspace-eyebrow">PAGE DETAIL · V{page.versionNo}</p>
          <h2>{truncateLabel(title || page.title, 80)}</h2>
        </div>
        <div className="mindspace-page-status">
          <span>{STATUS_LABELS[page.status] ?? page.status}</span>
          <strong>{TEMPLATE_LABELS[page.templateId] ?? page.templateId}</strong>
          <button
            type="button"
            onClick={() => void openDeleteDialog()}
            disabled={deletingPage || publishing || deletePreviewLoading}
          >
            删除页面
          </button>
          <button
            type="button"
            className="mindspace-primary"
            onClick={() => setPublishOpen((value) => !value)}
          >
            {page.publication ? '重新发布' : '发布页面'}
          </button>
        </div>
      </div>
      <div className="mindspace-page-floating-actions">
        <button type="button" className="mindspace-page-floating-action" onClick={handleOpenShareSheet}>
          分享
        </button>
        <button
          type="button"
          className="mindspace-page-floating-action is-secondary"
          onClick={() => void handleExportPageImage()}
          disabled={isExportingImage}
        >
          {isExportingImage ? '保存中…' : '保存图片'}
        </button>
      </div>
      {exportFeedback ? (
        <p className="mindspace-page-export-feedback" role="status">
          {exportFeedback}
        </p>
      ) : null}

      {error && !deletePreviewOpen && <div className="mindspace-security-note">{error}</div>}

      <MindSpaceModal
        open={deletePreviewOpen}
        onClose={closeDeleteDialog}
        title="确认删除页面"
        eyebrow="DELETE PAGE"
        className="mindspace-delete-dialog"
        disableClose={deletingPage || deletePreviewLoading}
      >
        {deletePreviewLoading && <div className="mindspace-state">正在分析连带内容…</div>}
        {error && deletePreviewOpen && <div className="mindspace-security-note">{error}</div>}
        {deletePreview && (
          <>
            <p className="mindspace-upload-dialog-desc">
              删除后无法恢复。以下相关内容将一并处理：
            </p>
            <ul className="mindspace-delete-summary">
              {deletePreview.summaryLines.map((line) => (
                <li key={line}>{line}</li>
              ))}
            </ul>
            {deletePreview.onlinePublication && (
              <a
                className="mindspace-delete-public-url"
                href={resolvePublicPageUrl(deletePreview.onlinePublication.publicUrl)}
                target="_blank"
                rel="noreferrer"
              >
                {resolvePublicPageUrl(deletePreview.onlinePublication.publicUrl)}
              </a>
            )}
            {deletePreview.linkedAssets.length > 0 && (
              <div className="mindspace-delete-assets">
                {deletePreview.linkedAssets.map((asset) => (
                  <div key={asset.id}>
                    <strong>{asset.displayName}</strong>
                    <span>{asset.kind === 'bundle' ? '发布快照' : '页面内容'}</span>
                  </div>
                ))}
              </div>
            )}
            <div className="mindspace-page-editor-actions">
              <button type="button" onClick={closeDeleteDialog} disabled={deletingPage}>
                取消
              </button>
              <button
                type="button"
                className="mindspace-delete-confirm"
                onClick={() => void confirmDeletePage()}
                disabled={deletingPage}
              >
                {deletingPage ? '删除中…' : '确认删除'}
              </button>
            </div>
          </>
        )}
      </MindSpaceModal>

      {page.publication && (
        <div className="mindspace-publication-live">
          <div>
            <span>{ACCESS_MODE_LABELS[page.publication.accessMode]}</span>
            <a
              className="mindspace-publication-url"
              href={publicPageUrl}
              target="_blank"
              rel="noreferrer"
            >
              {publicPageUrl}
            </a>
            <small>已访问 {page.publication.viewCount} 次，线上版本保持不可变。</small>
            {publicationStats && publicationStats.totalViews > 0 && (
              <small>
                设备：
                {publicationStats.devices
                  .map((item) => `${item.deviceType} ${item.views}`)
                  .join(' · ')}
                {' · '}来源：
                {publicationStats.sources
                  .map((item) => `${item.source} ${item.views}`)
                  .join(' · ')}
              </small>
            )}
          </div>
          <div>
            <a href={publicPageUrl} target="_blank" rel="noreferrer">
              打开页面
            </a>
            {page.publication.status === 'online' ? (
              <button type="button" onClick={() => void openPlazaPanel()} disabled={publishing}>
                发布到广场
              </button>
            ) : null}
            <button type="button" onClick={() => void offline()} disabled={publishing}>
              立即下线
            </button>
          </div>
        </div>
      )}

      {plazaPost ? (
        <div className="mindspace-publication-live">
          <div>
            <span>Plaza 广场</span>
            <a
              className="mindspace-publication-url"
              href={resolvePlazaPostUrl(plazaPost.id)}
              target="_blank"
              rel="noreferrer"
            >
              {resolvePlazaPostUrl(plazaPost.id)}
            </a>
            <small>
              状态：{plazaPost.status === 'published' ? '已公开' : '待审核'}。审核通过后会在广场首页展示。
            </small>
          </div>
        </div>
      ) : null}

      {plazaOpen ? (
        <section className="mindspace-publish-panel">
          <div>
            <p className="mindspace-eyebrow">PLAZA</p>
            <h3>发布到发现广场</h3>
          </div>
          <label>
            广场分类
            <select
              value={plazaCategoryId}
              onChange={(event) => setPlazaCategoryId(event.target.value)}
            >
              {plazaCategories.map((category) => (
                <option value={category.id} key={category.id}>
                  {category.icon} {category.name}
                </option>
              ))}
            </select>
          </label>
          <label>
            标签（可选，逗号分隔，最多 5 个）
            <input
              value={plazaTags}
              onChange={(event) => setPlazaTags(event.target.value)}
              placeholder="复盘, 季度报告"
            />
          </label>
          <label>
            封面图 URL（可选，留空使用默认）
            <input
              value={plazaCoverUrl}
              onChange={(event) => setPlazaCoverUrl(event.target.value)}
              placeholder="https://..."
            />
          </label>
          <label className="mindspace-checkbox-row">
            <input
              type="checkbox"
              checked={plazaAllowComment}
              onChange={(event) => setPlazaAllowComment(event.target.checked)}
            />
            允许评论
          </label>
          <div className="mindspace-page-editor-actions">
            <span>发布后默认进入审核队列；开发环境可配置自动过审。</span>
            <button type="button" onClick={() => setPlazaOpen(false)} disabled={plazaSubmitting}>
              取消
            </button>
            <button
              type="button"
              className="mindspace-primary"
              onClick={() => void submitPlaza()}
              disabled={plazaSubmitting || !plazaCategoryId}
            >
              {plazaSubmitting ? '提交中…' : '确认发布到广场'}
            </button>
          </div>
        </section>
      ) : null}

      {publishOpen && (
        <section className="mindspace-publish-panel">
          <div>
            <p className="mindspace-eyebrow">PUBLISH SAFELY</p>
            <h3>发布设置与安全检查</h3>
          </div>
          <label>
            页面地址
            <div className="mindspace-slug-field">
              <span>/u/我的主页/pages/</span>
              <input
                value={urlSlug}
                maxLength={64}
                onChange={(event) => {
                  setUrlSlug(event.target.value.toLowerCase());
                  setPublishCheck(null);
                  setFixNotice(null);
                }}
              />
            </div>
          </label>
          <label>
            访问方式
            <select
              value={accessMode}
              onChange={(event) => {
                setAccessMode(event.target.value as AccessMode);
                setPublishCheck(null);
                setFixNotice(null);
              }}
            >
              {Object.entries(ACCESS_MODE_LABELS).map(([value, label]) => (
                <option value={value} key={value}>
                  {label}
                </option>
              ))}
            </select>
          </label>
          {accessMode === 'password' && (
            <label>
              访问密码
              <input
                type="password"
                value={accessPassword}
                minLength={8}
                maxLength={128}
                autoComplete="new-password"
                onChange={(event) => {
                  setAccessPassword(event.target.value);
                  setPublishCheck(null);
                  setFixNotice(null);
                }}
              />
            </label>
          )}
          {accessMode === 'time_limited' && (
            <label>
              访问截止时间
              <input
                type="datetime-local"
                value={expiresAt}
                min={localDateTimeValue(Date.now() + 60_000)}
                onChange={(event) => {
                  setExpiresAt(event.target.value);
                  setPublishCheck(null);
                  setFixNotice(null);
                }}
              />
            </label>
          )}
          {fixNotice && fixNotice.length > 0 ? (
            <div className="mindspace-fix-notice">
              <strong>
                已修复 {fixNotice.reduce((total, change) => total + change.count, 0)} 处风险内容
              </strong>
              <ul>
                {fixNotice.map((change) => (
                  <li key={`${change.field}-${change.type}`}>
                    {change.fieldLabel}：{change.label} {change.count} 处
                  </li>
                ))}
              </ul>
              <p>页面内容已就地更新，可直接点击「确认发布」。</p>
            </div>
          ) : null}
          {publishCheck && (
            <div className={`mindspace-publish-check is-${publishCheck.status}`}>
              <strong>
                {publishCheck.allowed
                  ? '可以发布'
                  : publishBlockedBySlug && !publishBlockedBySecurity
                    ? '请更换页面地址'
                    : '当前不能发布'}{' '}
                · 风险等级 {publishCheck.riskLevel}
              </strong>
              {!publishCheck.slugAvailable && (
                <p>
                  页面地址 <code>/u/我的主页/pages/{publishCheck.urlSlug}</code> 已被其他页面使用
                  {publishCheck.slugConflict
                    ? `：《${publishCheck.slugConflict.title}》`
                    : ''}
                  。中文标题常会生成相同地址，请改用唯一地址。
                </p>
              )}
              {publishCheck.suggestedUrlSlug && !publishCheck.slugAvailable ? (
                <p className="mindspace-publish-slug-suggest">
                  推荐地址：
                  <button
                    type="button"
                    onClick={() => void applySuggestedSlug(publishCheck.suggestedUrlSlug!)}
                    disabled={publishing}
                  >
                    /u/我的主页/pages/{publishCheck.suggestedUrlSlug}
                  </button>
                </p>
              ) : null}
              {publishCheck.findings.length === 0 && publishCheck.slugAvailable && (
                <p>未发现敏感信息或外部链接。</p>
              )}
              {publishCheck.findings
                .filter((finding) => finding.blocking)
                .map((finding) => (
                  <p key={finding.id}>
                    阻断：{finding.label ?? finding.type} 共 {finding.occurrenceCount} 处（
                    {finding.sampleMasked}）
                  </p>
                ))}
              {publishWarningFindings.length > 0 && (
                <p className="mindspace-publish-warning-note">
                  以下提醒不会阻止发布，确认发布时会自动记录：
                </p>
              )}
              {publishWarningFindings.map((finding) => (
                <p key={finding.id}>
                  提醒：{finding.label ?? finding.type} 共 {finding.occurrenceCount} 处（
                  {finding.sampleMasked}）
                </p>
              ))}
            </div>
          )}
          <div className="mindspace-page-editor-actions">
            <span>
              {pushToPlaza
                ? '确认发布后会同步推送到 Plaza 发现广场。'
                : '发布会创建独立快照，后续修改草稿不会影响线上页面。'}
            </span>
            <div className="mindspace-publish-action-group">
              <button
                type="button"
                onClick={() => {
                  setFixNotice(null);
                  void runPublishCheck();
                }}
                disabled={publishing}
              >
                {publishing ? '检查中…' : '运行安全检查'}
              </button>
              {publishBlockedBySecurity ? (
                <button type="button" onClick={() => void applyOneClickFix()} disabled={publishing}>
                  {publishing ? '修复中…' : '一键修复'}
                </button>
              ) : null}
              <label className="mindspace-publish-plaza-toggle">
                <input
                  type="checkbox"
                  checked={pushToPlaza}
                  disabled={publishing}
                  onChange={(event) => {
                    const checked = event.target.checked;
                    setPushToPlaza(checked);
                    if (checked) {
                      void ensurePlazaCategories().catch((err) => {
                        setError(err instanceof Error ? err.message : '加载广场分类失败');
                        setPushToPlaza(false);
                      });
                    }
                  }}
                />
                推送 Plaza
              </label>
              <button
                type="button"
                className="mindspace-primary"
                onClick={() => void publish()}
                disabled={publishing || !publishCheck?.allowed}
              >
                {publishing ? (pushToPlaza ? '发布并推送…' : '发布中…') : '确认发布'}
              </button>
            </div>
          </div>
        </section>
      )}

      <div
        className={`mindspace-page-layout${page.contentFormat === 'html' ? ' is-html-page' : ''}`}
      >
        <div className="mindspace-page-editor">
          <label>
            标题
            <input
              value={title}
              maxLength={255}
              onChange={(event) => updateDraft({ ...draft, title: event.target.value })}
            />
          </label>
          <label>
            摘要
            <textarea
              value={summary}
              rows={4}
              maxLength={1000}
              onChange={(event) => updateDraft({ ...draft, summary: event.target.value })}
            />
          </label>
          {page.contentFormat !== 'html' && (
            <label>
              模板
              <select value={templateId} onChange={(event) => setTemplateId(event.target.value)}>
                {Object.entries(TEMPLATE_LABELS)
                  .filter(([value]) => value !== 'static-html')
                  .map(([value, label]) => (
                    <option value={value} key={value}>
                      {label}
                    </option>
                  ))}
              </select>
            </label>
          )}
          {page.contentFormat !== 'html' && (
            <label>
              页面内容
              <textarea
                className="mindspace-page-content-input"
                value={content}
                rows={18}
                onChange={(event) => updateDraft({ ...draft, content: event.target.value })}
              />
            </label>
          )}
        </div>

        <div className="mindspace-page-preview">
          <div className="mindspace-page-preview-bar">
            <span>{page.contentFormat === 'html' ? '页面预览编辑' : '安全预览'}</span>
            <div className="mindspace-page-preview-actions">
              <button type="button" onClick={() => {
                const previous = undo();
                if (previous) syncPreviewAfterHistory(previous);
              }} disabled={!canUndo} title="撤销 (⌘Z)">
                撤销
              </button>
              <button type="button" onClick={() => {
                const next = redo();
                if (next) syncPreviewAfterHistory(next);
              }} disabled={!canRedo} title="重做 (⌘⇧Z)">
                重做
              </button>
              <button
                type="button"
                onClick={openFullscreenPreview}
                disabled={page.contentFormat !== 'html' || !content.trim()}
                title={page.contentFormat === 'html' ? '进入沉浸式可视化编辑' : '仅 HTML 页面支持全屏编辑'}
              >
                全屏预览编辑
              </button>
              <button
                type="button"
                className={previewRefreshPending ? 'is-refresh-pending' : undefined}
                onClick={handleManualPreviewRefresh}
                title={previewRefreshPending ? '草稿已有新内容，点击刷新预览' : '将当前草稿同步到预览'}
              >
                刷新预览{previewRefreshPending ? ' · 有新修改' : ''}
              </button>
            </div>
          </div>
          {page.contentFormat === 'html' ? (
            <MindSpacePagePreviewPanel
              pageId={page.id}
              title={title}
              summary={summary}
              content={previewContent}
              onFrameReady={setPreviewFrame}
              reloadKey={previewKey}
              onContentChange={handlePreviewContentChange}
            />
          ) : (
            <MindSpacePageDraftPreviewFrame
              pageId={page.id}
              title={title}
              summary={summary}
              content={content}
              templateId={templateId}
              onFrameReady={setPreviewFrame}
              reloadKey={previewKey}
              minHeight={680}
              maxHeight={Number.POSITIVE_INFINITY}
            />
          )}
          {page.contentFormat === 'html' && (
            <details className="mindspace-html-source-editor">
              <summary>编辑 HTML 源码</summary>
              <textarea
                className="mindspace-page-content-input"
                value={content}
                rows={22}
                onChange={(event) => {
                  const nextContent = event.target.value;
                  updateDraft({ ...draft, content: nextContent });
                  if (!previewRefreshPending) {
                    setPreviewContent(nextContent);
                  }
                }}
              />
            </details>
          )}
        </div>
      </div>

      <div className="mindspace-page-meta">
        <div>
          <span>来源会话</span>
          <strong>{page.sourceSessionId ?? '手动创建'}</strong>
        </div>
        <div>
          <span>当前版本</span>
          <strong>v{page.versionNo}</strong>
        </div>
        <div>
          <span>更新时间</span>
          <strong>{new Date(page.updatedAt).toLocaleString()}</strong>
        </div>
      </div>

      <section className="mindspace-version-history">
        <p className="mindspace-eyebrow">VERSION HISTORY</p>
        <h3>页面版本</h3>
        {(page.versions ?? []).map((version) => (
          <div className="mindspace-version-row" key={version.id}>
            <strong>v{version.versionNo}</strong>
            <span>{version.changeNote || '保存页面草稿'}</span>
            <time>{new Date(version.createdAt).toLocaleString()}</time>
          </div>
        ))}
      </section>
    </section>
    {sharePayload ? <ShareSheet payload={sharePayload} onClose={() => setSharePayload(null)} /> : null}

      {fullscreenPreviewOpen && page && page.contentFormat === 'html' ? (
        <MindSpacePageFullscreenPreview
          pageTitle={title || page.title}
          title={title}
          content={content}
          reloadKey={previewKey}
          changeHighlight={changeHighlight}
          canUndo={canUndo}
          canRedo={canRedo}
          onUndo={handlePreviewUndo}
          onRedo={handlePreviewRedo}
          onClose={closeFullscreenPreview}
          onRefresh={() => handleManualPreviewRefresh()}
          refreshPending={previewRefreshPending}
          onContentChange={handlePreviewContentChange}
        />
      ) : null}
    </>
  );
}
