﻿import { Loader2 } from 'lucide-react';
import { AnimatePresence, motion } from 'motion/react';
import {
  lazy,
  Suspense,
  useCallback,
  useEffect,
  useMemo,
  useRef,
  useState,
} from 'react';

import type { PublicUserSummary } from '../../../packages/shared/src/contracts/auth';
import type {
  BigFishRuntimeSnapshotResponse,
  BigFishSessionSnapshotResponse,
  ExecuteBigFishActionRequest,
  SendBigFishMessageRequest,
  SubmitBigFishInputRequest,
} from '../../../packages/shared/src/contracts/bigFish';
import type { BigFishWorkSummary } from '../../../packages/shared/src/contracts/bigFishWorkSummary';
import type {
  PuzzleAgentActionRequest,
  PuzzleAgentOperationRecord,
} from '../../../packages/shared/src/contracts/puzzleAgentActions';
import type {
  PuzzleAgentSessionSnapshot,
  SendPuzzleAgentMessageRequest,
} from '../../../packages/shared/src/contracts/puzzleAgentSession';
import type { PuzzleRunSnapshot } from '../../../packages/shared/src/contracts/puzzleRuntimeSession';
import type { PuzzleWorkSummary } from '../../../packages/shared/src/contracts/puzzleWorkSummary';
import type {
  CustomWorldGalleryCard,
  CustomWorldLibraryEntry,
} from '../../../packages/shared/src/contracts/runtime';
import { buildCustomWorldPlayableCharacters } from '../../data/characterPresets';
import {
  getPublicAuthUserByCode,
  getPublicAuthUserById,
} from '../../services/authService';
import {
  createBigFishCreationSession,
  executeBigFishCreationAction,
  getBigFishCreationSession,
  streamBigFishCreationMessage,
} from '../../services/big-fish-creation';
import {
  startBigFishRuntimeRun,
  submitBigFishRuntimeInput,
} from '../../services/big-fish-runtime';
import {
  deleteBigFishWork,
  listBigFishWorks,
} from '../../services/big-fish-works';
import { readCustomWorldAgentUiState } from '../../services/customWorldAgentUiState';
import {
  buildBigFishGenerationAnchorEntries,
  buildMiniGameDraftGenerationProgress,
  buildPuzzleGenerationAnchorEntries,
  createMiniGameDraftGenerationState,
  type MiniGameDraftGenerationState,
} from '../../services/miniGameDraftGenerationProgress';
import { getPlatformProfileDashboard } from '../../services/platform-entry';
import {
  createPuzzleAgentSession,
  executePuzzleAgentAction,
  getPuzzleAgentSession,
  streamPuzzleAgentMessage,
} from '../../services/puzzle-agent';
import { getPuzzleGalleryDetail } from '../../services/puzzle-gallery';
import { advanceLocalPuzzleNextLevel } from '../../services/puzzle-runtime';
import {
  dragLocalPuzzlePiece,
  startLocalPuzzleRun,
  swapLocalPuzzlePieces,
} from '../../services/puzzle-runtime/puzzleLocalRuntime';
import { deletePuzzleWork, listPuzzleWorks } from '../../services/puzzle-works';
import { deleteRpgCreationAgentSession } from '../../services/rpg-creation';
import { rpgCreationPreviewAdapter } from '../../services/rpg-creation/rpgCreationPreviewAdapter';
import { deleteRpgEntryWorldProfile } from '../../services/rpg-entry';
import { getRpgEntryWorldGalleryDetailByCode } from '../../services/rpg-entry/rpgEntryLibraryClient';
import type { CustomWorldProfile } from '../../types';
import { useAuthUi } from '../auth/AuthUiContext';
import { CustomWorldCreationHub } from '../custom-world-home/CustomWorldCreationHub';
import { PuzzleAgentWorkspace } from '../puzzle-agent/PuzzleAgentWorkspace';
import { PuzzleGalleryDetailView } from '../puzzle-gallery/PuzzleGalleryDetailView';
import { PuzzleResultView } from '../puzzle-result/PuzzleResultView';
import { PuzzleRuntimeShell } from '../puzzle-runtime/PuzzleRuntimeShell';
import { useRpgCreationAgentOperationPolling } from '../rpg-entry/useRpgCreationAgentOperationPolling';
import { useRpgCreationEnterWorld } from '../rpg-entry/useRpgCreationEnterWorld';
import { useRpgCreationResultAutosave } from '../rpg-entry/useRpgCreationResultAutosave';
import { useRpgCreationSessionController } from '../rpg-entry/useRpgCreationSessionController';
import { PlatformEntryCreationTypeModal } from './PlatformEntryCreationTypeModal';
import type { PlatformCreationTypeId } from './platformEntryCreationTypes';
import { PlatformEntryHomeView } from './PlatformEntryHomeView';
import {
  buildCreationHubFallbackItems,
  normalizeAgentBackedProfile,
  resolveRpgCreationErrorMessage,
} from './platformEntryShared';
import type { PlatformEntryFlowShellProps } from './platformEntryTypes';
import { PlatformEntryWorldDetailView } from './PlatformEntryWorldDetailView';
import { usePlatformEntryBootstrap } from './usePlatformEntryBootstrap';
import { usePlatformEntryLibraryDetail } from './usePlatformEntryLibraryDetail';
import { usePlatformEntryNavigation } from './usePlatformEntryNavigation';

type AgentResultPublishGateView = {
  blockers: string[];
  publishReady: boolean;
};

type AgentResultBlockerView = {
  code?: string;
  message: string;
};

const AGENT_RESULT_STRUCTURAL_BLOCKER_CODES = new Set([
  'publish_missing_world_hook',
  'publish_missing_player_premise',
  'publish_missing_core_conflict',
  'publish_missing_main_chapter',
  'publish_missing_first_act',
]);

function readProfileTextField(
  profile: CustomWorldProfile | null,
  paths: string[],
) {
  for (const path of paths) {
    let current: unknown = profile;
    for (const segment of path.split('.')) {
      if (!current || typeof current !== 'object') {
        current = null;
        break;
      }
      current = (current as Record<string, unknown>)[segment];
    }
    if (typeof current === 'string' && current.trim()) {
      return current.trim();
    }
  }
  return null;
}

function hasProfileTextArray(profile: CustomWorldProfile | null, key: string) {
  const value = profile
    ? (profile as unknown as Record<string, unknown>)[key]
    : null;
  return Array.isArray(value)
    ? value.some((entry) => typeof entry === 'string' && entry.trim())
    : false;
}

function hasProfileArray(profile: CustomWorldProfile | null, key: string) {
  const value = profile
    ? (profile as unknown as Record<string, unknown>)[key]
    : null;
  return Array.isArray(value) && value.length > 0;
}

function hasSceneAct(profile: CustomWorldProfile | null) {
  const rawProfile = profile as unknown as Record<string, unknown> | null;
  const chapters =
    rawProfile &&
    (Array.isArray(rawProfile.sceneChapterBlueprints)
      ? rawProfile.sceneChapterBlueprints
      : Array.isArray(rawProfile.sceneChapters)
        ? rawProfile.sceneChapters
        : []);
  return Array.isArray(chapters)
    ? chapters.some((chapter) => {
        const acts =
          chapter && typeof chapter === 'object'
            ? (chapter as Record<string, unknown>).acts
            : null;
        return Array.isArray(acts) && acts.length > 0;
      })
    : false;
}

function isAgentResultStructuralBlockerResolved(
  profile: CustomWorldProfile,
  code: string | undefined,
) {
  if (!code || !AGENT_RESULT_STRUCTURAL_BLOCKER_CODES.has(code)) {
    return false;
  }

  if (code === 'publish_missing_world_hook') {
    return Boolean(
      readProfileTextField(profile, [
        'worldHook',
        'creatorIntent.worldHook',
        'anchorContent.worldPromise.hook',
        'settingText',
      ]),
    );
  }
  if (code === 'publish_missing_player_premise') {
    return Boolean(
      readProfileTextField(profile, [
        'playerPremise',
        'creatorIntent.playerPremise',
        'anchorContent.playerEntryPoint.openingIdentity',
        'anchorContent.playerEntryPoint.openingProblem',
        'anchorContent.playerEntryPoint.entryMotivation',
      ]),
    );
  }
  if (code === 'publish_missing_core_conflict') {
    return hasProfileTextArray(profile, 'coreConflicts');
  }
  if (code === 'publish_missing_main_chapter') {
    return (
      hasProfileArray(profile, 'chapters') ||
      hasProfileArray(profile, 'sceneChapterBlueprints') ||
      hasProfileArray(profile, 'sceneChapters')
    );
  }
  return hasSceneAct(profile);
}

function buildAgentResultPublishGateView(
  profile: CustomWorldProfile | null,
  fallbackBlockers: AgentResultBlockerView[],
  fallbackPublishReady: boolean,
): AgentResultPublishGateView {
  if (!profile) {
    return {
      blockers: fallbackBlockers.map((entry) => entry.message),
      publishReady: fallbackPublishReady,
    };
  }

  const blockers = fallbackBlockers
    .filter(
      (entry) =>
        !isAgentResultStructuralBlockerResolved(profile, entry.code),
    )
    .map((entry) => entry.message);

  return {
    blockers,
    publishReady: blockers.length === 0,
  };
}

const CustomWorldGenerationView = lazy(async () => {
  const module = await import('../CustomWorldGenerationView');
  return {
    default: module.CustomWorldGenerationView,
  };
});

const RpgCreationResultView = lazy(async () => {
  const module = await import('../rpg-creation-result/RpgCreationResultView');
  return {
    default: module.RpgCreationResultView,
  };
});

const CustomWorldAgentWorkspace = lazy(async () => {
  const module = await import(
    '../custom-world-agent/CustomWorldAgentWorkspace'
  );
  return {
    default: module.CustomWorldAgentWorkspace,
  };
});

const BigFishAgentWorkspace = lazy(async () => {
  const module = await import('../big-fish-creation/BigFishAgentWorkspace');
  return {
    default: module.BigFishAgentWorkspace,
  };
});

const BigFishResultView = lazy(async () => {
  const module = await import('../big-fish-result/BigFishResultView');
  return {
    default: module.BigFishResultView,
  };
});

const BigFishRuntimeShell = lazy(async () => {
  const module = await import('../big-fish-runtime/BigFishRuntimeShell');
  return {
    default: module.BigFishRuntimeShell,
  };
});

function LazyPanelFallback({ label }: { label: string }) {
  return (
    <div className="flex h-full min-h-0 items-center justify-center">
      <div className="platform-subpanel rounded-2xl px-5 py-4 text-sm text-[var(--platform-text-base)]">
        {label}
      </div>
    </div>
  );
}

export function PlatformEntryFlowShellImpl({
  selectionStage,
  setSelectionStage,
  hasSavedGame,
  savedSnapshot,
  handleContinueGame,
  handleStartNewGame,
  handleCustomWorldSelect,
}: PlatformEntryFlowShellProps) {
  const authUi = useAuthUi();
  const [showCreationTypeModal, setShowCreationTypeModal] = useState(false);
  const [selectedDetailEntry, setSelectedDetailEntry] =
    useState<CustomWorldLibraryEntry<CustomWorldProfile> | null>(null);
  const [bigFishSession, setBigFishSession] =
    useState<BigFishSessionSnapshotResponse | null>(null);
  const [bigFishWorks, setBigFishWorks] = useState<BigFishWorkSummary[]>([]);
  const [bigFishRun, setBigFishRun] =
    useState<BigFishRuntimeSnapshotResponse | null>(null);
  const [bigFishError, setBigFishError] = useState<string | null>(null);
  const [isBigFishBusy, setIsBigFishBusy] = useState(false);
  const [isBigFishLoadingLibrary, setIsBigFishLoadingLibrary] = useState(false);
  const [bigFishGenerationState, setBigFishGenerationState] =
    useState<MiniGameDraftGenerationState | null>(null);
  const [streamingBigFishReplyText, setStreamingBigFishReplyText] =
    useState('');
  const [isStreamingBigFishReply, setIsStreamingBigFishReply] = useState(false);
  const bigFishInputInFlightRef = useRef(false);
  const [puzzleSession, setPuzzleSession] =
    useState<PuzzleAgentSessionSnapshot | null>(null);
  const [puzzleOperation, setPuzzleOperation] =
    useState<PuzzleAgentOperationRecord | null>(null);
  const [puzzleWorks, setPuzzleWorks] = useState<PuzzleWorkSummary[]>([]);
  const [selectedPuzzleDetail, setSelectedPuzzleDetail] =
    useState<PuzzleWorkSummary | null>(null);
  const [puzzleRun, setPuzzleRun] = useState<PuzzleRunSnapshot | null>(null);
  const [puzzleError, setPuzzleError] = useState<string | null>(null);
  const [isPuzzleBusy, setIsPuzzleBusy] = useState(false);
  const [isPuzzleLoadingLibrary, setIsPuzzleLoadingLibrary] = useState(false);
  const [puzzleGenerationState, setPuzzleGenerationState] =
    useState<MiniGameDraftGenerationState | null>(null);
  const [isPuzzleNextLevelGenerating, setIsPuzzleNextLevelGenerating] =
    useState(false);
  const [isSearchingPublicCode, setIsSearchingPublicCode] = useState(false);
  const [publicSearchError, setPublicSearchError] = useState<string | null>(null);
  const [searchedPublicUser, setSearchedPublicUser] =
    useState<PublicUserSummary | null>(null);
  const [deletingCreationWorkId, setDeletingCreationWorkId] = useState<
    string | null
  >(null);
  const [streamingPuzzleReplyText, setStreamingPuzzleReplyText] = useState('');
  const [isStreamingPuzzleReply, setIsStreamingPuzzleReply] = useState(false);
  const hasInitialAgentSession = Boolean(
    readCustomWorldAgentUiState().activeSessionId,
  );

  const platformBootstrap = usePlatformEntryBootstrap({
    user: authUi?.user,
    canAccessProtectedData: authUi?.canAccessProtectedData,
    getProfileDashboard: getPlatformProfileDashboard,
    handleContinueGame,
    hasInitialAgentSession,
  });
  const entryNavigation = usePlatformEntryNavigation({
    setSelectionStage,
    setSelectedDetailEntry,
  });
  const { setPlatformTab } = platformBootstrap;

  const enterCreateTab = useCallback(() => {
    // 只依赖稳定的 setter，避免把 bootstrap 对象的 render 级引用变化
    // 传导成 Agent session 恢复 effect 的重复触发。
    setPlatformTab('create');
  }, [setPlatformTab]);

  const sessionController = useRpgCreationSessionController({
    userId: authUi?.user?.id,
    openLoginModal: authUi?.openLoginModal,
    selectionStage,
    setSelectionStage,
    enterCreateTab,
    onSessionOpened: () => {
      setShowCreationTypeModal(false);
    },
  });

  useRpgCreationAgentOperationPolling({
    activeAgentSessionId: sessionController.activeAgentSessionId,
    activeAgentOperationId: sessionController.activeAgentOperationId,
    userId: authUi?.user?.id,
    setAgentOperation: sessionController.setAgentOperation,
    persistAgentUiState: sessionController.persistAgentUiState,
    syncAgentSessionSnapshot: sessionController.syncAgentSessionSnapshot,
  });

  const autosaveCoordinator = useRpgCreationResultAutosave({
    selectionStage,
    activeAgentSessionId: sessionController.activeAgentSessionId,
    agentSession: sessionController.agentSession,
    generatedCustomWorldProfile: sessionController.generatedCustomWorldProfile,
    isAgentDraftResultView: sessionController.isAgentDraftResultView,
    userId: authUi?.user?.id,
    setGeneratedCustomWorldProfile:
      sessionController.setGeneratedCustomWorldProfile,
    setAgentOperation: sessionController.setAgentOperation,
    setSavedCustomWorldEntries: platformBootstrap.setSavedCustomWorldEntries,
    setSelectedDetailEntry,
    refreshCustomWorldWorks: platformBootstrap.refreshCustomWorldWorks,
    persistAgentUiState: sessionController.persistAgentUiState,
    syncAgentSessionSnapshot: sessionController.syncAgentSessionSnapshot,
    buildDraftResultProfile: (session) =>
      rpgCreationPreviewAdapter.buildPreviewFromSession(session),
  });

  const detailNavigation = usePlatformEntryLibraryDetail({
    userId: authUi?.user?.id,
    selectedDetailEntry,
    setSelectedDetailEntry,
    savedCustomWorldEntries: platformBootstrap.savedCustomWorldEntries,
    setSavedCustomWorldEntries: platformBootstrap.setSavedCustomWorldEntries,
    setGeneratedCustomWorldProfile:
      sessionController.setGeneratedCustomWorldProfile,
    setCustomWorldError: sessionController.setCustomWorldError,
    setCustomWorldAutoSaveError:
      autosaveCoordinator.setCustomWorldAutoSaveError,
    setCustomWorldAutoSaveState:
      autosaveCoordinator.setCustomWorldAutoSaveState,
    setCustomWorldGenerationViewSource:
      sessionController.setCustomWorldGenerationViewSource,
    setCustomWorldResultViewSource:
      sessionController.setCustomWorldResultViewSource,
    setSelectionStage,
    setPlatformTabToCreate: enterCreateTab,
    setPlatformError: platformBootstrap.setPlatformError,
    appendBrowseHistoryEntry: platformBootstrap.appendBrowseHistoryEntry,
    refreshCustomWorldWorks: platformBootstrap.refreshCustomWorldWorks,
    refreshPublishedGallery: platformBootstrap.refreshPublishedGallery,
    persistAgentUiState: sessionController.persistAgentUiState,
    syncAgentSessionSnapshot: sessionController.syncAgentSessionSnapshot,
    buildDraftResultProfile: (session) =>
      rpgCreationPreviewAdapter.buildPreviewFromSession(session),
    suppressAgentDraftResultAutoOpen:
      sessionController.suppressAgentDraftResultAutoOpen,
    releaseAgentDraftResultAutoOpenSuppression:
      sessionController.releaseAgentDraftResultAutoOpenSuppression,
    resetAutoSaveTrackingToIdle:
      autosaveCoordinator.resetAutoSaveTrackingToIdle,
    markAutoSavedProfile: autosaveCoordinator.markAutoSavedProfile,
  });

  const enterWorldCoordinator = useRpgCreationEnterWorld({
    isAgentDraftResultView: sessionController.isAgentDraftResultView,
    activeAgentSessionId: sessionController.activeAgentSessionId,
    generatedCustomWorldProfile: sessionController.generatedCustomWorldProfile,
    agentSessionProfile: sessionController.agentDraftResultProfile,
    agentSession: sessionController.agentSession,
    handleCustomWorldSelect,
    executePublishWorld: () =>
      autosaveCoordinator.executeAgentActionAndWait({
        action: 'publish_world',
      }),
    setGeneratedCustomWorldProfile:
      sessionController.setGeneratedCustomWorldProfile,
  });

  const previewCustomWorldCharacters = useMemo(
    () =>
      sessionController.generatedCustomWorldProfile
        ? buildCustomWorldPlayableCharacters(
            sessionController.generatedCustomWorldProfile,
          )
        : [],
    [sessionController.generatedCustomWorldProfile],
  );
  const agentResultPreview =
    sessionController.agentSession?.resultPreview ?? null;
  const agentResultPreviewBlockers = useMemo(
    () => agentResultPreview?.blockers ?? [],
    [agentResultPreview],
  );
  const agentResultPublishGateView = useMemo(
    () =>
      buildAgentResultPublishGateView(
        sessionController.generatedCustomWorldProfile,
        agentResultPreviewBlockers,
        Boolean(agentResultPreview?.publishReady),
      ),
    [
      agentResultPreview?.publishReady,
      agentResultPreviewBlockers,
      sessionController.generatedCustomWorldProfile,
    ],
  );
  const agentResultPreviewQualityFindings = useMemo(
    () => agentResultPreview?.qualityFindings ?? [],
    [agentResultPreview],
  );
  const agentResultPreviewSourceLabel = useMemo(() => {
    if (!agentResultPreview?.source) {
      return null;
    }
    if (agentResultPreview.source === 'published_profile') {
      return '已发布世界';
    }
    if (agentResultPreview.source === 'session_preview') {
      return '会话预览';
    }
    return '服务端预览';
  }, [agentResultPreview]);

  const featuredGalleryEntries = useMemo(
    () => platformBootstrap.publishedGalleryEntries.slice(0, 6),
    [platformBootstrap.publishedGalleryEntries],
  );

  const creationHubItems =
    platformBootstrap.customWorldWorkEntries.length > 0
      ? platformBootstrap.customWorldWorkEntries
      : buildCreationHubFallbackItems(
          platformBootstrap.savedCustomWorldEntries,
        );
  const resultViewError =
    autosaveCoordinator.customWorldAutoSaveError ??
    sessionController.customWorldError;

  useEffect(() => {
    if (
      selectionStage === 'custom-world-result' &&
      !sessionController.generatedCustomWorldProfile
    ) {
      setSelectionStage(selectedDetailEntry ? 'detail' : 'platform');
    }
  }, [
    selectedDetailEntry,
    selectionStage,
    sessionController.generatedCustomWorldProfile,
    setSelectionStage,
  ]);

  useEffect(() => {
    if (selectionStage === 'big-fish-result' && !bigFishSession?.draft) {
      setSelectionStage(
        bigFishSession ? 'big-fish-agent-workspace' : 'platform',
      );
    }
    if (selectionStage === 'big-fish-runtime' && !bigFishRun) {
      setSelectionStage(bigFishSession?.draft ? 'big-fish-result' : 'platform');
    }
  }, [bigFishRun, bigFishSession, selectionStage, setSelectionStage]);

  const runProtectedAction = useCallback(
    (action: () => void) => {
      if (!authUi?.requireAuth) {
        action();
        return;
      }

      authUi.requireAuth(action);
    },
    [authUi],
  );

  const handlePublicCodeSearch = useCallback(
    async (keyword: string) => {
      const normalizedKeyword = keyword.trim();
      if (!normalizedKeyword) {
        return;
      }

      setIsSearchingPublicCode(true);
      setPublicSearchError(null);
      setSearchedPublicUser(null);

      const upperKeyword = normalizedKeyword.toUpperCase();
      const shouldSearchUserIdFirst = /^user[_-][a-z0-9_-]+$/iu.test(normalizedKeyword);
      const shouldSearchWorkFirst =
        !shouldSearchUserIdFirst &&
        (upperKeyword.startsWith('CW') || /^\d{1,8}$/u.test(normalizedKeyword));
      const shouldSearchUserFirst =
        shouldSearchUserIdFirst || upperKeyword.startsWith('SY') || !shouldSearchWorkFirst;

      const tryOpenGalleryEntry = async () => {
        const entry = await getRpgEntryWorldGalleryDetailByCode(normalizedKeyword);
        await detailNavigation.openGalleryDetail({
          ownerUserId: entry.ownerUserId,
          profileId: entry.profileId,
          publicWorkCode: entry.publicWorkCode,
          authorPublicUserCode: entry.authorPublicUserCode,
          visibility: 'published',
          publishedAt: entry.publishedAt,
          updatedAt: entry.updatedAt,
          authorDisplayName: entry.authorDisplayName,
          worldName: entry.worldName,
          subtitle: entry.subtitle,
          summaryText: entry.summaryText,
          coverImageSrc: entry.coverImageSrc,
          themeMode: entry.themeMode,
          playableNpcCount: entry.playableNpcCount,
          landmarkCount: entry.landmarkCount,
        } satisfies CustomWorldGalleryCard);
      };

      try {
        if (shouldSearchUserIdFirst) {
          const user = await getPublicAuthUserById(normalizedKeyword);
          setSearchedPublicUser(user);
          return;
        }

        if (shouldSearchWorkFirst) {
          try {
            await tryOpenGalleryEntry();
            return;
          } catch {}
        }

        if (shouldSearchUserFirst) {
          try {
            const user = await getPublicAuthUserByCode(normalizedKeyword);
            setSearchedPublicUser(user);
            return;
          } catch {}
        }

        if (!shouldSearchWorkFirst) {
          await tryOpenGalleryEntry();
          return;
        }

        const user = await getPublicAuthUserByCode(normalizedKeyword);
        setSearchedPublicUser(user);
      } catch (error) {
        setPublicSearchError(
          resolveRpgCreationErrorMessage(error, '未找到对应的叙世号或作品号。'),
        );
      } finally {
        setIsSearchingPublicCode(false);
      }
    },
    [detailNavigation],
  );

  const prepareCreationLaunch = useCallback(() => {
    if (sessionController.isCreatingAgentSession) {
      return false;
    }

    if (!hasSavedGame) {
      handleStartNewGame();
    }

    sessionController.setCreationTypeError(null);
    return true;
  }, [handleStartNewGame, hasSavedGame, sessionController]);

  const openCreationTypePicker = useCallback(() => {
    if (!prepareCreationLaunch()) {
      return;
    }

    setShowCreationTypeModal(true);
  }, [prepareCreationLaunch]);

  const resolveBigFishErrorMessage = useCallback(
    (error: unknown, fallback: string) =>
      resolveRpgCreationErrorMessage(error, fallback),
    [],
  );
  const resolvePuzzleErrorMessage = useCallback(
    (error: unknown, fallback: string) =>
      resolveRpgCreationErrorMessage(error, fallback),
    [],
  );

  const refreshBigFishShelf = useCallback(async () => {
    setIsBigFishLoadingLibrary(true);

    try {
      const worksResponse = await listBigFishWorks();
      setBigFishWorks(worksResponse.items);
      setBigFishError(null);
    } catch (error) {
      setBigFishError(
        resolveBigFishErrorMessage(error, '读取大鱼吃小鱼作品列表失败。'),
      );
    } finally {
      setIsBigFishLoadingLibrary(false);
    }
  }, [resolveBigFishErrorMessage]);

  const refreshPuzzleShelf = useCallback(async () => {
    setIsPuzzleLoadingLibrary(true);

    try {
      const worksResponse = await listPuzzleWorks();
      setPuzzleWorks(worksResponse.items);
      setPuzzleError(null);
    } catch (error) {
      setPuzzleError(
        resolvePuzzleErrorMessage(error, '读取拼图作品列表失败。'),
      );
    } finally {
      setIsPuzzleLoadingLibrary(false);
    }
  }, [resolvePuzzleErrorMessage]);

  const openBigFishAgentWorkspace = useCallback(async () => {
    if (isBigFishBusy) {
      return;
    }

    setIsBigFishBusy(true);
    setBigFishError(null);
    setBigFishRun(null);

    try {
      const { session } = await createBigFishCreationSession({});
      setBigFishSession(session);
      enterCreateTab();
      setShowCreationTypeModal(false);
      setSelectionStage('big-fish-agent-workspace');
    } catch (error) {
      setBigFishError(
        resolveBigFishErrorMessage(error, '开启大鱼吃小鱼共创工作台失败。'),
      );
    } finally {
      setIsBigFishBusy(false);
    }
  }, [
    enterCreateTab,
    isBigFishBusy,
    resolveBigFishErrorMessage,
    setSelectionStage,
  ]);

  const openPuzzleAgentWorkspace = useCallback(async () => {
    if (isPuzzleBusy) {
      return;
    }

    setIsPuzzleBusy(true);
    setPuzzleError(null);
    setPuzzleRun(null);
    setPuzzleOperation(null);

    try {
      const { session } = await createPuzzleAgentSession({});
      setPuzzleSession(session);
      enterCreateTab();
      setShowCreationTypeModal(false);
      setSelectionStage('puzzle-agent-workspace');
    } catch (error) {
      setPuzzleError(
        resolvePuzzleErrorMessage(error, '开启拼图共创工作台失败。'),
      );
    } finally {
      setIsPuzzleBusy(false);
    }
  }, [
    enterCreateTab,
    isPuzzleBusy,
    resolvePuzzleErrorMessage,
    setSelectionStage,
  ]);

  const handleCreationHubCreateType = useCallback(
    (type: PlatformCreationTypeId) => {
      if (type === 'airp' || type === 'visual-novel') {
        return;
      }

      if (!prepareCreationLaunch()) {
        return;
      }

      if (type === 'rpg') {
        runProtectedAction(() => {
          void sessionController.openRpgAgentWorkspace();
        });
        return;
      }

      if (type === 'big-fish') {
        runProtectedAction(() => {
          void openBigFishAgentWorkspace();
        });
        return;
      }

      if (type === 'puzzle') {
        runProtectedAction(() => {
          void openPuzzleAgentWorkspace();
        });
      }
    },
    [
      openBigFishAgentWorkspace,
      openPuzzleAgentWorkspace,
      prepareCreationLaunch,
      runProtectedAction,
      sessionController,
    ],
  );

  const leaveBigFishFlow = useCallback(() => {
    setBigFishError(null);
    setBigFishRun(null);
    setBigFishGenerationState(null);
    setStreamingBigFishReplyText('');
    setIsStreamingBigFishReply(false);
    enterCreateTab();
    setSelectionStage('platform');
  }, [enterCreateTab, setSelectionStage]);

  const leavePuzzleFlow = useCallback(() => {
    setPuzzleError(null);
    setPuzzleOperation(null);
    setPuzzleRun(null);
    setPuzzleGenerationState(null);
    setIsPuzzleNextLevelGenerating(false);
    setStreamingPuzzleReplyText('');
    setIsStreamingPuzzleReply(false);
    enterCreateTab();
    setSelectionStage('platform');
  }, [enterCreateTab, setSelectionStage]);

  const submitBigFishMessage = useCallback(
    async (payload: SendBigFishMessageRequest) => {
      if (!bigFishSession || isStreamingBigFishReply) {
        return;
      }

      const optimisticMessage = {
        id: payload.clientMessageId,
        role: 'user',
        kind: 'chat',
        text: payload.text.trim(),
        createdAt: new Date().toISOString(),
      };

      setBigFishError(null);
      setStreamingBigFishReplyText('');
      setIsStreamingBigFishReply(true);
      setBigFishSession((current) =>
        current
          ? {
              ...current,
              messages: [...current.messages, optimisticMessage],
              updatedAt: optimisticMessage.createdAt,
            }
          : current,
      );

      try {
        const nextSession = await streamBigFishCreationMessage(
          bigFishSession.sessionId,
          payload,
          {
            onUpdate: setStreamingBigFishReplyText,
          },
        );
        setBigFishSession(nextSession);
        setStreamingBigFishReplyText('');
      } catch (error) {
        setBigFishError(
          resolveBigFishErrorMessage(error, '发送大鱼吃小鱼共创消息失败。'),
        );
      } finally {
        setIsStreamingBigFishReply(false);
      }
    },
    [bigFishSession, isStreamingBigFishReply, resolveBigFishErrorMessage],
  );

  const submitPuzzleMessage = useCallback(
    async (payload: SendPuzzleAgentMessageRequest) => {
      if (!puzzleSession || isStreamingPuzzleReply) {
        return;
      }

      const optimisticMessage = {
        id: payload.clientMessageId,
        role: 'user',
        kind: 'chat',
        text: payload.text.trim(),
        createdAt: new Date().toISOString(),
      } satisfies PuzzleAgentSessionSnapshot['messages'][number];

      setPuzzleError(null);
      setStreamingPuzzleReplyText('');
      setIsStreamingPuzzleReply(true);
      setPuzzleSession((current) =>
        current
          ? {
              ...current,
              messages: [...current.messages, optimisticMessage],
              updatedAt: optimisticMessage.createdAt,
            }
          : current,
      );

      try {
        const nextSession = await streamPuzzleAgentMessage(
          puzzleSession.sessionId,
          payload,
          {
            onUpdate: setStreamingPuzzleReplyText,
          },
        );
        setPuzzleSession(nextSession);
        setStreamingPuzzleReplyText('');
      } catch (error) {
        setPuzzleError(
          resolvePuzzleErrorMessage(error, '发送拼图共创消息失败。'),
        );
      } finally {
        setIsStreamingPuzzleReply(false);
      }
    },
    [isStreamingPuzzleReply, puzzleSession, resolvePuzzleErrorMessage],
  );

  const executeBigFishAction = useCallback(
    async (payload: ExecuteBigFishActionRequest) => {
      if (!bigFishSession || isBigFishBusy) {
        return;
      }

      setIsBigFishBusy(true);
      setBigFishError(null);

      try {
        if (payload.action === 'big_fish_compile_draft') {
          setSelectionStage('big-fish-generating');
          setBigFishGenerationState(createMiniGameDraftGenerationState('big-fish'));
          const { session } = await executeBigFishCreationAction(
            bigFishSession.sessionId,
            payload,
          );
          setBigFishSession(session);
          setBigFishGenerationState((current) =>
            current
              ? {
                  ...current,
                  phase: 'ready',
                  completedAssetCount: session.assetSlots.filter(
                    (slot) => slot.status === 'ready',
                  ).length,
                  totalAssetCount: session.assetSlots.length,
                }
              : current,
          );
          setSelectionStage('big-fish-result');
          return;
        }

        const { session } = await executeBigFishCreationAction(
          bigFishSession.sessionId,
          payload,
        );
        setBigFishSession(session);
      } catch (error) {
        setBigFishGenerationState((current) =>
          current
            ? {
                ...current,
                phase: 'failed',
                error: resolveBigFishErrorMessage(error, '执行大鱼吃小鱼操作失败。'),
              }
            : current,
        );
        setBigFishError(
          resolveBigFishErrorMessage(error, '执行大鱼吃小鱼操作失败。'),
        );
      } finally {
        setIsBigFishBusy(false);
      }
    },
    [
      bigFishSession,
      isBigFishBusy,
      resolveBigFishErrorMessage,
      setSelectionStage,
    ],
  );

  const executePuzzleAction = useCallback(
    async (payload: PuzzleAgentActionRequest) => {
      if (!puzzleSession || isPuzzleBusy) {
        return;
      }

      setIsPuzzleBusy(true);
      setPuzzleError(null);

      try {
        if (payload.action === 'compile_puzzle_draft') {
          setSelectionStage('puzzle-generating');
          setPuzzleGenerationState(createMiniGameDraftGenerationState('puzzle'));
          const { operation, session } = await executePuzzleAgentAction(
            puzzleSession.sessionId,
            payload,
          );
          setPuzzleOperation(operation);
          setPuzzleSession(session);
          setPuzzleGenerationState((current) =>
            current
              ? {
                  ...current,
                  phase: 'ready',
                  completedAssetCount: 1,
                  totalAssetCount: 1,
                }
              : current,
          );
          setSelectionStage('puzzle-result');
          return;
        }

        const { operation, session } = await executePuzzleAgentAction(
          puzzleSession.sessionId,
          payload,
        );
        setPuzzleOperation(operation);

        if (payload.action === 'publish_puzzle_work') {
          await refreshPuzzleShelf();
        }

        setPuzzleSession(session);

        if (
          payload.action === 'publish_puzzle_work' &&
          session.publishedProfileId
        ) {
          const galleryDetail = await getPuzzleGalleryDetail(
            session.publishedProfileId,
          );
          setSelectedPuzzleDetail(galleryDetail.item);
          setSelectionStage('puzzle-gallery-detail');
        }
      } catch (error) {
        setPuzzleGenerationState((current) =>
          current
            ? {
                ...current,
                phase: 'failed',
                error: resolvePuzzleErrorMessage(error, '执行拼图操作失败。'),
              }
            : current,
        );
        setPuzzleError(resolvePuzzleErrorMessage(error, '执行拼图操作失败。'));
      } finally {
        setIsPuzzleBusy(false);
      }
    },
    [
      isPuzzleBusy,
      puzzleSession,
      refreshPuzzleShelf,
      resolvePuzzleErrorMessage,
      setSelectionStage,
    ],
  );

  const startBigFishRun = useCallback(async () => {
    if (!bigFishSession || isBigFishBusy) {
      return;
    }

    setIsBigFishBusy(true);
    setBigFishError(null);

    try {
      const { run } = await startBigFishRuntimeRun(bigFishSession.sessionId);
      setBigFishRun(run);
      setSelectionStage('big-fish-runtime');
    } catch (error) {
      setBigFishError(
        resolveBigFishErrorMessage(error, '启动大鱼吃小鱼测试玩法失败。'),
      );
    } finally {
      setIsBigFishBusy(false);
    }
  }, [
    bigFishSession,
    isBigFishBusy,
    resolveBigFishErrorMessage,
    setSelectionStage,
  ]);

  const startPuzzleRunFromProfile = useCallback(
    async (profileId: string) => {
      if (isPuzzleBusy) {
        return;
      }

      setIsPuzzleBusy(true);
      setPuzzleError(null);

      try {
        const { item } = await getPuzzleGalleryDetail(profileId);
        setSelectedPuzzleDetail(item);
        setPuzzleRun(startLocalPuzzleRun(item));
        setSelectionStage('puzzle-runtime');
      } catch (error) {
        setPuzzleError(resolvePuzzleErrorMessage(error, '启动拼图玩法失败。'));
      } finally {
        setIsPuzzleBusy(false);
      }
    },
    [isPuzzleBusy, resolvePuzzleErrorMessage, setSelectionStage],
  );

  const submitBigFishInput = useCallback(
    (payload: SubmitBigFishInputRequest) => {
      if (!bigFishRun || bigFishInputInFlightRef.current) {
        return;
      }

      bigFishInputInFlightRef.current = true;
      void submitBigFishRuntimeInput(bigFishRun.runId, payload)
        .then(({ run }) => {
          setBigFishRun(run);
        })
        .catch((error) => {
          setBigFishError(
            resolveBigFishErrorMessage(error, '同步大鱼吃小鱼输入失败。'),
          );
        })
        .finally(() => {
          bigFishInputInFlightRef.current = false;
        });
    },
    [bigFishRun, resolveBigFishErrorMessage],
  );

  const swapPuzzlePiecesInRun = useCallback(
    (payload: { firstPieceId: string; secondPieceId: string }) => {
      if (!puzzleRun || isPuzzleBusy) {
        return;
      }

      setPuzzleError(null);
      setPuzzleRun(swapLocalPuzzlePieces(puzzleRun, payload));
    },
    [isPuzzleBusy, puzzleRun],
  );

  const dragPuzzlePiece = useCallback(
    (payload: {
      pieceId: string;
      targetRow: number;
      targetCol: number;
    }) => {
      if (!puzzleRun || isPuzzleBusy) {
        return;
      }

      setPuzzleError(null);
      setPuzzleRun(dragLocalPuzzlePiece(puzzleRun, payload));
    },
    [isPuzzleBusy, puzzleRun],
  );

  const advancePuzzleLevel = useCallback(async () => {
    if (!puzzleRun || isPuzzleBusy) {
      return;
    }

    const currentLevel = puzzleRun.currentLevel;
    if (!currentLevel || currentLevel.status !== 'cleared') {
      return;
    }

    setIsPuzzleBusy(true);
    setIsPuzzleNextLevelGenerating(true);
    setPuzzleError(null);

    try {
      const { run } = await advanceLocalPuzzleNextLevel({
        run: puzzleRun,
        sourceSessionId:
          selectedPuzzleDetail?.sourceSessionId ?? puzzleSession?.sessionId ?? null,
      });
      setPuzzleRun(run);
    } catch (error) {
      setPuzzleError(resolvePuzzleErrorMessage(error, '准备下一关失败。'));
    } finally {
      setIsPuzzleNextLevelGenerating(false);
      setIsPuzzleBusy(false);
    }
  }, [
    isPuzzleBusy,
    puzzleRun,
    puzzleSession,
    resolvePuzzleErrorMessage,
    selectedPuzzleDetail,
  ]);

  const leaveAgentWorkspace = useCallback(() => {
    enterCreateTab();
    sessionController.resetSessionViewState();
    sessionController.setGeneratedCustomWorldProfile(null);
    autosaveCoordinator.resetAutoSaveTrackingToIdle();
    sessionController.persistAgentUiState(
      sessionController.activeAgentSessionId,
      null,
    );
    setSelectionStage('platform');
  }, [
    autosaveCoordinator,
    enterCreateTab,
    sessionController,
    setSelectionStage,
  ]);

  const leaveAgentDraftGeneration = useCallback(() => {
    if (sessionController.isActiveGenerationRunning) {
      return;
    }

    sessionController.setAgentDraftGenerationStartedAt(null);
    sessionController.setCustomWorldGenerationViewSource(null);
    setSelectionStage('agent-workspace');
  }, [sessionController, setSelectionStage]);

  const leaveAgentDraftResult = useCallback(() => {
    sessionController.suppressAgentDraftResultAutoOpen();
    sessionController.setGeneratedCustomWorldProfile(null);
    sessionController.setCustomWorldError(null);
    autosaveCoordinator.resetAutoSaveTrackingToIdle();
    sessionController.setCustomWorldGenerationViewSource(null);
    sessionController.setCustomWorldResultViewSource(null);
    enterCreateTab();
    setSelectionStage('platform');
  }, [
    autosaveCoordinator,
    enterCreateTab,
    sessionController,
    setSelectionStage,
  ]);

  const leaveCustomWorldResult = useCallback(() => {
    sessionController.setGeneratedCustomWorldProfile(null);
    sessionController.setCustomWorldError(null);
    autosaveCoordinator.resetAutoSaveTrackingToIdle();
    sessionController.setCustomWorldGenerationViewSource(null);
    sessionController.setCustomWorldResultViewSource(null);
    setSelectionStage(selectedDetailEntry ? 'detail' : 'platform');
  }, [
    autosaveCoordinator,
    selectedDetailEntry,
    sessionController,
    setSelectionStage,
  ]);

  const handleStartSelectedWorld = useCallback(() => {
    if (!selectedDetailEntry) {
      return;
    }

    runProtectedAction(() => {
      handleCustomWorldSelect(selectedDetailEntry.profile);
    });
  }, [handleCustomWorldSelect, runProtectedAction, selectedDetailEntry]);

  const handleExperienceRpgWork = useCallback(
    (work: (typeof creationHubItems)[number]) => {
      if (!work.profileId) {
        return;
      }

      runProtectedAction(() => {
        const matchedEntry = platformBootstrap.savedCustomWorldEntries.find(
          (entry) => entry.profileId === work.profileId,
        );
        if (!matchedEntry) {
          platformBootstrap.setPlatformError('未找到可体验的作品，请刷新后重试。');
          return;
        }

        handleCustomWorldSelect(matchedEntry.profile);
      });
    },
    [
      handleCustomWorldSelect,
      platformBootstrap,
      platformBootstrap.savedCustomWorldEntries,
      runProtectedAction,
    ],
  );

  const handleDeleteLibraryEntry = useCallback(
    (entry: CustomWorldLibraryEntry<CustomWorldProfile>) => {
      if (!entry.profileId || deletingCreationWorkId) {
        return;
      }

      runProtectedAction(() => {
        const confirmed = window.confirm(
          `确认删除作品《${entry.worldName}》吗？删除后会从你的作品列表和公开广场中移除。`,
        );
        if (!confirmed) {
          return;
        }

        setDeletingCreationWorkId(entry.profileId);
        platformBootstrap.setPlatformError(null);

        void deleteRpgEntryWorldProfile(entry.profileId)
          .then(async (entries) => {
            platformBootstrap.setSavedCustomWorldEntries(entries);
            await platformBootstrap.refreshCustomWorldWorks().catch(() => []);
            await platformBootstrap.refreshPublishedGallery().catch(() => []);
          })
          .catch((error) => {
            platformBootstrap.setPlatformError(
              resolveRpgCreationErrorMessage(error, '删除自定义世界失败。'),
            );
          })
          .finally(() => {
            setDeletingCreationWorkId(null);
          });
      });
    },
    [deletingCreationWorkId, platformBootstrap, runProtectedAction],
  );

  const handleDeletePublishedWork = useCallback(
    (work: (typeof creationHubItems)[number]) => {
      if (deletingCreationWorkId) {
        return;
      }

      runProtectedAction(() => {
        const confirmed = window.confirm(
          `确认删除作品《${work.title}》吗？删除后会从你的作品列表和公开广场中移除。`,
        );
        if (!confirmed) {
          return;
        }
        setDeletingCreationWorkId(work.workId);
        platformBootstrap.setPlatformError(null);

        const deleteTask =
          work.sourceType === 'published_profile' && work.profileId
            ? deleteRpgEntryWorldProfile(work.profileId).then(async (entries) => {
                platformBootstrap.setSavedCustomWorldEntries(entries);
                await platformBootstrap.refreshCustomWorldWorks().catch(() => []);
              })
            : work.sourceType === 'agent_session' && work.sessionId
              ? deleteRpgCreationAgentSession(work.sessionId).then((items) => {
                  platformBootstrap.setCustomWorldWorkEntries(items);
                })
              : Promise.reject(new Error('当前 RPG 作品缺少可删除 ID。'));

        void deleteTask
          .then(async () => {
            await platformBootstrap.refreshPublishedGallery().catch(() => []);
          })
          .catch((error) => {
            platformBootstrap.setPlatformError(
              resolveRpgCreationErrorMessage(error, '删除自定义世界失败。'),
            );
          })
          .finally(() => {
            setDeletingCreationWorkId(null);
          });
      });
    },
    [deletingCreationWorkId, platformBootstrap, runProtectedAction],
  );

  const handleDeleteBigFishWork = useCallback(
    (work: BigFishWorkSummary) => {
      if (deletingCreationWorkId) {
        return;
      }

      runProtectedAction(() => {
        const confirmed = window.confirm(
          `确认删除作品《${work.title}》吗？删除后会从你的作品列表中移除。`,
        );
        if (!confirmed) {
          return;
        }

        setDeletingCreationWorkId(work.workId);
        setBigFishError(null);

        void deleteBigFishWork(work.sourceSessionId)
          .then((response) => {
            setBigFishWorks(response.items);
          })
          .catch((error) => {
            setBigFishError(
              resolveBigFishErrorMessage(error, '删除大鱼吃小鱼作品失败。'),
            );
          })
          .finally(() => {
            setDeletingCreationWorkId(null);
          });
      });
    },
    [deletingCreationWorkId, resolveBigFishErrorMessage, runProtectedAction],
  );

  const handleDeletePuzzleWork = useCallback(
    (work: PuzzleWorkSummary) => {
      if (deletingCreationWorkId) {
        return;
      }

      runProtectedAction(() => {
        const confirmed = window.confirm(
          `确认删除作品《${work.levelName}》吗？删除后会从你的作品列表和公开广场中移除。`,
        );
        if (!confirmed) {
          return;
        }

        setDeletingCreationWorkId(work.workId);
        setPuzzleError(null);

        void deletePuzzleWork(work.profileId)
          .then((response) => {
            setPuzzleWorks(response.items);
          })
          .catch((error) => {
            setPuzzleError(resolvePuzzleErrorMessage(error, '删除拼图作品失败。'));
          })
          .finally(() => {
            setDeletingCreationWorkId(null);
          });
      });
    },
    [deletingCreationWorkId, resolvePuzzleErrorMessage, runProtectedAction],
  );

  const openPuzzleDetail = useCallback(
    async (profileId: string) => {
      setIsPuzzleBusy(true);
      setPuzzleError(null);

      try {
        const { item } = await getPuzzleGalleryDetail(profileId);
        setSelectedPuzzleDetail(item);
        enterCreateTab();
        setSelectionStage('puzzle-gallery-detail');
      } catch (error) {
        setPuzzleError(resolvePuzzleErrorMessage(error, '读取拼图详情失败。'));
      } finally {
        setIsPuzzleBusy(false);
      }
    },
    [enterCreateTab, resolvePuzzleErrorMessage, setSelectionStage],
  );

  const openPuzzleDraft = useCallback(
    async (item: PuzzleWorkSummary) => {
      const sessionId = item.sourceSessionId?.trim();
      if (!sessionId) {
        setPuzzleError('这份拼图草稿缺少会话信息，请重新开始创作。');
        return;
      }

      setIsPuzzleBusy(true);
      setPuzzleError(null);
      setPuzzleOperation(null);
      setPuzzleRun(null);
      setSelectedPuzzleDetail(null);
      setStreamingPuzzleReplyText('');
      setIsStreamingPuzzleReply(false);

      try {
        const { session } = await getPuzzleAgentSession(sessionId);
        setPuzzleSession(session);
        enterCreateTab();
        setSelectionStage(session.draft ? 'puzzle-result' : 'puzzle-agent-workspace');
      } catch (error) {
        await refreshPuzzleShelf().catch(() => undefined);
        setPuzzleError(resolvePuzzleErrorMessage(error, '读取拼图创作草稿失败。'));
        enterCreateTab();
        setSelectionStage('platform');
      } finally {
        setIsPuzzleBusy(false);
      }
    },
    [
      enterCreateTab,
      refreshPuzzleShelf,
      resolvePuzzleErrorMessage,
      setSelectionStage,
    ],
  );

  const openBigFishDraft = useCallback(
    async (item: BigFishWorkSummary) => {
      const sessionId = item.sourceSessionId?.trim();
      if (!sessionId) {
        setBigFishError('这份大鱼吃小鱼草稿缺少会话信息，请重新开始创作。');
        return;
      }

      setIsBigFishBusy(true);
      setBigFishError(null);
      setBigFishRun(null);
      setStreamingBigFishReplyText('');
      setIsStreamingBigFishReply(false);

      try {
        const { session } = await getBigFishCreationSession(sessionId);
        setBigFishSession(session);
        enterCreateTab();
        setSelectionStage(
          session.draft ? 'big-fish-result' : 'big-fish-agent-workspace',
        );
      } catch (error) {
        await refreshBigFishShelf().catch(() => undefined);
        setBigFishError(
          resolveBigFishErrorMessage(error, '读取大鱼吃小鱼创作草稿失败。'),
        );
        enterCreateTab();
        setSelectionStage('platform');
      } finally {
        setIsBigFishBusy(false);
      }
    },
    [
      enterCreateTab,
      refreshBigFishShelf,
      resolveBigFishErrorMessage,
      setSelectionStage,
    ],
  );

  const startBigFishRunFromWork = useCallback(
    async (item: BigFishWorkSummary) => {
      const sessionId = item.sourceSessionId?.trim();
      if (!sessionId) {
        setBigFishError('当前作品缺少会话信息，暂时无法进入玩法。');
        return;
      }

      setIsBigFishBusy(true);
      setBigFishError(null);

      try {
        const { session } = await getBigFishCreationSession(sessionId);
        const { run } = await startBigFishRuntimeRun(sessionId);
        setBigFishSession(session);
        setBigFishRun(run);
        setSelectionStage('big-fish-runtime');
      } catch (error) {
        setBigFishError(
          resolveBigFishErrorMessage(error, '启动大鱼吃小鱼玩法失败。'),
        );
      } finally {
        setIsBigFishBusy(false);
      }
    },
    [resolveBigFishErrorMessage, setSelectionStage],
  );

  useEffect(() => {
    if (
      (platformBootstrap.platformTab === 'create' ||
        selectionStage === 'platform') &&
      platformBootstrap.canReadProtectedData
    ) {
      void refreshPuzzleShelf();
    }
  }, [
    platformBootstrap.canReadProtectedData,
    platformBootstrap.platformTab,
    refreshPuzzleShelf,
    selectionStage,
  ]);

  useEffect(() => {
    if (
      (platformBootstrap.platformTab === 'create' ||
        selectionStage === 'platform') &&
      platformBootstrap.canReadProtectedData
    ) {
      void refreshBigFishShelf();
    }
  }, [
    platformBootstrap.canReadProtectedData,
    platformBootstrap.platformTab,
    refreshBigFishShelf,
    selectionStage,
  ]);

  const creationHubContent = (
    <CustomWorldCreationHub
      items={creationHubItems}
      loading={
        platformBootstrap.isLoadingPlatform ||
        isBigFishLoadingLibrary ||
        isPuzzleLoadingLibrary
      }
      error={
        platformBootstrap.isLoadingPlatform ||
        isBigFishLoadingLibrary ||
        isPuzzleLoadingLibrary
          ? null
          : (platformBootstrap.platformError ??
            sessionController.agentWorkspaceRestoreError ??
            bigFishError ??
            puzzleError)
      }
      onRetry={() => {
        platformBootstrap.setPlatformError(null);
        setBigFishError(null);
        setPuzzleError(null);
        void platformBootstrap.refreshCustomWorldWorks().catch((error) => {
          platformBootstrap.setPlatformError(
            resolveRpgCreationErrorMessage(error, '读取创作作品列表失败。'),
          );
        });
        void refreshBigFishShelf();
        void refreshPuzzleShelf();
      }}
      createError={
        sessionController.creationTypeError ?? bigFishError ?? puzzleError
      }
      createBusy={
        sessionController.isCreatingAgentSession ||
        isBigFishBusy ||
        isPuzzleBusy
      }
      onCreateType={handleCreationHubCreateType}
      onOpenDraft={(item) => {
        runProtectedAction(() => {
          void detailNavigation.handleOpenCreationWork(item);
        });
      }}
      onEnterPublished={(profileId) => {
        runProtectedAction(() => {
          const matchedWork = creationHubItems.find(
            (entry) => entry.profileId === profileId,
          );
          if (!matchedWork) {
            return;
          }
          void detailNavigation.handleOpenCreationWork(matchedWork);
        });
      }}
      onDeletePublished={(item) => {
        handleDeletePublishedWork(item);
      }}
      deletingWorkId={deletingCreationWorkId}
      onExperienceRpg={(item) => {
        handleExperienceRpgWork(item);
      }}
      bigFishItems={bigFishWorks}
      onOpenBigFishDetail={(item) => {
        runProtectedAction(() => {
          void openBigFishDraft(item);
        });
      }}
      onExperienceBigFish={(item) => {
        runProtectedAction(() => {
          void startBigFishRunFromWork(item);
        });
      }}
      onDeleteBigFish={(item) => {
        handleDeleteBigFishWork(item);
      }}
      puzzleItems={puzzleWorks}
      onOpenPuzzleDetail={(item) => {
        runProtectedAction(() => {
          if (item.publicationStatus === 'draft') {
            void openPuzzleDraft(item);
            return;
          }
          void openPuzzleDetail(item.profileId);
        });
      }}
      onExperiencePuzzle={(profileId) => {
        runProtectedAction(() => {
          void startPuzzleRunFromProfile(profileId);
        });
      }}
      onDeletePuzzle={(item) => {
        handleDeletePuzzleWork(item);
      }}
    />
  );

  return (
    <>
      <AnimatePresence mode="wait">
        {selectionStage === 'platform' && (
          <motion.div
            key="platform-home"
            initial={{ opacity: 0, y: 12 }}
            animate={{ opacity: 1, y: 0 }}
            exit={{ opacity: 0, y: -12 }}
            className="flex h-full min-h-0 min-w-0 flex-col overflow-hidden"
          >
            <PlatformEntryHomeView
              activeTab={platformBootstrap.platformTab}
              onTabChange={platformBootstrap.setPlatformTab}
              hasSavedGame={hasSavedGame}
              savedSnapshot={savedSnapshot}
              saveEntries={platformBootstrap.saveEntries}
              saveError={platformBootstrap.saveError}
              featuredEntries={featuredGalleryEntries}
              latestEntries={platformBootstrap.publishedGalleryEntries}
              myEntries={platformBootstrap.savedCustomWorldEntries}
              historyEntries={platformBootstrap.historyEntries}
              profileDashboard={platformBootstrap.profileDashboard}
              isLoadingPlatform={platformBootstrap.isLoadingPlatform}
              isLoadingDashboard={platformBootstrap.isLoadingDashboard}
              isResumingSaveWorldKey={platformBootstrap.isResumingSaveWorldKey}
              platformError={
                platformBootstrap.isLoadingPlatform
                  ? null
                  : (platformBootstrap.platformError ??
                    sessionController.agentWorkspaceRestoreError)
              }
              dashboardError={
                platformBootstrap.isLoadingDashboard
                  ? null
                  : platformBootstrap.dashboardError
              }
              createTabContent={creationHubContent}
              onContinueGame={handleContinueGame}
              onResumeSave={(entry) => {
                void platformBootstrap.handleResumeSaveEntry(entry);
              }}
              onOpenCreateWorld={openCreationTypePicker}
              onOpenCreateTypePicker={openCreationTypePicker}
              onOpenGalleryDetail={(entry) => {
                runProtectedAction(() => {
                  void detailNavigation.openGalleryDetail(entry);
                });
              }}
              onOpenLibraryDetail={(entry) => {
                runProtectedAction(() => {
                  detailNavigation.openLibraryDetail(entry);
                });
              }}
              onDeleteLibraryEntry={(entry) => {
                handleDeleteLibraryEntry(entry);
              }}
              deletingLibraryEntryId={deletingCreationWorkId}
              onSearchPublicCode={(keyword) => {
                void handlePublicCodeSearch(keyword);
              }}
              isSearchingPublicCode={isSearchingPublicCode}
              onOpenProfileDashboardCard={() => {
                if (platformBootstrap.dashboardError) {
                  void platformBootstrap.refreshProfileDashboard();
                }
              }}
            />
          </motion.div>
        )}

        {selectionStage === 'detail' && (
          <motion.div
            key="platform-detail"
            initial={{ opacity: 0, y: 12 }}
            animate={{ opacity: 1, y: 0 }}
            exit={{ opacity: 0, y: -12 }}
            className="flex h-full min-h-0 flex-col"
          >
            {detailNavigation.isDetailLoading || !selectedDetailEntry ? (
              <div className="flex h-full items-center justify-center">
                <div className="platform-subpanel rounded-2xl px-5 py-4 text-sm text-[var(--platform-text-base)]">
                  {detailNavigation.detailError || '正在读取作品详情...'}
                </div>
              </div>
            ) : (
              <PlatformEntryWorldDetailView
                entry={selectedDetailEntry}
                isMutating={detailNavigation.isMutatingDetail}
                error={detailNavigation.detailError}
                onBack={() => {
                  detailNavigation.setDetailError(null);
                  entryNavigation.backToPlatformHome();
                }}
                onStartGame={handleStartSelectedWorld}
                onContinueEdit={
                  detailNavigation.isSelectedWorldOwned
                    ? () => {
                        runProtectedAction(() => {
                          detailNavigation.openSavedCustomWorldEditor(
                            selectedDetailEntry,
                          );
                        });
                      }
                    : null
                }
                onPublish={
                  selectedDetailEntry.visibility === 'draft' &&
                  detailNavigation.isSelectedWorldOwned
                    ? () => {
                        runProtectedAction(() => {
                          void detailNavigation.handlePublishSelectedWorld();
                        });
                      }
                    : null
                }
                onUnpublish={
                  selectedDetailEntry.visibility === 'published' &&
                  detailNavigation.isSelectedWorldOwned
                    ? () => {
                        runProtectedAction(() => {
                          void detailNavigation.handleUnpublishSelectedWorld();
                        });
                      }
                    : null
                }
                onDelete={
                  detailNavigation.isSelectedWorldOwned
                    ? () => {
                        runProtectedAction(() => {
                          void detailNavigation.handleDeleteSelectedWorld();
                        });
                      }
                    : null
                }
              />
            )}
          </motion.div>
        )}

        {selectionStage === 'agent-workspace' && (
          <motion.div
            key="agent-workspace"
            initial={{ opacity: 0, y: 12 }}
            animate={{ opacity: 1, y: 0 }}
            exit={{ opacity: 0, y: -12 }}
            className="flex h-full min-h-0 flex-col"
          >
            <Suspense
              fallback={
                <LazyPanelFallback label="正在加载 Agent 共创工作区..." />
              }
            >
              {sessionController.agentSession ? (
                <CustomWorldAgentWorkspace
                  session={sessionController.agentSession}
                  activeOperation={sessionController.agentOperation}
                  streamingReplyText={sessionController.streamingAgentReplyText}
                  isStreamingReply={sessionController.isStreamingAgentReply}
                  onBack={leaveAgentWorkspace}
                  onSubmitMessage={(payload) => {
                    void sessionController.submitAgentMessage(payload);
                  }}
                  onExecuteAction={(payload) => {
                    void sessionController.executeAgentAction(payload);
                  }}
                />
              ) : (
                <div className="flex h-full items-center justify-center">
                  <div className="platform-subpanel rounded-2xl px-5 py-4 text-sm text-[var(--platform-text-base)]">
                    {sessionController.isLoadingAgentSession
                      ? '正在准备 Agent 共创工作区...'
                      : sessionController.agentWorkspaceRestoreError ||
                        '正在恢复创作工作区...'}
                  </div>
                </div>
              )}
            </Suspense>
          </motion.div>
        )}

        {selectionStage === 'big-fish-agent-workspace' && (
          <motion.div
            key="big-fish-agent-workspace"
            initial={{ opacity: 0, y: 12 }}
            animate={{ opacity: 1, y: 0 }}
            exit={{ opacity: 0, y: -12 }}
            className="flex h-full min-h-0 flex-col"
          >
            <Suspense
              fallback={
                <LazyPanelFallback label="正在加载大鱼吃小鱼共创工作区..." />
              }
            >
              <BigFishAgentWorkspace
                session={bigFishSession}
                streamingReplyText={streamingBigFishReplyText}
                isBusy={isBigFishBusy || isStreamingBigFishReply}
                error={bigFishError}
                onBack={leaveBigFishFlow}
                onSubmitMessage={(payload) => {
                  void submitBigFishMessage(payload);
                }}
                onExecuteAction={(payload) => {
                  void executeBigFishAction(payload);
                }}
              />
            </Suspense>
          </motion.div>
        )}

        {selectionStage === 'big-fish-generating' && (
          <motion.div
            key="big-fish-generating"
            initial={{ opacity: 0, y: 12 }}
            animate={{ opacity: 1, y: 0 }}
            exit={{ opacity: 0, y: -12 }}
            className="flex h-full min-h-0 flex-col"
          >
            <Suspense
              fallback={<LazyPanelFallback label="正在加载大鱼吃小鱼生成面板..." />}
            >
              <CustomWorldGenerationView
                settingText={
                  bigFishSession?.lastAssistantReply ?? '正在整理当前玩法草稿。'
                }
                anchorEntries={buildBigFishGenerationAnchorEntries(bigFishSession)}
                progress={buildMiniGameDraftGenerationProgress(
                  bigFishGenerationState,
                )}
                isGenerating={isBigFishBusy}
                error={bigFishError}
                onBack={leaveBigFishFlow}
                onEditSetting={() => {
                  setSelectionStage('big-fish-agent-workspace');
                }}
                onRetry={() => {
                  void executeBigFishAction({ action: 'big_fish_compile_draft' });
                }}
                onInterrupt={undefined}
                backLabel="返回创作中心"
                settingActionLabel={null}
                retryLabel="重新生成草稿"
                settingTitle="当前玩法信息"
                settingDescription={null}
                progressTitle="大鱼吃小鱼草稿生成进度"
                activeBadgeLabel="草稿生成中"
                pausedBadgeLabel="草稿生成已暂停"
                idleBadgeLabel="等待返回工作区"
              />
            </Suspense>
          </motion.div>
        )}

        {selectionStage === 'big-fish-result' && bigFishSession?.draft && (
          <motion.div
            key="big-fish-result"
            initial={{ opacity: 0, y: 12 }}
            animate={{ opacity: 1, y: 0 }}
            exit={{ opacity: 0, y: -12 }}
            className="flex h-full min-h-0 flex-col"
          >
            <Suspense
              fallback={<LazyPanelFallback label="正在加载玩法结果页..." />}
            >
              <BigFishResultView
                session={bigFishSession}
                isBusy={isBigFishBusy}
                error={bigFishError}
                onBack={() => {
                  setSelectionStage('big-fish-agent-workspace');
                }}
                onDismissError={() => {
                  setBigFishError(null);
                }}
                onExecuteAction={(payload) => {
                  void executeBigFishAction(payload);
                }}
                onStartTestRun={() => {
                  void startBigFishRun();
                }}
              />
            </Suspense>
          </motion.div>
        )}

        {selectionStage === 'big-fish-runtime' && (
          <motion.div
            key="big-fish-runtime"
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 }}
            exit={{ opacity: 0 }}
            className="fixed inset-0 z-[100]"
          >
            <Suspense
              fallback={<LazyPanelFallback label="正在加载大鱼吃小鱼玩法..." />}
            >
              <BigFishRuntimeShell
                run={bigFishRun}
                assetSlots={bigFishSession?.assetSlots ?? []}
                isBusy={isBigFishBusy}
                error={bigFishError}
                onBack={() => {
                  setSelectionStage('big-fish-result');
                }}
                onSubmitInput={submitBigFishInput}
              />
            </Suspense>
          </motion.div>
        )}

        {selectionStage === 'puzzle-agent-workspace' && (
          <motion.div
            key="puzzle-agent-workspace"
            initial={{ opacity: 0, y: 12 }}
            animate={{ opacity: 1, y: 0 }}
            exit={{ opacity: 0, y: -12 }}
            className="flex h-full min-h-0 flex-col"
          >
            <PuzzleAgentWorkspace
              session={puzzleSession}
              activeOperation={puzzleOperation}
              streamingReplyText={streamingPuzzleReplyText}
              isBusy={isPuzzleBusy || isStreamingPuzzleReply}
              error={puzzleError}
              onBack={leavePuzzleFlow}
              onSubmitMessage={(payload) => {
                void submitPuzzleMessage(payload);
              }}
              onExecuteAction={(payload) => {
                void executePuzzleAction(payload);
              }}
            />
          </motion.div>
        )}

        {selectionStage === 'puzzle-generating' && (
          <motion.div
            key="puzzle-generating"
            initial={{ opacity: 0, y: 12 }}
            animate={{ opacity: 1, y: 0 }}
            exit={{ opacity: 0, y: -12 }}
            className="flex h-full min-h-0 flex-col"
          >
            <Suspense
              fallback={<LazyPanelFallback label="正在加载拼图生成面板..." />}
            >
              <CustomWorldGenerationView
                settingText={
                  puzzleSession?.lastAssistantReply ?? '正在整理当前拼图草稿。'
                }
                anchorEntries={buildPuzzleGenerationAnchorEntries(puzzleSession)}
                progress={buildMiniGameDraftGenerationProgress(
                  puzzleGenerationState,
                )}
                isGenerating={isPuzzleBusy}
                error={puzzleError}
                onBack={leavePuzzleFlow}
                onEditSetting={() => {
                  setSelectionStage('puzzle-agent-workspace');
                }}
                onRetry={() => {
                  void executePuzzleAction({ action: 'compile_puzzle_draft' });
                }}
                onInterrupt={undefined}
                backLabel="返回创作中心"
                settingActionLabel={null}
                retryLabel="重新生成草稿"
                settingTitle="当前拼图信息"
                settingDescription={null}
                progressTitle="拼图草稿生成进度"
                activeBadgeLabel="草稿生成中"
                pausedBadgeLabel="草稿生成已暂停"
                idleBadgeLabel="等待返回工作区"
              />
            </Suspense>
          </motion.div>
        )}

        {selectionStage === 'puzzle-result' && puzzleSession?.draft && (
          <motion.div
            key="puzzle-result"
            initial={{ opacity: 0, y: 12 }}
            animate={{ opacity: 1, y: 0 }}
            exit={{ opacity: 0, y: -12 }}
            className="flex h-full min-h-0 flex-col"
          >
            <PuzzleResultView
              session={puzzleSession}
              author={authUi?.user ?? null}
              isBusy={isPuzzleBusy}
              error={puzzleError}
              onBack={() => {
                setSelectionStage('puzzle-agent-workspace');
              }}
              onExecuteAction={(payload) => {
                void executePuzzleAction(payload);
              }}
            />
          </motion.div>
        )}

        {selectionStage === 'puzzle-gallery-detail' && selectedPuzzleDetail && (
          <motion.div
            key="puzzle-gallery-detail"
            initial={{ opacity: 0, y: 12 }}
            animate={{ opacity: 1, y: 0 }}
            exit={{ opacity: 0, y: -12 }}
            className="flex h-full min-h-0 flex-col"
          >
            <PuzzleGalleryDetailView
              item={selectedPuzzleDetail}
              isBusy={isPuzzleBusy}
              error={puzzleError}
              onBack={() => {
                enterCreateTab();
                setSelectionStage('platform');
              }}
              onStartGame={() => {
                void startPuzzleRunFromProfile(selectedPuzzleDetail.profileId);
              }}
            />
          </motion.div>
        )}

        {selectionStage === 'puzzle-runtime' && (
          <motion.div
            key="puzzle-runtime"
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 }}
            exit={{ opacity: 0 }}
            className="fixed inset-0 z-[100]"
          >
            <PuzzleRuntimeShell
              run={puzzleRun}
              isBusy={isPuzzleBusy || isPuzzleNextLevelGenerating}
              error={puzzleError}
              onBack={() => {
                setSelectionStage('puzzle-gallery-detail');
              }}
              onSwapPieces={(payload) => {
                void swapPuzzlePiecesInRun(payload);
              }}
              onDragPiece={(payload) => {
                void dragPuzzlePiece(payload);
              }}
              onAdvanceNextLevel={() => {
                void advancePuzzleLevel();
              }}
            />
            {isPuzzleNextLevelGenerating ? (
              <div className="fixed inset-0 z-[120] flex items-center justify-center bg-slate-950/62 px-5 backdrop-blur-sm">
                <div className="flex max-w-[18rem] flex-col items-center gap-3 rounded-[1.5rem] border border-white/12 bg-slate-950/92 px-6 py-5 text-center text-white shadow-[0_28px_80px_rgba(0,0,0,0.35)]">
                  <Loader2 className="h-6 w-6 animate-spin text-amber-200" />
                  <div className="text-sm font-bold">正在准备下一关</div>
                  <div className="text-xs leading-5 text-white/68">
                    广场暂无可接续作品，正在生成新的候选图。
                  </div>
                </div>
              </div>
            ) : null}
          </motion.div>
        )}

        {selectionStage === 'custom-world-generating' && (
          <motion.div
            key="custom-world-generating"
            initial={{ opacity: 0, y: 12 }}
            animate={{ opacity: 1, y: 0 }}
            exit={{ opacity: 0, y: -12 }}
            className="flex h-full min-h-0 flex-col"
          >
            <Suspense
              fallback={<LazyPanelFallback label="正在加载世界生成面板..." />}
            >
              <CustomWorldGenerationView
                settingText={sessionController.agentDraftSettingPreview}
                anchorEntries={sessionController.agentDraftAnchorPreviewEntries}
                progress={sessionController.agentDraftGenerationProgress}
                isGenerating={sessionController.isActiveGenerationRunning}
                error={sessionController.activeGenerationError}
                onBack={leaveAgentDraftGeneration}
                onEditSetting={leaveAgentDraftGeneration}
                onRetry={() => {
                  void sessionController.executeAgentAction({
                    action: 'draft_foundation',
                  });
                }}
                onInterrupt={undefined}
                backLabel="返回工作区"
                settingActionLabel={null}
                retryLabel="重新生成草稿"
                settingTitle="当前世界信息"
                settingDescription={null}
                progressTitle="世界草稿生成进度"
                activeBadgeLabel="草稿编译中"
                pausedBadgeLabel="草稿生成已暂停"
                idleBadgeLabel="等待返回工作区"
              />
            </Suspense>
          </motion.div>
        )}

        {selectionStage === 'custom-world-result' &&
          sessionController.generatedCustomWorldProfile && (
            <motion.div
              key="custom-world-result"
              initial={{ opacity: 0, y: 12 }}
              animate={{ opacity: 1, y: 0 }}
              exit={{ opacity: 0, y: -12 }}
              className="flex h-full min-h-0 flex-col"
            >
              <Suspense
                fallback={<LazyPanelFallback label="正在加载世界编辑器..." />}
              >
                <RpgCreationResultView
                  profile={sessionController.generatedCustomWorldProfile}
                  previewCharacters={previewCustomWorldCharacters}
                  isGenerating={false}
                  progress={0}
                  progressLabel=""
                  error={resultViewError}
                  onProfileChange={(profile) => {
                    sessionController.setGeneratedCustomWorldProfile(
                      normalizeAgentBackedProfile(profile),
                    );
                  }}
                  onBack={
                    sessionController.isAgentDraftResultView
                      ? () => {
                          void (async () => {
                            const currentProfile =
                              sessionController.generatedCustomWorldProfile;
                            if (!currentProfile) {
                              leaveAgentDraftResult();
                              return;
                            }

                            await autosaveCoordinator.syncAgentDraftResultProfile(
                              currentProfile,
                            );
                            leaveAgentDraftResult();
                          })().catch((error) => {
                            sessionController.setCustomWorldError(
                              resolveRpgCreationErrorMessage(
                                error,
                                '返回创作前同步草稿失败。',
                              ),
                            );
                          });
                        }
                      : leaveCustomWorldResult
                  }
                  onEditSetting={undefined}
                  onRegenerate={undefined}
                  onContinueExpand={undefined}
                  onEnterWorld={() => {
                    runProtectedAction(() => {
                      void enterWorldCoordinator
                        .enterWorldFromCurrentResult()
                        .catch((error) => {
                          sessionController.setCustomWorldError(
                            resolveRpgCreationErrorMessage(
                              error,
                              '发布并进入世界失败。',
                            ),
                          );
                        });
                    });
                  }}
                  onTestWorld={
                    sessionController.isAgentDraftResultView &&
                    sessionController.agentSession?.stage !== 'published'
                      ? () => {
                          runProtectedAction(() => {
                            void enterWorldCoordinator
                              .enterWorldForTestFromCurrentResult()
                              .catch((error) => {
                                sessionController.setCustomWorldError(
                                  resolveRpgCreationErrorMessage(
                                    error,
                                    '进入作品测试失败。',
                                  ),
                                );
                              });
                          });
                        }
                      : undefined
                  }
                  onPublishWorld={
                    sessionController.isAgentDraftResultView &&
                    sessionController.agentSession?.stage !== 'published'
                      ? async () => {
                          try {
                            await enterWorldCoordinator.publishCurrentResult();
                          } catch (error) {
                            sessionController.setCustomWorldError(
                              resolveRpgCreationErrorMessage(
                                error,
                                '发布到广场失败。',
                              ),
                            );
                            throw error;
                          }
                        }
                      : undefined
                  }
                  onGenerateEntity={
                    sessionController.isAgentDraftResultView
                      ? async (kind) => {
                          const action =
                            kind === 'landmark'
                              ? 'generate_landmarks'
                              : 'generate_characters';
                          const latestSession =
                            await autosaveCoordinator.executeAgentActionAndWait({
                              action,
                              count: 1,
                              ...(kind === 'playable'
                                ? { roleType: 'playable' as const }
                                : kind === 'story'
                                  ? { roleType: 'story' as const }
                                  : {}),
                            });
                          const latestProfile = latestSession
                            ? rpgCreationPreviewAdapter.buildPreviewFromSession(
                                latestSession,
                              )
                            : null;
                          if (latestProfile) {
                            sessionController.setGeneratedCustomWorldProfile(
                              latestProfile,
                            );
                          }
                          return { profile: latestProfile };
                        }
                      : undefined
                  }
                  onDeleteEntities={
                    sessionController.isAgentDraftResultView
                      ? async (kind, ids) => {
                          if (ids.length === 0) return;
                          const latestSession =
                            await autosaveCoordinator.executeAgentActionAndWait(
                              kind === 'story'
                                ? { action: 'delete_characters', roleIds: ids }
                                : { action: 'delete_landmarks', sceneIds: ids },
                            );
                          const latestProfile = latestSession
                            ? rpgCreationPreviewAdapter.buildPreviewFromSession(
                                latestSession,
                              )
                            : null;
                          if (latestProfile) {
                            sessionController.setGeneratedCustomWorldProfile(
                              latestProfile,
                            );
                          }
                        }
                      : undefined
                  }
                  readOnly={false}
                  compactAgentResultMode={
                    sessionController.isAgentDraftResultView
                  }
                  backLabel={
                    sessionController.isAgentDraftResultView
                      ? '返回创作'
                      : undefined
                  }
                  editActionLabel="继续调整设定"
                  enterWorldActionLabel={
                    sessionController.isAgentDraftResultView &&
                    sessionController.agentSession?.stage !== 'published'
                      ? '发布并进入世界'
                      : '进入世界'
                  }
                  publishReady={
                    sessionController.isAgentDraftResultView
                      ? agentResultPublishGateView.publishReady
                      : true
                  }
                  publishBlockers={
                    sessionController.isAgentDraftResultView
                      ? agentResultPublishGateView.blockers
                      : []
                  }
                  qualityFindings={
                    sessionController.isAgentDraftResultView
                      ? agentResultPreviewQualityFindings
                      : []
                  }
                  previewSourceLabel={
                    sessionController.isAgentDraftResultView
                      ? agentResultPreviewSourceLabel
                      : null
                  }
                  autoSaveState={autosaveCoordinator.customWorldAutoSaveState}
                />
              </Suspense>
            </motion.div>
          )}
      </AnimatePresence>

      <PlatformEntryCreationTypeModal
        isOpen={showCreationTypeModal}
        isBusy={
          sessionController.isCreatingAgentSession ||
          isBigFishBusy ||
          isPuzzleBusy
        }
        error={
          bigFishError ?? puzzleError ?? sessionController.creationTypeError
        }
        onClose={() => {
          if (
            sessionController.isCreatingAgentSession ||
            isBigFishBusy ||
            isPuzzleBusy
          ) {
            return;
          }
          setShowCreationTypeModal(false);
        }}
        onSelectRpg={() => {
          runProtectedAction(() => {
            void sessionController.openRpgAgentWorkspace();
          });
        }}
        onSelectBigFish={() => {
          runProtectedAction(() => {
            void openBigFishAgentWorkspace();
          });
        }}
        onSelectPuzzle={() => {
          runProtectedAction(() => {
            void openPuzzleAgentWorkspace();
          });
        }}
      />
      <AnimatePresence>
        {(searchedPublicUser || publicSearchError) && (
          <motion.div
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 }}
            exit={{ opacity: 0 }}
            className="fixed inset-0 z-50 flex items-center justify-center bg-black/45 p-4"
          >
            <div className="platform-surface w-full max-w-md rounded-[1.6rem] p-5">
              <div className="flex items-start justify-between gap-4">
                <div>
                  <div className="text-sm font-semibold text-[var(--platform-text-soft)]">
                    公开编号搜索
                  </div>
                  <div className="mt-1 text-xl font-black text-[var(--platform-text-strong)]">
                    {publicSearchError ? '未找到结果' : '命中用户'}
                  </div>
                </div>
                <button
                  type="button"
                  onClick={() => {
                    setSearchedPublicUser(null);
                    setPublicSearchError(null);
                  }}
                  className="platform-icon-button"
                  aria-label="关闭搜索结果"
                >
                  ×
                </button>
              </div>
              {publicSearchError ? (
                <div className="mt-4 text-sm leading-6 text-[var(--platform-text-soft)]">
                  {publicSearchError}
                </div>
              ) : searchedPublicUser ? (
                <div className="mt-4 rounded-[1.2rem] border border-[var(--platform-line-soft)] p-4">
                  <div className="text-lg font-bold text-[var(--platform-text-strong)]">
                    {searchedPublicUser.displayName}
                  </div>
                  <div className="mt-2 text-sm text-[var(--platform-text-soft)]">
                    叙世号 {searchedPublicUser.publicUserCode}
                  </div>
                </div>
              ) : null}
            </div>
          </motion.div>
        )}
      </AnimatePresence>
    </>
  );
}

export default PlatformEntryFlowShellImpl;
