﻿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 {
  CreateMatch3DSessionRequest,
  ExecuteMatch3DActionRequest,
  Match3DActionResponse,
  Match3DAgentSessionSnapshot,
  Match3DSessionResponse,
  SendMatch3DMessageRequest,
} from '../../../packages/shared/src/contracts/match3dAgent';
import type { Match3DRunSnapshot } from '../../../packages/shared/src/contracts/match3dRuntime';
import type {
  Match3DWorkProfile,
  Match3DWorkSummary,
} from '../../../packages/shared/src/contracts/match3dWorks';
import type {
  PuzzleAgentActionRequest,
  PuzzleAgentOperationRecord,
} from '../../../packages/shared/src/contracts/puzzleAgentActions';
import type { PuzzleResultDraft } from '../../../packages/shared/src/contracts/puzzleAgentDraft';
import type {
  CreatePuzzleAgentSessionRequest,
  PuzzleAgentSessionSnapshot,
  SendPuzzleAgentMessageRequest,
} from '../../../packages/shared/src/contracts/puzzleAgentSession';
import type {
  PuzzleRunSnapshot,
  PuzzleRuntimePropKind,
  SubmitPuzzleLeaderboardRequest,
} from '../../../packages/shared/src/contracts/puzzleRuntimeSession';
import type { PuzzleWorkSummary } from '../../../packages/shared/src/contracts/puzzleWorkSummary';
import type {
  CustomWorldGalleryCard,
  CustomWorldLibraryEntry,
  ProfilePlayedWorkSummary,
  ProfilePlayStatsResponse,
  ProfileSaveArchiveResumeResponse,
  ProfileSaveArchiveSummary,
} from '../../../packages/shared/src/contracts/runtime';
import { buildCustomWorldPlayableCharacters } from '../../data/characterPresets';
import {
  buildPublicWorkStagePath,
  pushAppHistoryPath,
} from '../../routing/appPageRoutes';
import {
  getPublicAuthUserByCode,
  getPublicAuthUserById,
} from '../../services/authService';
import {
  createBigFishCreationSession,
  executeBigFishCreationAction,
  getBigFishCreationSession,
  streamBigFishCreationMessage,
} from '../../services/big-fish-creation';
import {
  likeBigFishGalleryWork,
  listBigFishGallery,
  remixBigFishGalleryWork,
} from '../../services/big-fish-gallery';
import {
  advanceLocalBigFishRuntimeRun,
  recordBigFishPlay,
  startLocalBigFishRuntimeRun,
} from '../../services/big-fish-runtime';
import {
  deleteBigFishWork,
  listBigFishWorks,
} from '../../services/big-fish-works';
import {
  readCustomWorldAgentUiState,
  shouldRestoreCustomWorldAgentUiState,
} from '../../services/customWorldAgentUiState';
import { match3dCreationClient } from '../../services/match3d-creation';
import {
  clickMatch3DItem,
  finishMatch3DTimeUp,
  restartMatch3DRun,
  startMatch3DRun,
  stopMatch3DRun,
} from '../../services/match3d-runtime';
import {
  deleteMatch3DWork,
  getMatch3DWorkDetail,
  listMatch3DGallery,
  listMatch3DWorks,
} from '../../services/match3d-works';
import {
  buildBigFishGenerationAnchorEntries,
  buildMiniGameDraftGenerationProgress,
  buildPuzzleGenerationAnchorEntries,
  createMiniGameDraftGenerationState,
  type MiniGameDraftGenerationState,
} from '../../services/miniGameDraftGenerationProgress';
import { getPlatformProfileDashboard } from '../../services/platform-entry/platformProfileClient';
import {
  buildBigFishPublicWorkCode,
  buildMatch3DPublicWorkCode,
  buildPuzzlePublicWorkCode,
  isSameBigFishPublicWorkCode,
  isSameMatch3DPublicWorkCode,
  isSamePuzzlePublicWorkCode,
} from '../../services/publicWorkCode';
import {
  createPuzzleAgentSession,
  executePuzzleAgentAction,
  getPuzzleAgentSession,
  streamPuzzleAgentMessage,
} from '../../services/puzzle-agent';
import {
  getPuzzleGalleryDetail,
  likePuzzleGalleryWork,
  listPuzzleGallery,
  remixPuzzleGalleryWork,
} from '../../services/puzzle-gallery';
import {
  advanceLocalPuzzleNextLevel,
  advancePuzzleNextLevel,
  getPuzzleRun,
  startPuzzleRun,
  submitPuzzleLeaderboard,
  updatePuzzleRunPause,
  usePuzzleRuntimeProp as consumePuzzleRuntimeProp,
} from '../../services/puzzle-runtime';
import {
  applyLocalPuzzleFreezeTime,
  dragLocalPuzzlePiece,
  extendLocalPuzzleTime,
  isLocalPuzzleRun,
  refreshLocalPuzzleTimer,
  resolvePuzzleRestartLevelId,
  restartLocalPuzzleLevel,
  setLocalPuzzlePaused,
  startLocalPuzzleRun,
  submitLocalPuzzleLeaderboard,
  swapLocalPuzzlePieces,
} from '../../services/puzzle-runtime/puzzleLocalRuntime';
import {
  claimPuzzleWorkPointIncentive,
  deletePuzzleWork,
  listPuzzleWorks,
} from '../../services/puzzle-works';
import { deleteRpgCreationAgentSession } from '../../services/rpg-creation';
import { rpgCreationPreviewAdapter } from '../../services/rpg-creation/rpgCreationPreviewAdapter';
import {
  deleteRpgEntryWorldProfile,
  getRpgEntryWorldGalleryDetailByCode,
  likeRpgEntryWorldGallery,
  recordRpgEntryWorldGalleryPlay,
  remixRpgEntryWorldGallery,
} from '../../services/rpg-entry/rpgEntryLibraryClient';
import { getRpgProfilePlayStats } from '../../services/rpg-entry/rpgProfileClient';
import { requestRpgRuntimeJson } from '../../services/rpg-runtime/rpgRuntimeRequest';
import type { CustomWorldProfile } from '../../types';
import { useAuthUi } from '../auth/AuthUiContext';
import {
  isBigFishGalleryEntry,
  isMatch3DGalleryEntry,
  isPuzzleGalleryEntry,
  mapBigFishWorkToPlatformGalleryCard,
  mapMatch3DWorkToPlatformGalleryCard,
  mapPuzzleWorkToPlatformGalleryCard,
  type PlatformPublicGalleryCard,
} from '../rpg-entry/rpgEntryWorldPresentation';
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 { isPlatformCreationTypeVisible } from './platformEntryCreationTypes';
import {
  PlatformEntryHomeView,
  type PlatformHomeTab,
} from './PlatformEntryHomeView';
import {
  buildCreationHubFallbackItems,
  resolveRpgCreationErrorMessage,
} from './platformEntryShared';
import type { PlatformEntryFlowShellProps } from './platformEntryTypes';
import { PlatformEntryWorldDetailView } from './PlatformEntryWorldDetailView';
import { PlatformWorkDetailView } from './PlatformWorkDetailView';
import { usePlatformCreationAgentFlowController } from './usePlatformCreationAgentFlowController';
import { usePlatformEntryBootstrap } from './usePlatformEntryBootstrap';
import { usePlatformEntryLibraryDetail } from './usePlatformEntryLibraryDetail';
import { usePlatformEntryNavigation } from './usePlatformEntryNavigation';

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

type PuzzleDetailReturnTarget = {
  tab: PlatformHomeTab;
};

type PuzzleRuntimeReturnStage =
  | 'puzzle-result'
  | 'puzzle-gallery-detail'
  | 'work-detail'
  | 'platform';

type BigFishRuntimeReturnStage = 'big-fish-result' | 'work-detail' | 'platform';

type PuzzleSaveArchiveState = {
  runtimeKind?: unknown;
  entryProfileId?: unknown;
  currentProfileId?: unknown;
  currentLevelId?: unknown;
};

async function resumePuzzleProfileSaveArchiveRaw(worldKey: string) {
  return requestRpgRuntimeJson<
    ProfileSaveArchiveResumeResponse<PuzzleSaveArchiveState>
  >(
    `/profile/save-archives/${encodeURIComponent(worldKey)}`,
    { method: 'POST' },
    '恢复拼图存档失败',
  );
}

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 getPlatformPublicGalleryEntryTime(entry: PlatformPublicGalleryCard) {
  const rawTime = entry.publishedAt ?? entry.updatedAt;
  const timestamp = new Date(rawTime).getTime();
  return Number.isNaN(timestamp) ? 0 : timestamp;
}

function getPlatformPublicGalleryEntryKey(entry: PlatformPublicGalleryCard) {
  const kind = isBigFishGalleryEntry(entry)
    ? 'big-fish'
    : isPuzzleGalleryEntry(entry)
      ? 'puzzle'
      : isMatch3DGalleryEntry(entry)
        ? 'match3d'
        : 'rpg';
  return `${kind}:${entry.ownerUserId}:${entry.profileId}`;
}

function isSamePlatformPublicGalleryEntry(
  left: PlatformPublicGalleryCard,
  right: PlatformPublicGalleryCard,
) {
  return (
    getPlatformPublicGalleryEntryKey(left) ===
    getPlatformPublicGalleryEntryKey(right)
  );
}

function mergePlatformPublicGalleryEntries(
  rpgEntries: CustomWorldGalleryCard[],
  puzzleEntries: PlatformPublicGalleryCard[],
) {
  const entryMap = new Map<string, PlatformPublicGalleryCard>();

  [...rpgEntries, ...puzzleEntries].forEach((entry) => {
    entryMap.set(getPlatformPublicGalleryEntryKey(entry), entry);
  });

  return Array.from(entryMap.values()).sort(
    (left, right) =>
      getPlatformPublicGalleryEntryTime(right) -
      getPlatformPublicGalleryEntryTime(left),
  );
}

function mapRpgGalleryCardToPublicWorkDetail(
  entry: CustomWorldGalleryCard,
): PlatformPublicGalleryCard {
  return entry;
}

function mapPuzzleWorkToPublicWorkDetail(
  item: PuzzleWorkSummary,
): PlatformPublicGalleryCard {
  return mapPuzzleWorkToPlatformGalleryCard(item);
}

function mapMatch3DWorkToPublicWorkDetail(
  item: Match3DWorkSummary,
): PlatformPublicGalleryCard {
  return mapMatch3DWorkToPlatformGalleryCard(item);
}

function mapBigFishWorkToPublicWorkDetail(
  item: BigFishWorkSummary,
): PlatformPublicGalleryCard {
  return mapBigFishWorkToPlatformGalleryCard(item);
}

function mapPublicWorkDetailToMatch3DWork(
  entry: PlatformPublicGalleryCard,
): Match3DWorkSummary | null {
  if (!isMatch3DGalleryEntry(entry)) {
    return null;
  }

  return {
    workId: entry.workId,
    profileId: entry.profileId,
    ownerUserId: entry.ownerUserId,
    sourceSessionId: null,
    gameName: entry.worldName,
    themeText: entry.themeTags[0] ?? '经典消除',
    summary: entry.summaryText,
    tags: entry.themeTags,
    coverImageSrc: entry.coverImageSrc,
    referenceImageSrc: null,
    clearCount: 12,
    difficulty: 4,
    publicationStatus: 'published',
    playCount: entry.playCount ?? 0,
    updatedAt: entry.updatedAt,
    publishedAt: entry.publishedAt,
    publishReady: true,
  };
}

function buildMatch3DProfileFromSession(
  session: Match3DAgentSessionSnapshot | null,
): Match3DWorkProfile | null {
  const draft = session?.draft;
  if (!session || !draft?.profileId) {
    return null;
  }

  const now = session.updatedAt || new Date().toISOString();
  return {
    workId: draft.profileId,
    profileId: draft.profileId,
    ownerUserId: 'current-user',
    sourceSessionId: session.sessionId,
    gameName: draft.gameName,
    themeText: draft.themeText,
    summary: draft.summary ?? draft.summaryText ?? '',
    tags: draft.tags,
    coverImageSrc: draft.coverImageSrc ?? draft.referenceImageSrc ?? null,
    referenceImageSrc: draft.referenceImageSrc ?? null,
    clearCount: draft.clearCount,
    difficulty: draft.difficulty,
    publicationStatus: 'draft',
    playCount: 0,
    updatedAt: now,
    publishedAt: null,
    publishReady: Boolean(draft.publishReady),
  };
}

function mapPublicWorkDetailToPuzzleWork(
  entry: PlatformPublicGalleryCard,
): PuzzleWorkSummary | null {
  if (!isPuzzleGalleryEntry(entry)) {
    return null;
  }

  return {
    workId: entry.workId,
    profileId: entry.profileId,
    ownerUserId: entry.ownerUserId,
    sourceSessionId: null,
    authorDisplayName: entry.authorDisplayName,
    levelName: entry.worldName,
    summary: entry.summaryText,
    themeTags: entry.themeTags,
    coverImageSrc: entry.coverImageSrc,
    publicationStatus: 'published',
    updatedAt: entry.updatedAt,
    publishedAt: entry.publishedAt,
    playCount: entry.playCount ?? 0,
    remixCount: entry.remixCount ?? 0,
    likeCount: entry.likeCount ?? 0,
    pointIncentiveTotalHalfPoints: 0,
    pointIncentiveClaimedPoints: 0,
    pointIncentiveTotalPoints: 0,
    pointIncentiveClaimablePoints: 0,
    publishReady: true,
    levels:
      entry.coverSlides?.map((slide, index) => ({
        levelId: slide.id || `puzzle-level-${index + 1}`,
        levelName: slide.label,
        pictureDescription: entry.summaryText,
        candidates: [],
        selectedCandidateId: null,
        coverImageSrc: slide.imageSrc,
        coverAssetId: null,
        generationStatus: 'ready' as const,
      })) ?? [],
  };
}

function mapPublicWorkDetailToBigFishWork(
  entry: PlatformPublicGalleryCard,
): BigFishWorkSummary | null {
  if (!isBigFishGalleryEntry(entry)) {
    return null;
  }

  const levelCount = Number.parseInt(
    entry.themeTags.find((tag) => /^\d+级$/u.test(tag))?.replace('级', '') ??
      '0',
    10,
  );

  return {
    workId: entry.workId,
    sourceSessionId: entry.profileId,
    ownerUserId: entry.ownerUserId,
    authorDisplayName: entry.authorDisplayName,
    title: entry.worldName,
    subtitle: entry.subtitle,
    summary: entry.summaryText,
    coverImageSrc: entry.coverImageSrc,
    status: 'published',
    updatedAt: entry.updatedAt,
    publishedAt: entry.publishedAt,
    publishReady: true,
    levelCount: Number.isNaN(levelCount) ? 0 : levelCount,
    levelMainImageReadyCount: 0,
    levelMotionReadyCount: 0,
    backgroundReady: Boolean(entry.coverImageSrc),
    playCount: entry.playCount ?? 0,
    remixCount: entry.remixCount ?? 0,
    likeCount: entry.likeCount ?? 0,
  };
}

function mergePuzzleWorkSummary(
  current: PuzzleWorkSummary,
  updated: PuzzleWorkSummary,
): PuzzleWorkSummary {
  return current.profileId === updated.profileId ? updated : current;
}

function mergeBigFishWorkSummary(
  current: BigFishWorkSummary,
  updated: BigFishWorkSummary,
): BigFishWorkSummary {
  return current.sourceSessionId === updated.sourceSessionId
    ? updated
    : current;
}

async function resolvePublicWorkAuthorSummary(
  entry: PlatformPublicGalleryCard,
): Promise<PublicUserSummary | null> {
  if ('authorPublicUserCode' in entry && entry.authorPublicUserCode?.trim()) {
    try {
      return await getPublicAuthUserByCode(entry.authorPublicUserCode);
    } catch {
      if (!entry.ownerUserId.trim()) {
        return null;
      }
    }
  }

  if (entry.ownerUserId.trim()) {
    return getPublicAuthUserById(entry.ownerUserId);
  }

  return null;
}

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',
        'anchorContent.worldPromise.hook',
        'settingText',
      ]),
    );
  }
  if (code === 'publish_missing_player_premise') {
    return Boolean(
      readProfileTextField(profile, [
        'playerPremise',
        'creatorIntent.playerPremise',
        'anchorContent.playerEntryPoint',
        '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,
  };
}

function buildPuzzleResultProfileId(sessionId: string | null | undefined) {
  const normalizedSessionId = sessionId?.trim();
  if (!normalizedSessionId) {
    return null;
  }
  const stableSuffix = normalizedSessionId.startsWith('puzzle-session-')
    ? normalizedSessionId.slice('puzzle-session-'.length)
    : normalizedSessionId;
  return `puzzle-profile-${stableSuffix}`;
}

function buildPuzzleCompileActionFromFormPayload(
  payload: CreatePuzzleAgentSessionRequest | null,
): PuzzleAgentActionRequest {
  const workTitle = payload?.workTitle?.trim() || payload?.seedText?.trim();
  const workDescription = payload?.workDescription?.trim();
  const pictureDescription = payload?.pictureDescription?.trim();

  return {
    action: 'compile_puzzle_draft',
    promptText: pictureDescription || workTitle,
    ...(workTitle ? { workTitle } : {}),
    ...(workDescription ? { workDescription } : {}),
    ...(pictureDescription ? { pictureDescription } : {}),
    referenceImageSrc: payload?.referenceImageSrc || null,
    candidateCount: 1,
  };
}

function buildPuzzleFormPayloadFromSession(
  session: PuzzleAgentSessionSnapshot,
): CreatePuzzleAgentSessionRequest {
  const formDraft = session.draft?.formDraft;
  const workTitle =
    formDraft?.workTitle?.trim() ||
    session.draft?.workTitle?.trim() ||
    session.draft?.levelName?.trim() ||
    session.anchorPack.themePromise.value.trim() ||
    session.seedText?.trim() ||
    '';
  const workDescription =
    formDraft?.workDescription?.trim() ||
    session.draft?.workDescription?.trim() ||
    session.draft?.summary?.trim() ||
    '';
  const pictureDescription =
    formDraft?.pictureDescription?.trim() ||
    session.draft?.levels?.[0]?.pictureDescription?.trim() ||
    session.anchorPack.visualSubject.value.trim() ||
    '';

  return {
    seedText: workTitle,
    workTitle,
    workDescription,
    pictureDescription,
    referenceImageSrc: null,
  };
}

function buildPuzzleFormPayloadFromAction(
  payload: PuzzleAgentActionRequest,
): CreatePuzzleAgentSessionRequest | null {
  if (
    payload.action !== 'compile_puzzle_draft' &&
    payload.action !== 'save_puzzle_form_draft'
  ) {
    return null;
  }

  const workTitle = payload.workTitle?.trim() ?? '';
  const workDescription = payload.workDescription?.trim() ?? '';
  const pictureDescription =
    payload.pictureDescription?.trim() || payload.promptText?.trim() || '';

  return {
    seedText: workTitle,
    workTitle,
    workDescription,
    pictureDescription,
    referenceImageSrc:
      payload.action === 'compile_puzzle_draft'
        ? (payload.referenceImageSrc ?? null)
        : null,
  };
}

function isPuzzleFormOnlyDraft(session: PuzzleAgentSessionSnapshot | null) {
  return Boolean(
    session?.stage === 'collecting_anchors' && session.draft?.formDraft,
  );
}

function isEmptyPuzzleFormOnlyDraft(
  session: PuzzleAgentSessionSnapshot | null,
) {
  if (!isPuzzleFormOnlyDraft(session)) {
    return false;
  }

  const formDraft = session?.draft?.formDraft;
  return !(
    session?.seedText?.trim() ||
    formDraft?.workTitle?.trim() ||
    formDraft?.workDescription?.trim() ||
    formDraft?.pictureDescription?.trim()
  );
}

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,
  };
});

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

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

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

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

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

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

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

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

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>
  );
}

function mergePuzzleServiceRuntimeState(
  currentRun: PuzzleRunSnapshot,
  serviceRun: PuzzleRunSnapshot,
): PuzzleRunSnapshot {
  if (!currentRun.currentLevel || !serviceRun.currentLevel) {
    return currentRun;
  }

  const serviceLevel = serviceRun.currentLevel;
  if (
    currentRun.currentLevel.status === 'cleared' &&
    serviceLevel.status !== 'cleared'
  ) {
    return {
      ...currentRun,
      recommendedNextProfileId: serviceRun.recommendedNextProfileId,
      nextLevelMode: serviceRun.nextLevelMode,
      nextLevelProfileId: serviceRun.nextLevelProfileId,
      nextLevelId: serviceRun.nextLevelId,
      recommendedNextWorks: serviceRun.recommendedNextWorks,
      leaderboardEntries:
        currentRun.currentLevel.leaderboardEntries.length > 0
          ? currentRun.currentLevel.leaderboardEntries
          : currentRun.leaderboardEntries,
    };
  }

  const leaderboardEntries =
    serviceLevel.leaderboardEntries.length > 0
      ? serviceLevel.leaderboardEntries
      : serviceRun.leaderboardEntries;

  return {
    ...currentRun,
    recommendedNextProfileId: serviceRun.recommendedNextProfileId,
    nextLevelMode: serviceRun.nextLevelMode,
    nextLevelProfileId: serviceRun.nextLevelProfileId,
    nextLevelId: serviceRun.nextLevelId,
    recommendedNextWorks: serviceRun.recommendedNextWorks,
    leaderboardEntries,
    currentLevel: {
      ...currentRun.currentLevel,
      status: serviceLevel.status,
      startedAtMs: serviceLevel.startedAtMs,
      clearedAtMs: serviceLevel.clearedAtMs,
      elapsedMs: serviceLevel.elapsedMs,
      timeLimitMs: serviceLevel.timeLimitMs,
      remainingMs: serviceLevel.remainingMs,
      pausedAccumulatedMs: serviceLevel.pausedAccumulatedMs,
      pauseStartedAtMs: serviceLevel.pauseStartedAtMs,
      freezeAccumulatedMs: serviceLevel.freezeAccumulatedMs,
      freezeStartedAtMs: serviceLevel.freezeStartedAtMs,
      freezeUntilMs: serviceLevel.freezeUntilMs,
      leaderboardEntries,
    },
  };
}

export function PlatformEntryFlowShellImpl({
  selectionStage,
  setSelectionStage,
  hasSavedGame,
  savedSnapshot,
  handleContinueGame,
  handleStartNewGame,
  handleCustomWorldSelect,
  initialPublicWorkCode,
}: PlatformEntryFlowShellProps) {
  const authUi = useAuthUi();
  const [showCreationTypeModal, setShowCreationTypeModal] = useState(false);
  const [selectedDetailEntry, setSelectedDetailEntry] =
    useState<CustomWorldLibraryEntry<CustomWorldProfile> | null>(null);
  const [selectedPublicWorkDetail, setSelectedPublicWorkDetail] =
    useState<PlatformPublicGalleryCard | null>(null);
  const [selectedPublicWorkAuthor, setSelectedPublicWorkAuthor] =
    useState<PublicUserSummary | null>(null);
  const publicWorkAuthorRequestKeyRef = useRef(0);
  const [publicWorkDetailError, setPublicWorkDetailError] = useState<
    string | null
  >(null);
  const [isPublicWorkDetailBusy, setIsPublicWorkDetailBusy] = useState(false);
  const [bigFishWorks, setBigFishWorks] = useState<BigFishWorkSummary[]>([]);
  const [bigFishGalleryEntries, setBigFishGalleryEntries] = useState<
    BigFishWorkSummary[]
  >([]);
  const [match3dWorks, setMatch3DWorks] = useState<Match3DWorkSummary[]>([]);
  const [match3dGalleryEntries, setMatch3DGalleryEntries] = useState<
    Match3DWorkSummary[]
  >([]);
  const [match3dProfile, setMatch3DProfile] =
    useState<Match3DWorkProfile | null>(null);
  const [match3dRun, setMatch3DRun] = useState<Match3DRunSnapshot | null>(null);
  const [match3dRuntimeReturnStage, setMatch3DRuntimeReturnStage] =
    useState<'match3d-result' | 'work-detail'>('match3d-result');
  const [isMatch3DLoadingLibrary, setIsMatch3DLoadingLibrary] = useState(false);
  const [bigFishRun, setBigFishRun] =
    useState<BigFishRuntimeSnapshotResponse | null>(null);
  const [bigFishRuntimeShare, setBigFishRuntimeShare] = useState<{
    title: string;
    publicWorkCode: string;
  } | null>(null);
  const [bigFishRuntimeWork, setBigFishRuntimeWork] =
    useState<BigFishWorkSummary | null>(null);
  const [bigFishRuntimeStartedAt, setBigFishRuntimeStartedAt] = useState<
    number | null
  >(null);
  const [bigFishRuntimeReturnStage, setBigFishRuntimeReturnStage] =
    useState<BigFishRuntimeReturnStage>('platform');
  const [isBigFishLoadingLibrary, setIsBigFishLoadingLibrary] = useState(false);
  const [bigFishGenerationState, setBigFishGenerationState] =
    useState<MiniGameDraftGenerationState | null>(null);
  const [, setPuzzleOperation] = useState<PuzzleAgentOperationRecord | null>(
    null,
  );
  const [puzzleWorks, setPuzzleWorks] = useState<PuzzleWorkSummary[]>([]);
  const [puzzleGalleryEntries, setPuzzleGalleryEntries] = useState<
    PuzzleWorkSummary[]
  >([]);
  const [selectedPuzzleDetail, setSelectedPuzzleDetail] =
    useState<PuzzleWorkSummary | null>(null);
  const [puzzleDetailReturnTarget, setPuzzleDetailReturnTarget] =
    useState<PuzzleDetailReturnTarget | null>(null);
  const [puzzleRuntimeReturnStage, setPuzzleRuntimeReturnStage] =
    useState<PuzzleRuntimeReturnStage>('puzzle-gallery-detail');
  const [isPuzzleLeaderboardBusy, setIsPuzzleLeaderboardBusy] = useState(false);
  const submittedPuzzleLeaderboardKeysRef = useRef(new Set<string>());
  const [puzzleRun, setPuzzleRun] = useState<PuzzleRunSnapshot | null>(null);
  const puzzleRunRef = useRef<PuzzleRunSnapshot | null>(null);
  const [isPuzzleLoadingLibrary, setIsPuzzleLoadingLibrary] = useState(false);
  const [puzzleGenerationState, setPuzzleGenerationState] =
    useState<MiniGameDraftGenerationState | null>(null);
  const [puzzleFormDraftPayload, setPuzzleFormDraftPayload] =
    useState<CreatePuzzleAgentSessionRequest | 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 [claimingPuzzlePointIncentiveProfileId, setClaimingPuzzlePointIncentiveProfileId] =
    useState<string | null>(null);
  const isBigFishCreationVisible = isPlatformCreationTypeVisible('big-fish');
  const [profilePlayStats, setProfilePlayStats] =
    useState<ProfilePlayStatsResponse | null>(null);
  const [profilePlayStatsError, setProfilePlayStatsError] = useState<
    string | null
  >(null);
  const [isProfilePlayStatsLoading, setIsProfilePlayStatsLoading] =
    useState(false);
  const [isProfilePlayStatsOpen, setIsProfilePlayStatsOpen] = useState(false);
  const hadReadableProtectedDataRef = useRef(false);
  const hasInitialAgentSession = Boolean(
    readCustomWorldAgentUiState().activeSessionId &&
      shouldRestoreCustomWorldAgentUiState(),
  );
  const handledInitialPublicWorkCodeRef = useRef<string | null>(null);

  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 resolveBigFishErrorMessage = useCallback(
    (error: unknown, fallback: string) =>
      resolveRpgCreationErrorMessage(error, fallback),
    [],
  );
  const resolvePuzzleErrorMessage = useCallback(
    (error: unknown, fallback: string) =>
      resolveRpgCreationErrorMessage(error, fallback),
    [],
  );
  const resolveMatch3DErrorMessage = 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 refreshBigFishGallery = useCallback(async () => {
    try {
      const galleryResponse = await listBigFishGallery();
      setBigFishGalleryEntries(galleryResponse.items);
      return galleryResponse.items;
    } catch (error) {
      setBigFishGalleryEntries([]);
      setBigFishError(
        resolveBigFishErrorMessage(error, '读取大鱼吃小鱼广场失败。'),
      );
      return [];
    }
  }, [resolveBigFishErrorMessage]);

  const refreshMatch3DShelf = useCallback(async () => {
    setIsMatch3DLoadingLibrary(true);

    try {
      const worksResponse = await listMatch3DWorks();
      setMatch3DWorks(worksResponse.items);
      setMatch3DError(null);
    } catch (error) {
      setMatch3DError(
        resolveMatch3DErrorMessage(error, '读取抓大鹅作品列表失败。'),
      );
    } finally {
      setIsMatch3DLoadingLibrary(false);
    }
  }, [resolveMatch3DErrorMessage]);

  const refreshMatch3DGallery = useCallback(async () => {
    try {
      const galleryResponse = await listMatch3DGallery();
      setMatch3DGalleryEntries(galleryResponse.items);
      return galleryResponse.items;
    } catch {
      // 中文注释：公开广场是首页展示数据，失败时只降级为空列表；
      // 不写入创作错误态，避免挡住抓大鹅共创入口。
      setMatch3DGalleryEntries([]);
      return [];
    }
  }, []);

  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 refreshPuzzleGallery = useCallback(async () => {
    try {
      const galleryResponse = await listPuzzleGallery();
      setPuzzleGalleryEntries(galleryResponse.items);
      return galleryResponse.items;
    } catch (error) {
      setPuzzleGalleryEntries([]);
      setPuzzleError(resolvePuzzleErrorMessage(error, '读取拼图广场失败。'));
      return [];
    }
  }, [resolvePuzzleErrorMessage]);

  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,
    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,
    syncAgentCreationResultView: sessionController.syncAgentCreationResultView,
    buildDraftResultProfile: (view) =>
      rpgCreationPreviewAdapter.buildPreviewFromResultView(view),
  });

  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,
    syncAgentCreationResultView: sessionController.syncAgentCreationResultView,
    buildDraftResultProfile: (view) =>
      rpgCreationPreviewAdapter.buildPreviewFromResultView(view),
    suppressAgentDraftResultAutoOpen:
      sessionController.suppressAgentDraftResultAutoOpen,
    releaseAgentDraftResultAutoOpenSuppression:
      sessionController.releaseAgentDraftResultAutoOpenSuppression,
    resetAutoSaveTrackingToIdle:
      autosaveCoordinator.resetAutoSaveTrackingToIdle,
    markAutoSavedProfile: autosaveCoordinator.markAutoSavedProfile,
  });

  const enterWorldCoordinator = useRpgCreationEnterWorld({
    isAgentDraftResultView: sessionController.isAgentDraftResultView,
    activeAgentSessionId: sessionController.activeAgentSessionId,
    generatedCustomWorldProfile: sessionController.generatedCustomWorldProfile,
    handleCustomWorldSelect,
    syncAgentDraftResultProfile:
      autosaveCoordinator.syncAgentDraftResultProfile,
    executePublishWorld: async () => {
      const latestSession = await autosaveCoordinator.executeAgentActionAndWait(
        {
          action: 'publish_world',
        },
      );
      // 发布动作会在后端同步 gallery 投影；前端发布完成后立即刷新首页/分类页共用的公开作品列表。
      await Promise.allSettled([
        platformBootstrap.refreshPublishedGallery(),
        platformBootstrap.refreshCustomWorldWorks(),
        isBigFishCreationVisible
          ? refreshBigFishGallery()
          : Promise.resolve([] as BigFishWorkSummary[]),
        refreshMatch3DGallery(),
        refreshPuzzleGallery(),
      ]);
      return latestSession;
    },
    syncAgentCreationResultView: sessionController.syncAgentCreationResultView,
    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(() => {
    const bigFishPublicEntries = isBigFishCreationVisible
      ? bigFishGalleryEntries.map(mapBigFishWorkToPlatformGalleryCard)
      : [];
    const match3dPublicEntries = match3dGalleryEntries.map(
      mapMatch3DWorkToPlatformGalleryCard,
    );
    const puzzlePublicEntries = puzzleGalleryEntries.map(
      mapPuzzleWorkToPlatformGalleryCard,
    );
    return mergePlatformPublicGalleryEntries(
      platformBootstrap.publishedGalleryEntries,
      [...bigFishPublicEntries, ...match3dPublicEntries, ...puzzlePublicEntries],
    ).slice(0, 6);
  }, [
    isBigFishCreationVisible,
    bigFishGalleryEntries,
    match3dGalleryEntries,
    platformBootstrap.publishedGalleryEntries,
    puzzleGalleryEntries,
  ]);
  const latestGalleryEntries = useMemo(
    () =>
      mergePlatformPublicGalleryEntries(
        platformBootstrap.publishedGalleryEntries,
        [
          ...(isBigFishCreationVisible
            ? bigFishGalleryEntries.map(mapBigFishWorkToPlatformGalleryCard)
            : []),
          ...match3dGalleryEntries.map(mapMatch3DWorkToPlatformGalleryCard),
          ...puzzleGalleryEntries.map(mapPuzzleWorkToPlatformGalleryCard),
        ],
      ),
    [
      isBigFishCreationVisible,
      bigFishGalleryEntries,
      match3dGalleryEntries,
      platformBootstrap.publishedGalleryEntries,
      puzzleGalleryEntries,
    ],
  );

  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,
  ]);

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

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

  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 bigFishFlow = usePlatformCreationAgentFlowController<
    BigFishSessionSnapshotResponse,
    Record<string, never>,
    { session: BigFishSessionSnapshotResponse },
    SendBigFishMessageRequest,
    ExecuteBigFishActionRequest,
    { session: BigFishSessionSnapshotResponse }
  >({
    client: {
      createSession: createBigFishCreationSession,
      getSession: getBigFishCreationSession,
      streamMessage: streamBigFishCreationMessage,
      executeAction: executeBigFishCreationAction,
      selectSession: (response) => response.session,
    },
    createPayload: {},
    workspaceStage: 'big-fish-agent-workspace',
    resultStage: 'big-fish-result',
    platformStage: 'platform',
    isCompileAction: (payload) => payload.action === 'big_fish_compile_draft',
    resolveErrorMessage: resolveBigFishErrorMessage,
    errorMessages: {
      open: '开启大鱼吃小鱼共创工作台失败。',
      restoreMissingSession: '这份大鱼吃小鱼草稿缺少会话信息，请重新开始创作。',
      restore: '读取大鱼吃小鱼创作草稿失败。',
      submit: '发送大鱼吃小鱼共创消息失败。',
      execute: '执行大鱼吃小鱼操作失败。',
    },
    enterCreateTab,
    setSelectionStage,
    onSessionOpened: () => {
      setShowCreationTypeModal(false);
    },
    onActionComplete: ({ payload, response, setSession }) => {
      setSession(response.session);
      if (payload.action === 'big_fish_publish_game') {
        void refreshBigFishShelf();
        void refreshBigFishGallery();
      }
      if (payload.action !== 'big_fish_compile_draft') {
        return;
      }
      setBigFishGenerationState((current) =>
        current
          ? {
              ...current,
              phase: 'ready',
              completedAssetCount: response.session.assetSlots.filter(
                (slot) => slot.status === 'ready',
              ).length,
              totalAssetCount: response.session.assetSlots.length,
            }
          : current,
      );
    },
    beforeExecuteAction: ({ payload }) => {
      if (payload.action !== 'big_fish_compile_draft') {
        return;
      }
      setSelectionStage('big-fish-generating');
      setBigFishGenerationState(createMiniGameDraftGenerationState('big-fish'));
    },
    onActionError: ({ payload, errorMessage }) => {
      if (payload.action !== 'big_fish_compile_draft') {
        return;
      }
      setBigFishGenerationState((current) =>
        current
          ? {
              ...current,
              phase: 'failed',
              error: errorMessage,
            }
          : current,
      );
    },
  });

  const match3dFlow = usePlatformCreationAgentFlowController<
    Match3DAgentSessionSnapshot,
    CreateMatch3DSessionRequest,
    Match3DSessionResponse,
    SendMatch3DMessageRequest,
    ExecuteMatch3DActionRequest,
    Match3DActionResponse
  >({
    client: {
      createSession: match3dCreationClient.createSession,
      getSession: match3dCreationClient.getSession,
      streamMessage: match3dCreationClient.streamMessage,
      executeAction: match3dCreationClient.executeAction,
      selectSession: (response) => response.session,
    },
    createPayload: {},
    workspaceStage: 'match3d-agent-workspace',
    resultStage: 'match3d-result',
    platformStage: 'platform',
    isCompileAction: (payload) => payload.action === 'match3d_compile_draft',
    resolveErrorMessage: resolveMatch3DErrorMessage,
    errorMessages: {
      open: '开启抓大鹅共创工作台失败。',
      restoreMissingSession: '这份抓大鹅草稿缺少会话信息，请重新开始创作。',
      restore: '读取抓大鹅创作草稿失败。',
      submit: '发送抓大鹅共创消息失败。',
      execute: '执行抓大鹅操作失败。',
    },
    enterCreateTab,
    setSelectionStage,
    onSessionOpened: () => {
      setShowCreationTypeModal(false);
    },
    onActionComplete: async ({ payload, response, setSession }) => {
      setSession(response.session);
      if (payload.action !== 'match3d_compile_draft') {
        return;
      }

      const profileId = response.session.draft?.profileId;
      if (!profileId) {
        setMatch3DProfile(null);
        return;
      }

      try {
        const { item } = await getMatch3DWorkDetail(profileId);
        setMatch3DProfile(item);
        await refreshMatch3DShelf().catch(() => undefined);
      } catch {
        setMatch3DProfile(buildMatch3DProfileFromSession(response.session));
      }
    },
  });

  const puzzleFlow = usePlatformCreationAgentFlowController<
    PuzzleAgentSessionSnapshot,
    CreatePuzzleAgentSessionRequest,
    { session: PuzzleAgentSessionSnapshot },
    SendPuzzleAgentMessageRequest,
    PuzzleAgentActionRequest,
    {
      operation: PuzzleAgentOperationRecord;
      session: PuzzleAgentSessionSnapshot;
    }
  >({
    client: {
      createSession: createPuzzleAgentSession,
      getSession: getPuzzleAgentSession,
      streamMessage: streamPuzzleAgentMessage,
      executeAction: executePuzzleAgentAction,
      selectSession: (response) => response.session,
    },
    createPayload: {},
    workspaceStage: 'puzzle-agent-workspace',
    resultStage: 'puzzle-result',
    platformStage: 'platform',
    isCompileAction: (payload) => payload.action === 'compile_puzzle_draft',
    resolveErrorMessage: resolvePuzzleErrorMessage,
    errorMessages: {
      open: '开启拼图共创工作台失败。',
      restoreMissingSession: '这份拼图草稿缺少会话信息，请重新开始创作。',
      restore: '读取拼图创作草稿失败。',
      submit: '发送拼图共创消息失败。',
      execute: '执行拼图操作失败。',
    },
    enterCreateTab,
    setSelectionStage,
    onSessionOpened: () => {
      setShowCreationTypeModal(false);
    },
    onActionComplete: async ({ payload, response, setSession }) => {
      setPuzzleOperation(response.operation);
      setSession(response.session);
      const formPayload = buildPuzzleFormPayloadFromAction(payload);
      if (formPayload) {
        setPuzzleFormDraftPayload(formPayload);
      }

      if (payload.action === 'publish_puzzle_work') {
        await Promise.allSettled([
          refreshPuzzleShelf(),
          refreshPuzzleGallery(),
        ]);
      }

      if (payload.action === 'compile_puzzle_draft') {
        setPuzzleGenerationState((current) =>
          current
            ? {
                ...current,
                phase: 'ready',
                completedAssetCount: 1,
                totalAssetCount: 1,
              }
            : current,
        );
      }

      if (
        payload.action === 'publish_puzzle_work' &&
        response.session.publishedProfileId
      ) {
        const galleryDetail = await getPuzzleGalleryDetail(
          response.session.publishedProfileId,
        );
        setSelectedPuzzleDetail(galleryDetail.item);
        const detailEntry = mapPuzzleWorkToPublicWorkDetail(galleryDetail.item);
        setSelectedPublicWorkDetail(detailEntry);
        setPublicWorkDetailError(null);
        setSelectionStage('work-detail');
        pushAppHistoryPath(
          buildPublicWorkStagePath(
            'work-detail',
            buildPuzzlePublicWorkCode(galleryDetail.item.profileId),
          ),
        );
      }
    },
    beforeExecuteAction: ({ payload }) => {
      const formPayload = buildPuzzleFormPayloadFromAction(payload);
      if (formPayload) {
        setPuzzleFormDraftPayload(formPayload);
      }

      if (payload.action !== 'compile_puzzle_draft') {
        return;
      }
      setSelectionStage('puzzle-generating');
      setPuzzleGenerationState(createMiniGameDraftGenerationState('puzzle'));
    },
    onActionError: ({ payload, errorMessage }) => {
      if (payload.action !== 'compile_puzzle_draft') {
        return;
      }
      setPuzzleGenerationState((current) =>
        current
          ? {
              ...current,
              phase: 'failed',
              error: errorMessage,
            }
          : current,
      );
    },
  });

  const bigFishSession = bigFishFlow.session;
  const bigFishError = bigFishFlow.error;
  const setBigFishError = bigFishFlow.setError;
  const isBigFishBusy = bigFishFlow.isBusy;
  const streamingBigFishReplyText = bigFishFlow.streamingReplyText;
  const isStreamingBigFishReply = bigFishFlow.isStreamingReply;

  const match3dSession = match3dFlow.session;
  const match3dError = match3dFlow.error;
  const setMatch3DSession = match3dFlow.setSession;
  const setMatch3DError = match3dFlow.setError;
  const isMatch3DBusy = match3dFlow.isBusy;
  const streamingMatch3DReplyText = match3dFlow.streamingReplyText;
  const setStreamingMatch3DReplyText = match3dFlow.setStreamingReplyText;
  const isStreamingMatch3DReply = match3dFlow.isStreamingReply;
  const setIsStreamingMatch3DReply = match3dFlow.setIsStreamingReply;

  const puzzleSession = puzzleFlow.session;
  const puzzleError = puzzleFlow.error;
  const setPuzzleError = puzzleFlow.setError;
  const isPuzzleBusy = puzzleFlow.isBusy;
  const setIsPuzzleBusy = puzzleFlow.setIsBusy;
  const isStreamingPuzzleReply = puzzleFlow.isStreamingReply;
  const resetRpgSessionViewState = sessionController.resetSessionViewState;
  const setRpgGeneratedCustomWorldProfile =
    sessionController.setGeneratedCustomWorldProfile;
  const setRpgCustomWorldError = sessionController.setCustomWorldError;
  const persistRpgAgentUiState = sessionController.persistAgentUiState;
  const resetAutoSaveTrackingToIdle =
    autosaveCoordinator.resetAutoSaveTrackingToIdle;

  useEffect(() => {
    puzzleRunRef.current = puzzleRun;
  }, [puzzleRun]);

  const openBigFishAgentWorkspace = useCallback(async () => {
    setBigFishRun(null);
    await bigFishFlow.openWorkspace();
  }, [bigFishFlow]);

  const openMatch3DAgentWorkspace = useCallback(async () => {
    setMatch3DSession(null);
    setMatch3DProfile(null);
    setMatch3DRun(null);
    setMatch3DError(null);
    setStreamingMatch3DReplyText('');
    setIsStreamingMatch3DReply(false);
    await match3dFlow.openWorkspace();
  }, [
    match3dFlow,
    setIsStreamingMatch3DReply,
    setMatch3DError,
    setMatch3DProfile,
    setMatch3DRun,
    setMatch3DSession,
    setStreamingMatch3DReplyText,
  ]);

  const openPuzzleAgentWorkspace = useCallback(async () => {
    setPuzzleRun(null);
    setPuzzleOperation(null);
    setPuzzleGenerationState(null);
    setPuzzleFormDraftPayload(null);
    const nextSession = await puzzleFlow.openWorkspace({});
    if (nextSession) {
      void refreshPuzzleShelf();
    }
  }, [puzzleFlow, refreshPuzzleShelf]);

  const createPuzzleDraftFromForm = useCallback(
    async (payload: CreatePuzzleAgentSessionRequest) => {
      setPuzzleFormDraftPayload(payload);
      const nextSession =
        puzzleFlow.session && !isEmptyPuzzleFormOnlyDraft(puzzleFlow.session)
          ? puzzleFlow.session
          : await puzzleFlow.openWorkspace(payload);
      if (!nextSession) {
        return;
      }

      await puzzleFlow.executeAction(
        buildPuzzleCompileActionFromFormPayload(payload),
        nextSession,
      );
    },
    [puzzleFlow],
  );

  const savePuzzleFormDraft = useCallback(
    async (payload: CreatePuzzleAgentSessionRequest) => {
      const session = puzzleFlow.session;
      if (!session || session.stage !== 'collecting_anchors') {
        return;
      }

      setPuzzleFormDraftPayload(payload);

      try {
        const response = await executePuzzleAgentAction(session.sessionId, {
          action: 'save_puzzle_form_draft',
          promptText: payload.pictureDescription ?? null,
          workTitle: payload.workTitle ?? payload.seedText ?? '',
          workDescription: payload.workDescription ?? '',
          pictureDescription: payload.pictureDescription ?? '',
        });
        setPuzzleOperation(response.operation);
        puzzleFlow.setSession(response.session);
        setPuzzleError(null);
        void refreshPuzzleShelf();
      } catch (error) {
        setPuzzleError(
          resolvePuzzleErrorMessage(error, '保存拼图表单草稿失败。'),
        );
      }
    },
    [puzzleFlow, refreshPuzzleShelf, resolvePuzzleErrorMessage, setPuzzleError],
  );

  useEffect(() => {
    if (platformBootstrap.canReadProtectedData) {
      hadReadableProtectedDataRef.current = true;
      return;
    }

    if (authUi?.user || !hadReadableProtectedDataRef.current) {
      return;
    }

    hadReadableProtectedDataRef.current = false;

    // 创作中心只展示当前登录用户的私有作品。
    // 一旦退出登录或鉴权上下文被收回，三类作品缓存必须同步清空，不能等刷新页面。
    setShowCreationTypeModal(false);
    setSelectedDetailEntry(null);
    setSelectedPublicWorkDetail(null);
    setPublicWorkDetailError(null);
    setIsPublicWorkDetailBusy(false);
    setBigFishWorks([]);
    setBigFishRun(null);
    setBigFishRuntimeShare(null);
    setBigFishRuntimeWork(null);
    setBigFishRuntimeStartedAt(null);
    setBigFishRuntimeReturnStage('platform');
    setBigFishGenerationState(null);
    setBigFishError(null);
    setMatch3DSession(null);
    setMatch3DProfile(null);
    setMatch3DWorks([]);
    setMatch3DGalleryEntries([]);
    setMatch3DRun(null);
    setMatch3DRuntimeReturnStage('match3d-result');
    setMatch3DError(null);
    setStreamingMatch3DReplyText('');
    setIsStreamingMatch3DReply(false);
    setPuzzleOperation(null);
    setPuzzleWorks([]);
    setSelectedPuzzleDetail(null);
    setPuzzleRuntimeReturnStage('puzzle-gallery-detail');
    setPuzzleRun(null);
    setPuzzleGenerationState(null);
    setIsPuzzleNextLevelGenerating(false);
    setPuzzleError(null);
    setDeletingCreationWorkId(null);
    setClaimingPuzzlePointIncentiveProfileId(null);
    setProfilePlayStats(null);
    setProfilePlayStatsError(null);
    setIsProfilePlayStatsOpen(false);
    resetRpgSessionViewState();
    setRpgGeneratedCustomWorldProfile(null);
    setRpgCustomWorldError(null);
    persistRpgAgentUiState(null, null);
    resetAutoSaveTrackingToIdle();

    if (
      selectionStage !== 'platform' &&
      selectionStage !== 'work-detail' &&
      selectionStage !== 'detail' &&
      selectionStage !== 'puzzle-gallery-detail'
    ) {
      setSelectionStage('platform');
    }
  }, [
    authUi?.user,
    platformBootstrap.canReadProtectedData,
    persistRpgAgentUiState,
    resetAutoSaveTrackingToIdle,
    resetRpgSessionViewState,
    selectionStage,
    setBigFishError,
    setIsStreamingMatch3DReply,
    setMatch3DError,
    setMatch3DSession,
    setPuzzleError,
    setRpgCustomWorldError,
    setRpgGeneratedCustomWorldProfile,
    setSelectionStage,
    setStreamingMatch3DReplyText,
  ]);

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

      if (!prepareCreationLaunch()) {
        return;
      }

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

      if (type === 'match3d') {
        runProtectedAction(() => {
          void openMatch3DAgentWorkspace();
        });
        return;
      }

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

  const leaveBigFishFlow = useCallback(() => {
    setBigFishRun(null);
    setBigFishRuntimeWork(null);
    setBigFishRuntimeStartedAt(null);
    setBigFishRuntimeReturnStage('platform');
    setBigFishGenerationState(null);
    bigFishFlow.leaveFlow();
  }, [bigFishFlow]);

  const leaveMatch3DFlow = useCallback(() => {
    setMatch3DRun(null);
    setMatch3DRuntimeReturnStage('match3d-result');
    match3dFlow.leaveFlow();
  }, [match3dFlow]);

  const leavePuzzleFlow = useCallback(() => {
    setPuzzleOperation(null);
    setPuzzleRun(null);
    setPuzzleGenerationState(null);
    setIsPuzzleNextLevelGenerating(false);
    puzzleFlow.leaveFlow();
  }, [puzzleFlow]);

  const submitBigFishMessage = bigFishFlow.submitMessage;

  const submitMatch3DMessage = match3dFlow.submitMessage;

  const submitPuzzleMessage = puzzleFlow.submitMessage;

  const executeBigFishAction = bigFishFlow.executeAction;

  const executeMatch3DAction = match3dFlow.executeAction;

  const executePuzzleAction = puzzleFlow.executeAction;

  const retryPuzzleDraftGeneration = useCallback(() => {
    if (puzzleFormDraftPayload) {
      void createPuzzleDraftFromForm(puzzleFormDraftPayload);
      return;
    }

    void executePuzzleAction(
      buildPuzzleCompileActionFromFormPayload(puzzleFormDraftPayload),
    );
  }, [createPuzzleDraftFromForm, executePuzzleAction, puzzleFormDraftPayload]);

  const executePuzzleWorkspaceAction = useCallback(
    (payload: PuzzleAgentActionRequest) => {
      if (
        payload.action === 'compile_puzzle_draft' &&
        isEmptyPuzzleFormOnlyDraft(puzzleFlow.session)
      ) {
        const formPayload = buildPuzzleFormPayloadFromAction(payload);
        if (formPayload) {
          void createPuzzleDraftFromForm(formPayload);
          return;
        }
      }

      void executePuzzleAction(payload);
    },
    [createPuzzleDraftFromForm, executePuzzleAction, puzzleFlow.session],
  );

  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]);

  useEffect(() => {
    if (selectionStage === 'match3d-result' && !match3dSession?.draft) {
      setSelectionStage(
        match3dSession ? 'match3d-agent-workspace' : 'platform',
      );
    }
    if (selectionStage === 'match3d-runtime' && !match3dRun) {
      setSelectionStage(match3dSession?.draft ? 'match3d-result' : 'platform');
    }
  }, [match3dRun, match3dSession, selectionStage, setSelectionStage]);

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

    const sessionId = bigFishSession.sessionId;
    setBigFishError(null);
    setBigFishRuntimeShare(null);
    setBigFishRuntimeWork(null);
    setBigFishRuntimeStartedAt(Date.now());
    setBigFishRuntimeReturnStage('big-fish-result');
    setBigFishRun(startLocalBigFishRuntimeRun({ session: bigFishSession }));
    setSelectionStage('big-fish-runtime');
    void recordBigFishPlay(sessionId, { elapsedMs: 0 }).catch((error) => {
      setBigFishError(
        resolveBigFishErrorMessage(error, '记录大鱼吃小鱼游玩失败。'),
      );
    });
    void refreshBigFishShelf();
  }, [
    bigFishSession,
    refreshBigFishShelf,
    resolveBigFishErrorMessage,
    setSelectionStage,
  ]);

  const restartBigFishRun = useCallback(() => {
    if (!bigFishSession && !bigFishRun) {
      return;
    }

    const sessionId = bigFishSession?.sessionId ?? bigFishRun?.sessionId;
    if (!sessionId) {
      return;
    }

    setBigFishError(null);
    if (bigFishSession) {
      setBigFishRuntimeShare(null);
      setBigFishRuntimeReturnStage('big-fish-result');
    }
    setBigFishRuntimeStartedAt(Date.now());
    setBigFishRun(
      startLocalBigFishRuntimeRun({
        session: bigFishSession,
        work: bigFishRuntimeWork,
      }),
    );
    setSelectionStage('big-fish-runtime');
    void recordBigFishPlay(sessionId, { elapsedMs: 0 }).catch((error) => {
      setBigFishError(
        resolveBigFishErrorMessage(error, '记录大鱼吃小鱼游玩失败。'),
      );
    });
  }, [
    bigFishRun,
    bigFishRuntimeWork,
    bigFishSession,
    resolveBigFishErrorMessage,
    setSelectionStage,
  ]);

  const startPuzzleRunFromProfile = useCallback(
    async (
      profileId: string,
      returnStage: PuzzleRuntimeReturnStage = 'work-detail',
      detailItem?: PuzzleWorkSummary,
      mirrorErrorToPublicDetail = false,
      levelId?: string | null,
    ) => {
      if (isPuzzleBusy) {
        return;
      }

      setIsPuzzleBusy(true);
      setPuzzleError(null);

      try {
        const item =
          detailItem ?? (await getPuzzleGalleryDetail(profileId)).item;
        const { run } = await startPuzzleRun({
          profileId: item.profileId,
          levelId: levelId ?? null,
        });
        setSelectedPuzzleDetail(item);
        setPuzzleRun(run);
        setPuzzleRuntimeReturnStage(returnStage);
        setSelectionStage('puzzle-runtime');
        void platformBootstrap.refreshSaveArchives();
        pushAppHistoryPath(
          buildPublicWorkStagePath(
            'puzzle-runtime',
            buildPuzzlePublicWorkCode(item.profileId),
          ),
        );
      } catch (error) {
        const message = resolvePuzzleErrorMessage(error, '启动拼图玩法失败。');
        setPuzzleError(message);
        if (mirrorErrorToPublicDetail) {
          setPublicWorkDetailError(message);
        }
      } finally {
        setIsPuzzleBusy(false);
      }
    },
    [
      isPuzzleBusy,
      platformBootstrap,
      resolvePuzzleErrorMessage,
      setIsPuzzleBusy,
      setPuzzleError,
      setSelectionStage,
    ],
  );

  const startMatch3DRunFromProfile = useCallback(
    async (
      profile: Match3DWorkProfile | Match3DWorkSummary,
      returnStage: 'match3d-result' | 'work-detail' = 'match3d-result',
      mirrorErrorToPublicDetail = false,
    ) => {
      if (isMatch3DBusy) {
        return;
      }

      match3dFlow.setIsBusy(true);
      setMatch3DError(null);

      try {
        const { run } = await startMatch3DRun(profile.profileId);
        setMatch3DRun(run);
        setMatch3DRuntimeReturnStage(returnStage);
        setSelectionStage('match3d-runtime');
        if (profile.publicationStatus === 'published') {
          pushAppHistoryPath(
            buildPublicWorkStagePath(
              'work-detail',
              buildMatch3DPublicWorkCode(profile.profileId),
            ),
          );
        }
      } catch (error) {
        const message = resolveMatch3DErrorMessage(
          error,
          '启动抓大鹅玩法失败。',
        );
        setMatch3DError(message);
        if (mirrorErrorToPublicDetail) {
          setPublicWorkDetailError(message);
        }
      } finally {
        match3dFlow.setIsBusy(false);
      }
    },
    [
      isMatch3DBusy,
      match3dFlow,
      resolveMatch3DErrorMessage,
      setMatch3DError,
      setSelectionStage,
    ],
  );

  const buildPuzzleTestWork = useCallback(
    (draft: PuzzleResultDraft) => {
      const profileId =
        puzzleSession?.publishedProfileId ??
        `draft-${puzzleSession?.sessionId ?? 'puzzle'}-test`;
      const now = new Date().toISOString();

      return {
        workId: `test-${profileId}`,
        profileId,
        ownerUserId: authUi?.user?.id ?? 'current-user',
        sourceSessionId: puzzleSession?.sessionId ?? null,
        authorDisplayName: authUi?.user?.displayName ?? '玩家',
        workTitle: draft.workTitle || draft.levelName,
        workDescription: draft.workDescription || draft.summary,
        levelName: draft.levelName,
        summary: draft.summary,
        themeTags: draft.themeTags,
        coverImageSrc: draft.coverImageSrc,
        coverAssetId: draft.coverAssetId,
        publicationStatus: 'draft',
        updatedAt: now,
        publishedAt: null,
        playCount: 0,
        remixCount: 0,
        likeCount: 0,
        pointIncentiveTotalHalfPoints: 0,
        pointIncentiveClaimedPoints: 0,
        pointIncentiveTotalPoints: 0,
        pointIncentiveClaimablePoints: 0,
        publishReady: Boolean(puzzleSession?.resultPreview?.publishReady),
        levels: draft.levels,
      } satisfies PuzzleWorkSummary;
    },
    [
      authUi?.user?.displayName,
      authUi?.user?.id,
      puzzleSession?.publishedProfileId,
      puzzleSession?.resultPreview?.publishReady,
      puzzleSession?.sessionId,
    ],
  );

  const startPuzzleTestRunFromDraft = useCallback(
    (draft: PuzzleResultDraft) => {
      if (!draft.coverImageSrc) {
        setPuzzleError('请先选择一张正式拼图图片。');
        return;
      }

      const testWork = buildPuzzleTestWork(draft);
      setSelectedPuzzleDetail(testWork);
      setPuzzleRun(startLocalPuzzleRun(testWork));
      setPuzzleRuntimeReturnStage('puzzle-result');
      setPuzzleError(null);
      setSelectionStage('puzzle-runtime');
    },
    [buildPuzzleTestWork, setSelectionStage],
  );

  const submitBigFishInput = useCallback(
    (payload: SubmitBigFishInputRequest) => {
      if (!bigFishRun || bigFishRun.status !== 'running') {
        return;
      }

      setBigFishRun((currentRun) =>
        currentRun
          ? advanceLocalBigFishRuntimeRun(currentRun, payload)
          : currentRun,
      );
    },
    [bigFishRun],
  );

  const reportBigFishObservedPlayTime = useCallback(() => {
    const sessionId = bigFishRun?.sessionId?.trim();
    if (!sessionId || !bigFishRuntimeStartedAt) {
      return;
    }

    const elapsedMs = Math.max(1_000, Date.now() - bigFishRuntimeStartedAt);
    setBigFishRuntimeStartedAt(null);
    void recordBigFishPlay(sessionId, { elapsedMs }).catch((error) => {
      setBigFishError(
        resolveBigFishErrorMessage(error, '记录大鱼吃小鱼游玩时长失败。'),
      );
    });
  }, [
    bigFishRun?.sessionId,
    bigFishRuntimeStartedAt,
    resolveBigFishErrorMessage,
  ]);

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

      setPuzzleError(null);
      // 交换、合并与通关判定都由前端即时裁决，正式 run 不再等待后端 /swap。
      setPuzzleRun(swapLocalPuzzlePieces(puzzleRun, payload));
    },
    [isPuzzleBusy, puzzleRun, setPuzzleError],
  );

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

      setPuzzleError(null);
      // 拖动落点、合并、拆分与通关判定都属于前端即时交互裁决。
      // 后端只保留开局、道具、下一关与真实排行榜等服务侧能力。
      setPuzzleRun(dragLocalPuzzlePiece(puzzleRun, payload));
    },
    [isPuzzleBusy, puzzleRun, setPuzzleError],
  );

  useEffect(() => {
    if (selectionStage !== 'puzzle-runtime' || !puzzleRun?.currentLevel) {
      return;
    }
    if (puzzleRun.currentLevel.status !== 'playing') {
      return;
    }

    const timerId = window.setInterval(() => {
      // 中文注释：正式 run 的棋盘交互也在前端即时裁决，倒计时展示同样走本地时钟；超时落库仍由 onTimeExpired 拉取后端快照完成。
      setPuzzleRun((currentRun) =>
        currentRun ? refreshLocalPuzzleTimer(currentRun) : currentRun,
      );
    }, 250);

    return () => window.clearInterval(timerId);
  }, [puzzleRun, selectionStage]);

  const setPuzzleRuntimePaused = useCallback(
    async (paused: boolean) => {
      if (!puzzleRun?.currentLevel) {
        return;
      }

      if (isLocalPuzzleRun(puzzleRun)) {
        setPuzzleRun((currentRun) =>
          currentRun ? setLocalPuzzlePaused(currentRun, paused) : currentRun,
        );
        return;
      }

      try {
        const { run } = await updatePuzzleRunPause(puzzleRun.runId, {
          paused,
        });
        setPuzzleRun((currentRun) =>
          currentRun
            ? mergePuzzleServiceRuntimeState(currentRun, run)
            : currentRun,
        );
        void platformBootstrap.refreshProfileDashboard();
      } catch (error) {
        setPuzzleError(
          resolvePuzzleErrorMessage(error, '更新拼图计时状态失败。'),
        );
      }
    },
    [platformBootstrap, puzzleRun, resolvePuzzleErrorMessage, setPuzzleError],
  );

  const syncPuzzleRuntimeTimeout = useCallback(async () => {
    if (
      !puzzleRun?.currentLevel ||
      puzzleRun.currentLevel.status === 'cleared'
    ) {
      return;
    }

    if (isLocalPuzzleRun(puzzleRun)) {
      setPuzzleRun((currentRun) =>
        currentRun ? refreshLocalPuzzleTimer(currentRun) : currentRun,
      );
      return;
    }

    try {
      const { run } = await getPuzzleRun(puzzleRun.runId);
      setPuzzleRun((currentRun) =>
        currentRun
          ? mergePuzzleServiceRuntimeState(currentRun, run)
          : currentRun,
      );
      void platformBootstrap.refreshSaveArchives();
    } catch (error) {
      setPuzzleError(
        resolvePuzzleErrorMessage(error, '同步拼图失败状态失败。'),
      );
    }
  }, [platformBootstrap, puzzleRun, resolvePuzzleErrorMessage, setPuzzleError]);

  const usePuzzleProp = useCallback(
    async (propKind: PuzzleRuntimePropKind) => {
      if (!puzzleRun?.currentLevel) {
        return null;
      }
      const canUseProp =
        propKind === 'extendTime'
          ? puzzleRun.currentLevel.status !== 'cleared'
          : puzzleRun.currentLevel.status === 'playing';
      if (!canUseProp) {
        return null;
      }

      if (isLocalPuzzleRun(puzzleRun)) {
        const currentRun = puzzleRunRef.current ?? puzzleRun;
        if (!currentRun.currentLevel) {
          return null;
        }
        const nextRun =
          propKind === 'extendTime'
            ? extendLocalPuzzleTime(currentRun)
            : propKind === 'freezeTime'
            ? applyLocalPuzzleFreezeTime(currentRun)
            : setLocalPuzzlePaused(currentRun, propKind === 'reference');
        puzzleRunRef.current = nextRun;
        setPuzzleRun(nextRun);
        return nextRun;
      }

      const { run } = await consumePuzzleRuntimeProp(puzzleRun.runId, {
        propKind,
      });
      const nextRun = mergePuzzleServiceRuntimeState(
        puzzleRunRef.current ?? puzzleRun,
        run,
      );
      puzzleRunRef.current = nextRun;
      setPuzzleRun(nextRun);
      void platformBootstrap.refreshProfileDashboard();
      void platformBootstrap.refreshSaveArchives();
      return nextRun;
    },
    [platformBootstrap, puzzleRun],
  );

  const restartPuzzleCurrentLevel = useCallback(async () => {
    const currentLevel = puzzleRun?.currentLevel ?? null;
    if (!puzzleRun || !currentLevel || isPuzzleBusy) {
      return;
    }

    setPuzzleError(null);
    const restartLevelId = resolvePuzzleRestartLevelId(
      puzzleRun,
      selectedPuzzleDetail,
    );
    if (isLocalPuzzleRun(puzzleRun)) {
      const nextRun = restartLocalPuzzleLevel(puzzleRunRef.current ?? puzzleRun);
      puzzleRunRef.current = nextRun;
      setPuzzleRun(nextRun);
      return;
    }

    await startPuzzleRunFromProfile(
      currentLevel.profileId,
      puzzleRuntimeReturnStage,
      selectedPuzzleDetail?.profileId === currentLevel.profileId
        ? selectedPuzzleDetail
        : undefined,
      false,
      restartLevelId,
    );
  }, [
    isPuzzleBusy,
    puzzleRun,
    puzzleRuntimeReturnStage,
    selectedPuzzleDetail,
    setPuzzleError,
    startPuzzleRunFromProfile,
  ]);

  const resumePuzzleSaveArchive = useCallback(
    async (entry: ProfileSaveArchiveSummary) => {
      if (isPuzzleBusy) {
        return;
      }

      setIsPuzzleBusy(true);
      setPuzzleError(null);
      platformBootstrap.setSaveError(null);

      try {
        const resumedArchive = await resumePuzzleProfileSaveArchiveRaw(
          entry.worldKey,
        );
        platformBootstrap.setSaveEntries((currentEntries) =>
          currentEntries.map((currentEntry) =>
            currentEntry.worldKey === resumedArchive.entry.worldKey
              ? resumedArchive.entry
              : currentEntry,
          ),
        );
        const gameState = resumedArchive.snapshot.gameState;
        const profileId =
          typeof gameState.currentProfileId === 'string' &&
          gameState.currentProfileId.trim()
            ? gameState.currentProfileId
            : typeof gameState.entryProfileId === 'string' &&
                gameState.entryProfileId.trim()
              ? gameState.entryProfileId
              : (entry.profileId ?? entry.worldKey.replace(/^puzzle:/u, ''));
        const levelId =
          typeof gameState.currentLevelId === 'string' &&
          gameState.currentLevelId.trim()
            ? gameState.currentLevelId
            : null;
        await startPuzzleRunFromProfile(
          profileId,
          'platform',
          undefined,
          false,
          levelId,
        );
      } catch (error) {
        platformBootstrap.setSaveError(
          resolvePuzzleErrorMessage(error, '恢复拼图存档失败。'),
        );
      } finally {
        setIsPuzzleBusy(false);
      }
    },
    [
      isPuzzleBusy,
      platformBootstrap,
      resolvePuzzleErrorMessage,
      setPuzzleError,
      startPuzzleRunFromProfile,
    ],
  );

  useEffect(() => {
    const currentLevel = puzzleRun?.currentLevel ?? null;
    if (!puzzleRun || !currentLevel || currentLevel.status !== 'cleared') {
      return;
    }
    if (currentLevel.elapsedMs === null) {
      return;
    }
    if ((currentLevel.leaderboardEntries ?? []).length > 0) {
      return;
    }

    const submitKey = `${puzzleRun.runId}:${currentLevel.profileId}:${currentLevel.gridSize}:${currentLevel.elapsedMs}`;
    if (submittedPuzzleLeaderboardKeysRef.current.has(submitKey)) {
      return;
    }
    submittedPuzzleLeaderboardKeysRef.current.add(submitKey);
    setIsPuzzleLeaderboardBusy(true);

    const payload: SubmitPuzzleLeaderboardRequest = {
      profileId: currentLevel.profileId,
      gridSize: currentLevel.gridSize,
      elapsedMs: currentLevel.elapsedMs,
      nickname: authUi?.user?.displayName?.trim() || '玩家',
    };

    if (isLocalPuzzleRun(puzzleRun)) {
      setPuzzleRun(submitLocalPuzzleLeaderboard(puzzleRun, payload.nickname));
      void advanceLocalPuzzleNextLevel({
        run: puzzleRun,
        sourceSessionId:
          selectedPuzzleDetail?.sourceSessionId ??
          puzzleSession?.sessionId ??
          null,
      })
        .then(({ run }) => {
          setPuzzleRun((currentRun) => {
            if (!currentRun) {
              return currentRun;
            }
            return mergePuzzleServiceRuntimeState(currentRun, run);
          });
        })
        .catch(() => {
          // 中文注释：本地试玩缺少后端候选时保留本地排行榜和既有下一关入口，避免结算被探测请求打断。
        })
        .finally(() => {
          setIsPuzzleLeaderboardBusy(false);
        });
      return;
    }

    void submitPuzzleLeaderboard(puzzleRun.runId, payload)
      .then(({ run }) => {
        setPuzzleRun((currentRun) => {
          if (!currentRun) {
            return currentRun;
          }
          return mergePuzzleServiceRuntimeState(currentRun, run);
        });
        void platformBootstrap.refreshSaveArchives();
      })
      .catch((error) => {
        submittedPuzzleLeaderboardKeysRef.current.delete(submitKey);
        setPuzzleError(
          resolvePuzzleErrorMessage(error, '提交拼图排行榜失败。'),
        );
      })
      .finally(() => {
        setIsPuzzleLeaderboardBusy(false);
      });
  }, [
    authUi?.user?.displayName,
    platformBootstrap,
    puzzleRun,
    puzzleSession,
    resolvePuzzleErrorMessage,
    selectedPuzzleDetail,
    setPuzzleError,
  ]);

  const advancePuzzleLevel = useCallback(async (target?: {
    profileId?: string;
    levelId?: string | null;
  }) => {
    if (!puzzleRun || isPuzzleBusy || isPuzzleLeaderboardBusy) {
      return;
    }

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

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

    try {
      const targetProfileId = target?.profileId?.trim();
      if (
        targetProfileId &&
        targetProfileId !== currentLevel.profileId &&
        puzzleRun.nextLevelMode === 'similarWorks'
      ) {
        await startPuzzleRunFromProfile(
          targetProfileId,
          'puzzle-gallery-detail',
          undefined,
          false,
          null,
        );
        return;
      }
      const { run } = isLocalPuzzleRun(puzzleRun)
        ? await advanceLocalPuzzleNextLevel({
            run: puzzleRun,
            sourceSessionId:
              selectedPuzzleDetail?.sourceSessionId ??
              puzzleSession?.sessionId ??
              null,
          })
        : await advancePuzzleNextLevel(puzzleRun.runId);
      setPuzzleRun(run);
      if (!isLocalPuzzleRun(puzzleRun)) {
        void platformBootstrap.refreshSaveArchives();
      }
    } catch (error) {
      setPuzzleError(resolvePuzzleErrorMessage(error, '准备下一关失败。'));
    } finally {
      setIsPuzzleNextLevelGenerating(false);
      setIsPuzzleBusy(false);
    }
  }, [
    isPuzzleBusy,
    isPuzzleLeaderboardBusy,
    platformBootstrap,
    puzzleRun,
    puzzleSession,
    resolvePuzzleErrorMessage,
    selectedPuzzleDetail,
    startPuzzleRunFromProfile,
  ]);

  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 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(async (response) => {
            setBigFishWorks(response.items);
            await refreshBigFishGallery().catch(() => []);
          })
          .catch((error) => {
            setBigFishError(
              resolveBigFishErrorMessage(error, '删除大鱼吃小鱼作品失败。'),
            );
          })
          .finally(() => {
            setDeletingCreationWorkId(null);
          });
      });
    },
    [
      deletingCreationWorkId,
      refreshBigFishGallery,
      resolveBigFishErrorMessage,
      runProtectedAction,
    ],
  );

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

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

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

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

  const handleDeleteMatch3DWork = useCallback(
    (work: Match3DWorkSummary) => {
      if (deletingCreationWorkId) {
        return;
      }

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

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

        void deleteMatch3DWork(work.profileId)
          .then((response) => {
            setMatch3DWorks(response.items);
            void refreshMatch3DGallery();
          })
          .catch((error) => {
            setMatch3DError(
              resolveMatch3DErrorMessage(error, '删除抓大鹅作品失败。'),
            );
          })
          .finally(() => {
            setDeletingCreationWorkId(null);
          });
      });
    },
    [
      deletingCreationWorkId,
      refreshMatch3DGallery,
      resolveMatch3DErrorMessage,
      runProtectedAction,
      setMatch3DError,
    ],
  );

  const clearSelectedPublicWorkAuthor = useCallback(() => {
    publicWorkAuthorRequestKeyRef.current += 1;
    setSelectedPublicWorkAuthor(null);
  }, []);

  const loadSelectedPublicWorkAuthor = useCallback(
    (entry: PlatformPublicGalleryCard) => {
      const requestKey = publicWorkAuthorRequestKeyRef.current + 1;
      publicWorkAuthorRequestKeyRef.current = requestKey;
      setSelectedPublicWorkAuthor(null);

      void resolvePublicWorkAuthorSummary(entry)
        .then((author) => {
          if (publicWorkAuthorRequestKeyRef.current === requestKey) {
            setSelectedPublicWorkAuthor(author);
          }
        })
        .catch(() => {
          if (publicWorkAuthorRequestKeyRef.current === requestKey) {
            setSelectedPublicWorkAuthor(null);
          }
        });
    },
    [],
  );

  const openPublicWorkDetail = useCallback(
    (entry: PlatformPublicGalleryCard) => {
      setSelectedPublicWorkDetail(entry);
      setPublicWorkDetailError(null);
      setSelectionStage('work-detail');
      if (entry.publicWorkCode?.trim()) {
        pushAppHistoryPath(
          buildPublicWorkStagePath('work-detail', entry.publicWorkCode),
        );
      }
    },
    [setSelectionStage],
  );

  const syncUpdatedPublicWorkDetail = useCallback(
    (updatedEntry: PlatformPublicGalleryCard) => {
      setSelectedPublicWorkDetail((current) =>
        current && isSamePlatformPublicGalleryEntry(current, updatedEntry)
          ? updatedEntry
          : current,
      );
    },
    [],
  );

  const handleClaimPuzzlePointIncentive = useCallback(
    (work: PuzzleWorkSummary) => {
      if (claimingPuzzlePointIncentiveProfileId) {
        return;
      }

      runProtectedAction(() => {
        setClaimingPuzzlePointIncentiveProfileId(work.profileId);
        setPuzzleError(null);

        void claimPuzzleWorkPointIncentive(work.profileId)
          .then((response) => {
            const updatedWork = response.item;
            setPuzzleWorks((current) =>
              current.map((item) =>
                mergePuzzleWorkSummary(item, updatedWork),
              ),
            );
            setPuzzleGalleryEntries((current) =>
              current.map((item) =>
                mergePuzzleWorkSummary(item, updatedWork),
              ),
            );
            setSelectedPuzzleDetail((current) =>
              current ? mergePuzzleWorkSummary(current, updatedWork) : current,
            );
            syncUpdatedPublicWorkDetail(
              mapPuzzleWorkToPublicWorkDetail(updatedWork),
            );
            void platformBootstrap.refreshProfileDashboard();
          })
          .catch((error) => {
            setPuzzleError(
              resolvePuzzleErrorMessage(error, '领取拼图积分激励失败。'),
            );
          })
          .finally(() => {
            setClaimingPuzzlePointIncentiveProfileId(null);
          });
      });
    },
    [
      claimingPuzzlePointIncentiveProfileId,
      platformBootstrap,
      resolvePuzzleErrorMessage,
      runProtectedAction,
      setPuzzleError,
      syncUpdatedPublicWorkDetail,
    ],
  );

  const likePublicWork = useCallback(
    (entry: PlatformPublicGalleryCard) => {
      if (isPublicWorkDetailBusy) {
        return;
      }

      runProtectedAction(() => {
        setIsPublicWorkDetailBusy(true);
        setPublicWorkDetailError(null);

        if (isBigFishGalleryEntry(entry)) {
          void likeBigFishGalleryWork(entry.profileId)
            .then((response) => {
              const updatedWork = response.items.find(
                (item) => item.sourceSessionId === entry.profileId,
              );
              if (!updatedWork) {
                return;
              }
              setBigFishGalleryEntries((current) =>
                current.map((item) =>
                  mergeBigFishWorkSummary(item, updatedWork),
                ),
              );
              setBigFishWorks((current) =>
                current.map((item) =>
                  mergeBigFishWorkSummary(item, updatedWork),
                ),
              );
              syncUpdatedPublicWorkDetail(
                mapBigFishWorkToPublicWorkDetail(updatedWork),
              );
              setBigFishRuntimeWork((current) =>
                current
                  ? mergeBigFishWorkSummary(current, updatedWork)
                  : current,
              );
            })
            .catch((error) => {
              setPublicWorkDetailError(
                resolveBigFishErrorMessage(error, '点赞大鱼吃小鱼作品失败。'),
              );
            })
            .finally(() => {
              setIsPublicWorkDetailBusy(false);
            });
          return;
        }

        if (isPuzzleGalleryEntry(entry)) {
          void likePuzzleGalleryWork(entry.profileId)
            .then((response) => {
              const updatedWork = response.item;
              setPuzzleGalleryEntries((current) =>
                current.map((item) =>
                  mergePuzzleWorkSummary(item, updatedWork),
                ),
              );
              setPuzzleWorks((current) =>
                current.map((item) =>
                  mergePuzzleWorkSummary(item, updatedWork),
                ),
              );
              setSelectedPuzzleDetail((current) =>
                current
                  ? mergePuzzleWorkSummary(current, updatedWork)
                  : current,
              );
              syncUpdatedPublicWorkDetail(
                mapPuzzleWorkToPublicWorkDetail(updatedWork),
              );
            })
            .catch((error) => {
              setPublicWorkDetailError(
                resolvePuzzleErrorMessage(error, '点赞拼图作品失败。'),
              );
            })
            .finally(() => {
              setIsPublicWorkDetailBusy(false);
            });
          return;
        }

        void likeRpgEntryWorldGallery(entry.ownerUserId, entry.profileId)
          .then((updatedEntry) => {
            setSelectedDetailEntry((current) =>
              current?.profileId === updatedEntry.profileId
                ? updatedEntry
                : current,
            );
            platformBootstrap.setPublishedGalleryEntries((current) =>
              current.map((item) =>
                item.profileId === updatedEntry.profileId ? updatedEntry : item,
              ),
            );
            syncUpdatedPublicWorkDetail(
              mapRpgGalleryCardToPublicWorkDetail(updatedEntry),
            );
          })
          .catch((error) => {
            setPublicWorkDetailError(
              resolveRpgCreationErrorMessage(error, '点赞 RPG 作品失败。'),
            );
          })
          .finally(() => {
            setIsPublicWorkDetailBusy(false);
          });
      });
    },
    [
      isPublicWorkDetailBusy,
      platformBootstrap,
      resolveBigFishErrorMessage,
      resolvePuzzleErrorMessage,
      runProtectedAction,
      syncUpdatedPublicWorkDetail,
    ],
  );

  useEffect(() => {
    const detailEntry =
      selectionStage === 'work-detail'
        ? selectedPublicWorkDetail
        : selectionStage === 'detail' &&
            selectedDetailEntry &&
            selectedDetailEntry.visibility !== 'draft'
          ? mapRpgGalleryCardToPublicWorkDetail(selectedDetailEntry)
          : null;

    if (!detailEntry) {
      clearSelectedPublicWorkAuthor();
      return;
    }

    loadSelectedPublicWorkAuthor(detailEntry);
  }, [
    clearSelectedPublicWorkAuthor,
    loadSelectedPublicWorkAuthor,
    selectedDetailEntry,
    selectedPublicWorkDetail,
    selectionStage,
  ]);

  const openRpgPublicWorkDetail = useCallback(
    async (entry: CustomWorldGalleryCard) => {
      setIsPublicWorkDetailBusy(true);
      setPublicWorkDetailError(null);
      clearSelectedPublicWorkAuthor();
      setSelectedPublicWorkDetail(entry);
      setSelectionStage('work-detail');

      try {
        const detailEntry =
          await detailNavigation.loadGalleryDetailEntry(entry);
        setSelectedDetailEntry(detailEntry);
        const detailCard = mapRpgGalleryCardToPublicWorkDetail(detailEntry);
        setSelectedPublicWorkDetail(detailCard);
        if (detailEntry.publicWorkCode?.trim()) {
          pushAppHistoryPath(
            buildPublicWorkStagePath('work-detail', detailEntry.publicWorkCode),
          );
        }
      } catch (error) {
        setSelectedPublicWorkDetail(entry);
        setPublicWorkDetailError(
          resolveRpgCreationErrorMessage(error, '读取作品详情失败。'),
        );
      } finally {
        setIsPublicWorkDetailBusy(false);
      }
    },
    [
      clearSelectedPublicWorkAuthor,
      detailNavigation,
      setSelectedDetailEntry,
      setSelectionStage,
    ],
  );

  const openPuzzlePublicWorkDetail = useCallback(
    async (
      profileId: string,
      returnTarget: PuzzleDetailReturnTarget = {
        tab: platformBootstrap.platformTab,
      },
    ) => {
      setIsPuzzleBusy(true);
      setIsPublicWorkDetailBusy(true);
      setPuzzleError(null);
      setPublicWorkDetailError(null);
      setSelectionStage('work-detail');

      try {
        const { item } = await getPuzzleGalleryDetail(profileId);
        setSelectedPuzzleDetail(item);
        setPuzzleDetailReturnTarget(returnTarget);
        openPublicWorkDetail(mapPuzzleWorkToPublicWorkDetail(item));
      } catch (error) {
        setPublicWorkDetailError(
          resolvePuzzleErrorMessage(error, '读取拼图详情失败。'),
        );
      } finally {
        setIsPuzzleBusy(false);
        setIsPublicWorkDetailBusy(false);
      }
    },
    [
      openPublicWorkDetail,
      platformBootstrap.platformTab,
      resolvePuzzleErrorMessage,
      setPuzzleError,
    ],
  );

  const openMatch3DPublicWorkDetail = useCallback(
    async (profileId: string) => {
      setIsPublicWorkDetailBusy(true);
      setMatch3DError(null);
      setPublicWorkDetailError(null);
      setSelectionStage('work-detail');

      try {
        const entries =
          match3dGalleryEntries.length > 0
            ? match3dGalleryEntries
            : await refreshMatch3DGallery();
        const matchedEntry = entries.find(
          (entry) => entry.profileId === profileId,
        );

        if (!matchedEntry) {
          throw new Error('未找到抓大鹅作品。');
        }

        openPublicWorkDetail(mapMatch3DWorkToPublicWorkDetail(matchedEntry));
      } catch (error) {
        setPublicWorkDetailError(
          resolveMatch3DErrorMessage(error, '读取抓大鹅详情失败。'),
        );
      } finally {
        setIsPublicWorkDetailBusy(false);
      }
    },
    [
      match3dGalleryEntries,
      openPublicWorkDetail,
      refreshMatch3DGallery,
      resolveMatch3DErrorMessage,
      setMatch3DError,
      setSelectionStage,
    ],
  );

  const openPuzzleDetail = useCallback(
    async (
      profileId: string,
      returnTarget: PuzzleDetailReturnTarget = {
        tab: platformBootstrap.platformTab,
      },
    ) => {
      setIsPuzzleBusy(true);
      setPuzzleError(null);

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

  const openPuzzleDraft = useCallback(
    async (item: PuzzleWorkSummary) => {
      setPuzzleOperation(null);
      setPuzzleRun(null);
      setSelectedPuzzleDetail(null);
      if (!item.sourceSessionId?.trim()) {
        if (item.publicationStatus === 'published') {
          await openPuzzleDetail(item.profileId, { tab: 'create' });
          return;
        }

        setPuzzleError('这份拼图草稿缺少会话信息，请重新开始创作。');
        return;
      }

      const restoredSession = await puzzleFlow.restoreDraft(
        item.sourceSessionId,
      );
      if (!restoredSession) {
        await refreshPuzzleShelf().catch(() => undefined);
        return;
      }

      if (isPuzzleFormOnlyDraft(restoredSession)) {
        setPuzzleFormDraftPayload(
          buildPuzzleFormPayloadFromSession(restoredSession),
        );
        setSelectionStage('puzzle-agent-workspace');
      } else {
        setPuzzleFormDraftPayload(null);
      }
    },
    [
      openPuzzleDetail,
      puzzleFlow,
      refreshPuzzleShelf,
      setPuzzleError,
      setSelectionStage,
    ],
  );

  const openMatch3DDraft = useCallback(
    async (item: Match3DWorkSummary) => {
      setMatch3DRun(null);
      setMatch3DError(null);
      setMatch3DProfile(null);

      if (item.publicationStatus === 'published') {
        openPublicWorkDetail(mapMatch3DWorkToPublicWorkDetail(item));
        return;
      }

      if (!item.sourceSessionId?.trim()) {
        setMatch3DError('这份抓大鹅草稿缺少会话信息，请重新开始创作。');
        return;
      }

      const restoredSession = await match3dFlow.restoreDraft(item.sourceSessionId);
      if (!restoredSession) {
        await refreshMatch3DShelf().catch(() => undefined);
        return;
      }

      try {
        const { item: profile } = await getMatch3DWorkDetail(item.profileId);
        setMatch3DProfile(profile);
      } catch (error) {
        setMatch3DProfile(buildMatch3DProfileFromSession(restoredSession));
        setMatch3DError(
          resolveMatch3DErrorMessage(error, '读取抓大鹅作品详情失败。'),
        );
      }
    },
    [
      match3dFlow,
      openPublicWorkDetail,
      refreshMatch3DShelf,
      resolveMatch3DErrorMessage,
      setMatch3DError,
    ],
  );

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

      const publicWorkCode = buildBigFishPublicWorkCode(item.sourceSessionId);
      setBigFishError(null);
      bigFishFlow.setSession(null);
      setBigFishRuntimeWork(item);
      setBigFishRuntimeShare({
        title: item.title,
        publicWorkCode,
      });
      setBigFishRuntimeStartedAt(Date.now());
      setBigFishRuntimeReturnStage(returnStage);
      setBigFishRun(startLocalBigFishRuntimeRun({ work: item }));
      setSelectionStage('big-fish-runtime');
      pushAppHistoryPath(
        buildPublicWorkStagePath('big-fish-runtime', publicWorkCode),
      );
      void recordBigFishPlay(sessionId, { elapsedMs: 0 }).catch((error) => {
        setBigFishError(
          resolveBigFishErrorMessage(error, '记录大鱼吃小鱼游玩失败。'),
        );
      });
    },
    [bigFishFlow, resolveBigFishErrorMessage, setSelectionStage],
  );

  const startSelectedPublicWork = useCallback(() => {
    if (!selectedPublicWorkDetail || isPublicWorkDetailBusy) {
      return;
    }

    if (isBigFishGalleryEntry(selectedPublicWorkDetail)) {
      const work = mapPublicWorkDetailToBigFishWork(selectedPublicWorkDetail);
      if (!work) {
        setPublicWorkDetailError('当前作品缺少会话信息，暂时无法进入玩法。');
        return;
      }
      startBigFishRunFromWork(work);
      return;
    }

    if (isPuzzleGalleryEntry(selectedPublicWorkDetail)) {
      const work = mapPublicWorkDetailToPuzzleWork(selectedPublicWorkDetail);
      if (!work) {
        setPublicWorkDetailError('当前拼图作品信息不完整，暂时无法进入玩法。');
        return;
      }
      setPublicWorkDetailError(null);
      void startPuzzleRunFromProfile(work.profileId, 'work-detail', work, true);
      return;
    }

    if (isMatch3DGalleryEntry(selectedPublicWorkDetail)) {
      const work = mapPublicWorkDetailToMatch3DWork(selectedPublicWorkDetail);
      if (!work) {
        setPublicWorkDetailError('当前抓大鹅作品信息不完整，暂时无法进入玩法。');
        return;
      }
      setPublicWorkDetailError(null);
      void startMatch3DRunFromProfile(work, 'work-detail', true);
      return;
    }

    const launchEntry =
      selectedDetailEntry?.profileId === selectedPublicWorkDetail.profileId
        ? selectedDetailEntry
        : null;
    if (!launchEntry) {
      setPublicWorkDetailError('作品详情尚未读取完成。');
      return;
    }

    runProtectedAction(() => {
      setIsPublicWorkDetailBusy(true);
      void recordRpgEntryWorldGalleryPlay(
        launchEntry.ownerUserId,
        launchEntry.profileId,
      )
        .then((updatedEntry) => {
          setSelectedDetailEntry(updatedEntry);
          setSelectedPublicWorkDetail(
            mapRpgGalleryCardToPublicWorkDetail(updatedEntry),
          );
          handleCustomWorldSelect(updatedEntry.profile);
        })
        .catch((error) => {
          setPublicWorkDetailError(
            resolveRpgCreationErrorMessage(error, '记录作品游玩失败。'),
          );
        })
        .finally(() => {
          setIsPublicWorkDetailBusy(false);
        });
    });
  }, [
    handleCustomWorldSelect,
    isPublicWorkDetailBusy,
    runProtectedAction,
    selectedDetailEntry,
    selectedPublicWorkDetail,
    startBigFishRunFromWork,
    startMatch3DRunFromProfile,
    startPuzzleRunFromProfile,
  ]);

  const remixPublicWork = useCallback(
    (entry: PlatformPublicGalleryCard) => {
      if (isPublicWorkDetailBusy) {
        return;
      }

      runProtectedAction(() => {
        setIsPublicWorkDetailBusy(true);
        setPublicWorkDetailError(null);

        if (isBigFishGalleryEntry(entry)) {
          void remixBigFishGalleryWork(entry.profileId)
            .then((response) => {
              bigFishFlow.setSession(response.session);
              enterCreateTab();
              setSelectionStage('big-fish-result');
            })
            .catch((error) => {
              setPublicWorkDetailError(
                resolveBigFishErrorMessage(error, 'Remix 大鱼吃小鱼作品失败。'),
              );
            })
            .finally(() => {
              setIsPublicWorkDetailBusy(false);
            });
          return;
        }

        if (isPuzzleGalleryEntry(entry)) {
          void remixPuzzleGalleryWork(entry.profileId)
            .then((response) => {
              puzzleFlow.setSession(response.session);
              setPuzzleOperation(null);
              enterCreateTab();
              setSelectionStage('puzzle-result');
            })
            .catch((error) => {
              setPublicWorkDetailError(
                resolvePuzzleErrorMessage(error, 'Remix 拼图作品失败。'),
              );
            })
            .finally(() => {
              setIsPublicWorkDetailBusy(false);
            });
          return;
        }

        if (isMatch3DGalleryEntry(entry)) {
          setPublicWorkDetailError('抓大鹅作品改造将在后续版本开放。');
          setIsPublicWorkDetailBusy(false);
          return;
        }

        void remixRpgEntryWorldGallery(entry.ownerUserId, entry.profileId)
          .then((response) => {
            const nextEntry = response.entry;
            setSelectedDetailEntry(nextEntry);
            platformBootstrap.setSavedCustomWorldEntries([
              nextEntry,
              ...platformBootstrap.savedCustomWorldEntries.filter(
                (entry) => entry.profileId !== nextEntry.profileId,
              ),
            ]);
            void detailNavigation.openSavedCustomWorldEditor(nextEntry);
          })
          .catch((error) => {
            setPublicWorkDetailError(
              resolveRpgCreationErrorMessage(error, 'Remix RPG 作品失败。'),
            );
          })
          .finally(() => {
            setIsPublicWorkDetailBusy(false);
          });
      });
    },
    [
      bigFishFlow,
      detailNavigation,
      enterCreateTab,
      isPublicWorkDetailBusy,
      platformBootstrap,
      puzzleFlow,
      resolveBigFishErrorMessage,
      resolvePuzzleErrorMessage,
      runProtectedAction,
      setSelectionStage,
    ],
  );

  const remixSelectedPublicWork = useCallback(() => {
    if (!selectedPublicWorkDetail) {
      return;
    }
    remixPublicWork(selectedPublicWorkDetail);
  }, [remixPublicWork, selectedPublicWorkDetail]);

  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 shouldSearchBigFishFirst = upperKeyword.startsWith('BF');
      const shouldSearchMatch3DFirst = upperKeyword.startsWith('M3');
      const shouldSearchPuzzleFirst = upperKeyword.startsWith('PZ');
      const shouldSearchWorkFirst =
        !shouldSearchUserIdFirst &&
        !shouldSearchBigFishFirst &&
        !shouldSearchMatch3DFirst &&
        !shouldSearchPuzzleFirst &&
        (upperKeyword.startsWith('CW') || /^\d{1,8}$/u.test(normalizedKeyword));
      const shouldSearchUserFirst =
        shouldSearchUserIdFirst ||
        upperKeyword.startsWith('SY') ||
        (!shouldSearchWorkFirst &&
          !shouldSearchBigFishFirst &&
          !shouldSearchMatch3DFirst &&
          !shouldSearchPuzzleFirst);

      const tryOpenGalleryEntry = async () => {
        const entry =
          await getRpgEntryWorldGalleryDetailByCode(normalizedKeyword);
        const card = {
          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,
          playCount: entry.playCount ?? 0,
          remixCount: entry.remixCount ?? 0,
          likeCount: entry.likeCount ?? 0,
        } satisfies CustomWorldGalleryCard;
        setSelectedDetailEntry(entry);
        openPublicWorkDetail(card);
      };
      const tryOpenPuzzleGalleryEntry = async () => {
        const entries =
          puzzleGalleryEntries.length > 0
            ? puzzleGalleryEntries
            : await refreshPuzzleGallery();
        const matchedEntry = entries.find((entry) =>
          isSamePuzzlePublicWorkCode(normalizedKeyword, entry.profileId),
        );

        if (!matchedEntry) {
          throw new Error('未找到拼图作品。');
        }

        await openPuzzlePublicWorkDetail(matchedEntry.profileId, {
          tab: platformBootstrap.platformTab,
        });
      };
      const tryOpenBigFishGalleryEntry = async () => {
        const entries =
          bigFishGalleryEntries.length > 0
            ? bigFishGalleryEntries
            : await refreshBigFishGallery();
        const matchedEntry = entries.find((entry) =>
          isSameBigFishPublicWorkCode(normalizedKeyword, entry.sourceSessionId),
        );

        if (!matchedEntry) {
          throw new Error('未找到大鱼吃小鱼作品。');
        }

        openPublicWorkDetail(mapBigFishWorkToPublicWorkDetail(matchedEntry));
      };
      const tryOpenMatch3DGalleryEntry = async () => {
        const entries =
          match3dGalleryEntries.length > 0
            ? match3dGalleryEntries
            : await refreshMatch3DGallery();
        const matchedEntry = entries.find((entry) =>
          isSameMatch3DPublicWorkCode(normalizedKeyword, entry.profileId),
        );

        if (!matchedEntry) {
          throw new Error('未找到抓大鹅作品。');
        }

        openPublicWorkDetail(mapMatch3DWorkToPublicWorkDetail(matchedEntry));
      };

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

        if (shouldSearchPuzzleFirst) {
          await tryOpenPuzzleGalleryEntry();
          return;
        }

        if (shouldSearchBigFishFirst) {
          await tryOpenBigFishGalleryEntry();
          return;
        }

        if (shouldSearchMatch3DFirst) {
          await tryOpenMatch3DGalleryEntry();
          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);
      }
    },
    [
      bigFishGalleryEntries,
      match3dGalleryEntries,
      refreshMatch3DGallery,
      openPuzzlePublicWorkDetail,
      openPublicWorkDetail,
      platformBootstrap.platformTab,
      puzzleGalleryEntries,
      refreshBigFishGallery,
      refreshPuzzleGallery,
    ],
  );

  const openProfilePlayedWorks = useCallback(() => {
    setIsProfilePlayStatsOpen(true);
    setIsProfilePlayStatsLoading(true);
    setProfilePlayStatsError(null);

    void getRpgProfilePlayStats()
      .then(setProfilePlayStats)
      .catch((error) => {
        setProfilePlayStats(null);
        setProfilePlayStatsError(
          resolveRpgCreationErrorMessage(error, '读取玩过作品失败。'),
        );
      })
      .finally(() => {
        setIsProfilePlayStatsLoading(false);
      });
  }, []);

  const openPlayedWork = useCallback(
    (work: ProfilePlayedWorkSummary) => {
      const worldType = (work.worldType ?? '').toLowerCase();
      setIsProfilePlayStatsOpen(false);

      if (worldType === 'puzzle' || work.worldKey.startsWith('puzzle:')) {
        const profileId =
          work.profileId ?? work.worldKey.replace(/^puzzle:/u, '');
        if (profileId) {
          void openPuzzlePublicWorkDetail(profileId, { tab: 'profile' });
        }
        return;
      }

      if (
        worldType === 'match3d' ||
        worldType === 'match_3d' ||
        work.worldKey.startsWith('match3d:')
      ) {
        const profileId =
          work.profileId ?? work.worldKey.replace(/^match3d:/u, '');
        if (profileId) {
          void openMatch3DPublicWorkDetail(profileId);
        }
        return;
      }

      if (
        worldType === 'big_fish' ||
        worldType === 'big-fish' ||
        work.worldKey.startsWith('big-fish:')
      ) {
        const sessionId =
          work.profileId ?? work.worldKey.replace(/^big-fish:/u, '');
        if (!sessionId) {
          return;
        }
        void refreshBigFishGallery()
          .then((entries) => {
            const matchedEntry = entries.find(
              (entry) => entry.sourceSessionId === sessionId,
            );
            if (matchedEntry) {
              openPublicWorkDetail(
                mapBigFishWorkToPublicWorkDetail(matchedEntry),
              );
              return;
            }
            openPublicWorkDetail(
              mapBigFishWorkToPublicWorkDetail({
                workId: `big-fish:${sessionId}`,
                sourceSessionId: sessionId,
                ownerUserId: work.ownerUserId ?? '',
                authorDisplayName: work.worldSubtitle || '玩家',
                title: work.worldTitle,
                subtitle: work.worldSubtitle,
                summary: work.worldSubtitle,
                coverImageSrc: null,
                status: 'published',
                updatedAt: work.lastPlayedAt,
                publishReady: true,
                levelCount: 0,
                levelMainImageReadyCount: 0,
                levelMotionReadyCount: 0,
                backgroundReady: false,
              }),
            );
          })
          .catch((error) => {
            setBigFishError(
              resolveBigFishErrorMessage(error, '进入大鱼吃小鱼作品失败。'),
            );
          });
        return;
      }

      const profileId = work.profileId ?? work.worldKey;
      const ownerUserId = work.ownerUserId;
      if (!ownerUserId || !profileId) {
        return;
      }

      void openRpgPublicWorkDetail({
        ownerUserId,
        profileId,
        publicWorkCode: null,
        authorPublicUserCode: null,
        visibility: 'published',
        publishedAt: work.firstPlayedAt,
        updatedAt: work.lastPlayedAt,
        authorDisplayName: work.worldSubtitle,
        worldName: work.worldTitle,
        subtitle: work.worldSubtitle,
        summaryText: '',
        coverImageSrc: null,
        themeMode: 'martial',
        playableNpcCount: 0,
        landmarkCount: 0,
        playCount: 0,
        remixCount: 0,
        likeCount: 0,
      });
    },
    [
      openMatch3DPublicWorkDetail,
      openPuzzlePublicWorkDetail,
      openPublicWorkDetail,
      openRpgPublicWorkDetail,
      refreshBigFishGallery,
      resolveBigFishErrorMessage,
    ],
  );

  useEffect(() => {
    const publicWorkCode = initialPublicWorkCode?.trim();
    if (
      !publicWorkCode ||
      handledInitialPublicWorkCodeRef.current === publicWorkCode
    ) {
      return;
    }

    handledInitialPublicWorkCodeRef.current = publicWorkCode;
    void handlePublicCodeSearch(publicWorkCode);
  }, [handlePublicCodeSearch, initialPublicWorkCode]);

  const openBigFishDraft = useCallback(
    async (item: BigFishWorkSummary) => {
      setBigFishRun(null);
      const restoredSession = await bigFishFlow.restoreDraft(
        item.sourceSessionId,
      );
      if (!restoredSession) {
        await refreshBigFishShelf().catch(() => undefined);
      }
    },
    [bigFishFlow, refreshBigFishShelf],
  );

  useEffect(() => {
    if (selectionStage === 'platform') {
      if (isBigFishCreationVisible) {
        void refreshBigFishGallery();
      }
      void refreshMatch3DGallery();
      void refreshPuzzleGallery();
    }
  }, [
    isBigFishCreationVisible,
    refreshBigFishGallery,
    refreshMatch3DGallery,
    refreshPuzzleGallery,
    selectionStage,
  ]);

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

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

  const creationHubContent = (
    <Suspense fallback={<LazyPanelFallback label="正在加载创作中心..." />}>
      <CustomWorldCreationHub
        items={creationHubItems}
        loading={
          platformBootstrap.isLoadingPlatform ||
          isBigFishLoadingLibrary ||
          isMatch3DLoadingLibrary ||
          isPuzzleLoadingLibrary
        }
        error={
          platformBootstrap.isLoadingPlatform ||
          isBigFishLoadingLibrary ||
          isMatch3DLoadingLibrary ||
          isPuzzleLoadingLibrary
            ? null
            : (platformBootstrap.platformError ??
              sessionController.agentWorkspaceRestoreError ??
              bigFishError ??
              match3dError ??
              puzzleError)
        }
        onRetry={() => {
          platformBootstrap.setPlatformError(null);
          setBigFishError(null);
          setMatch3DError(null);
          setPuzzleError(null);
          void platformBootstrap.refreshCustomWorldWorks().catch((error) => {
            platformBootstrap.setPlatformError(
              resolveRpgCreationErrorMessage(error, '读取创作作品列表失败。'),
            );
          });
          if (isBigFishCreationVisible) {
            void refreshBigFishShelf();
          }
          void refreshMatch3DShelf();
          void refreshPuzzleShelf();
        }}
        createError={
          sessionController.creationTypeError ??
          bigFishError ??
          match3dError ??
          puzzleError
        }
        createBusy={
          sessionController.isCreatingAgentSession ||
          isBigFishBusy ||
          isMatch3DBusy ||
          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}
        rpgLibraryEntries={platformBootstrap.savedCustomWorldEntries}
        bigFishItems={isBigFishCreationVisible ? bigFishWorks : []}
        onOpenBigFishDetail={
          isBigFishCreationVisible
            ? (item) => {
                runProtectedAction(() => {
                  void openBigFishDraft(item);
                });
              }
            : undefined
        }
        onDeleteBigFish={
          isBigFishCreationVisible
            ? (item) => {
                handleDeleteBigFishWork(item);
              }
            : null
        }
        match3dItems={match3dWorks}
        onOpenMatch3DDetail={(item) => {
          runProtectedAction(() => {
            void openMatch3DDraft(item);
          });
        }}
        onDeleteMatch3D={(item) => {
          handleDeleteMatch3DWork(item);
        }}
        puzzleItems={puzzleWorks}
        onOpenPuzzleDetail={(item) => {
          runProtectedAction(() => {
            void openPuzzleDraft(item);
          });
        }}
        onDeletePuzzle={(item) => {
          handleDeletePuzzleWork(item);
        }}
        onClaimPuzzlePointIncentive={(item) => {
          handleClaimPuzzlePointIncentive(item);
        }}
        claimingPuzzleProfileId={claimingPuzzlePointIncentiveProfileId}
      />
    </Suspense>
  );

  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={latestGalleryEntries}
              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) => {
                if (
                  (entry.worldType ?? '').toLowerCase() === 'puzzle' ||
                  entry.worldKey.startsWith('puzzle:')
                ) {
                  void resumePuzzleSaveArchive(entry);
                  return;
                }
                void platformBootstrap.handleResumeSaveEntry(entry);
              }}
              onOpenCreateWorld={openCreationTypePicker}
              onOpenCreateTypePicker={openCreationTypePicker}
              onOpenGalleryDetail={(entry) => {
                if (isBigFishGalleryEntry(entry)) {
                  openPublicWorkDetail(entry);
                  return;
                }

                if (isPuzzleGalleryEntry(entry)) {
                  void openPuzzlePublicWorkDetail(entry.profileId, {
                    tab: platformBootstrap.platformTab,
                  });
                  return;
                }

                if (isMatch3DGalleryEntry(entry)) {
                  openPublicWorkDetail(entry);
                  return;
                }

                void openRpgPublicWorkDetail(entry);
              }}
              onOpenLibraryDetail={(entry) => {
                runProtectedAction(() => {
                  void detailNavigation.openLibraryDetail(entry);
                });
              }}
              onDeleteLibraryEntry={(entry) => {
                handleDeleteLibraryEntry(entry);
              }}
              deletingLibraryEntryId={deletingCreationWorkId}
              onSearchPublicCode={(keyword) => {
                void handlePublicCodeSearch(keyword);
              }}
              isSearchingPublicCode={isSearchingPublicCode}
              profilePlayStats={profilePlayStats}
              isProfilePlayStatsOpen={isProfilePlayStatsOpen}
              isProfilePlayStatsLoading={isProfilePlayStatsLoading}
              profilePlayStatsError={profilePlayStatsError}
              onCloseProfilePlayStats={() => {
                setIsProfilePlayStatsOpen(false);
              }}
              onOpenPlayedWork={openPlayedWork}
              onOpenProfileDashboardCard={(cardKey) => {
                if (cardKey === 'playedWorks') {
                  openProfilePlayedWorks();
                  return;
                }
                if (platformBootstrap.dashboardError) {
                  void platformBootstrap.refreshProfileDashboard();
                }
              }}
              onRechargeSuccess={platformBootstrap.refreshProfileDashboard}
            />
          </motion.div>
        )}

        {selectionStage === 'work-detail' && selectedPublicWorkDetail && (
          <motion.div
            key="platform-work-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"
          >
            <PlatformWorkDetailView
              entry={selectedPublicWorkDetail}
              authorAvatarUrl={selectedPublicWorkAuthor?.avatarUrl ?? null}
              authorDisplayName={selectedPublicWorkAuthor?.displayName ?? null}
              isBusy={
                isPublicWorkDetailBusy ||
                isPuzzleBusy ||
                isBigFishBusy ||
                isMatch3DBusy
              }
              error={publicWorkDetailError}
              onBack={() => {
                setPublicWorkDetailError(null);
                clearSelectedPublicWorkAuthor();
                setSelectionStage('platform');
              }}
              onLike={() => {
                likePublicWork(selectedPublicWorkDetail);
              }}
              onStart={startSelectedPublicWork}
              onRemix={remixSelectedPublicWork}
            />
          </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>
            ) : selectedDetailEntry.visibility !== 'draft' ? (
              <PlatformWorkDetailView
                entry={mapRpgGalleryCardToPublicWorkDetail(selectedDetailEntry)}
                authorAvatarUrl={selectedPublicWorkAuthor?.avatarUrl ?? null}
                authorDisplayName={
                  selectedPublicWorkAuthor?.displayName ?? null
                }
                isBusy={detailNavigation.isMutatingDetail}
                error={detailNavigation.detailError}
                onBack={() => {
                  detailNavigation.setDetailError(null);
                  clearSelectedPublicWorkAuthor();
                  entryNavigation.backToPlatformHome();
                }}
                onLike={() => {
                  likePublicWork(
                    mapRpgGalleryCardToPublicWorkDetail(selectedDetailEntry),
                  );
                }}
                onStart={handleStartSelectedWorld}
                onRemix={() => {
                  remixPublicWork(
                    mapRpgGalleryCardToPublicWorkDetail(selectedDetailEntry),
                  );
                }}
              />
            ) : (
              <PlatformEntryWorldDetailView
                entry={selectedDetailEntry}
                isMutating={detailNavigation.isMutatingDetail}
                error={detailNavigation.detailError}
                onBack={() => {
                  detailNavigation.setDetailError(null);
                  entryNavigation.backToPlatformHome();
                }}
                onStartGame={handleStartSelectedWorld}
                onContinueEdit={
                  detailNavigation.isSelectedWorldOwned
                    ? () => {
                        runProtectedAction(() => {
                          void detailNavigation.openSavedCustomWorldEditor(
                            selectedDetailEntry,
                          );
                        });
                      }
                    : null
                }
                onPublish={
                  selectedDetailEntry.visibility === 'draft' &&
                  detailNavigation.isSelectedWorldOwned
                    ? () => {
                        runProtectedAction(() => {
                          void detailNavigation.handlePublishSelectedWorld();
                        });
                      }
                    : null
                }
                onUnpublish={
                  selectedDetailEntry.visibility !== 'draft' &&
                  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}
                isStreamingReply={isStreamingBigFishReply}
                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 ?? []}
                shareTitle={bigFishRuntimeShare?.title ?? null}
                sharePublicWorkCode={
                  bigFishRuntimeShare?.publicWorkCode ?? null
                }
                isBusy={isBigFishBusy}
                error={bigFishError}
                onBack={() => {
                  reportBigFishObservedPlayTime();
                  setSelectionStage(bigFishRuntimeReturnStage);
                }}
                onRestart={() => {
                  reportBigFishObservedPlayTime();
                  void restartBigFishRun();
                }}
                onSubmitInput={submitBigFishInput}
              />
            </Suspense>
          </motion.div>
        )}

        {selectionStage === 'match3d-agent-workspace' && (
          <motion.div
            key="match3d-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="正在加载抓大鹅共创工作区..." />}
            >
              <Match3DAgentWorkspace
                session={match3dSession}
                streamingReplyText={streamingMatch3DReplyText}
                isStreamingReply={isStreamingMatch3DReply}
                isBusy={isMatch3DBusy || isStreamingMatch3DReply}
                error={match3dError}
                onBack={leaveMatch3DFlow}
                onSubmitMessage={(payload) => {
                  void submitMatch3DMessage(payload);
                }}
                onExecuteAction={(payload) => {
                  void executeMatch3DAction(payload);
                }}
              />
            </Suspense>
          </motion.div>
        )}

        {selectionStage === 'match3d-result' && match3dSession?.draft && (
          <motion.div
            key="match3d-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="正在加载抓大鹅结果..." />}
            >
              <Match3DResultView
                profile={
                  match3dProfile ?? buildMatch3DProfileFromSession(match3dSession)!
                }
                draft={match3dSession.draft}
                isBusy={isMatch3DBusy}
                error={match3dError}
                onBack={() => {
                  setSelectionStage('match3d-agent-workspace');
                }}
                onSaved={(profile) => {
                  setMatch3DProfile(profile);
                }}
                onPublished={(profile) => {
                  setMatch3DProfile(profile);
                  void Promise.allSettled([
                    refreshMatch3DShelf(),
                    refreshMatch3DGallery(),
                  ]);
                  openPublicWorkDetail(mapMatch3DWorkToPublicWorkDetail(profile));
                }}
                onStartTestRun={(profile) => {
                  setMatch3DProfile(profile);
                  void startMatch3DRunFromProfile(profile, 'match3d-result');
                }}
              />
            </Suspense>
          </motion.div>
        )}

        {selectionStage === 'match3d-runtime' && (
          <motion.div
            key="match3d-runtime"
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 }}
            exit={{ opacity: 0 }}
            className="fixed inset-0 z-[100]"
          >
            <Suspense
              fallback={<LazyPanelFallback label="正在加载抓大鹅玩法..." />}
            >
              <Match3DRuntimeShell
                run={match3dRun}
                isBusy={isMatch3DBusy}
                error={match3dError}
                onBack={() => {
                  if (match3dRun?.runId && match3dRun.status === 'running') {
                    void stopMatch3DRun(match3dRun.runId).catch(() => undefined);
                  }
                  setSelectionStage(match3dRuntimeReturnStage);
                }}
                onRestart={() => {
                  if (!match3dRun?.runId || isMatch3DBusy) {
                    return;
                  }

                  match3dFlow.setIsBusy(true);
                  setMatch3DError(null);
                  void restartMatch3DRun(match3dRun.runId)
                    .then(({ run }) => {
                      setMatch3DRun(run);
                    })
                    .catch((error) => {
                      setMatch3DError(
                        resolveMatch3DErrorMessage(
                          error,
                          '重新开始抓大鹅玩法失败。',
                        ),
                      );
                    })
                    .finally(() => {
                      match3dFlow.setIsBusy(false);
                    });
                }}
                onOptimisticRunChange={setMatch3DRun}
                onClickItem={(payload) => {
                  const runId = payload.runId ?? match3dRun?.runId;
                  if (!runId) {
                    return Promise.reject(new Error('抓大鹅运行态缺少 runId。'));
                  }
                  return clickMatch3DItem(runId, payload);
                }}
                onTimeExpired={() => {
                  if (!match3dRun?.runId) {
                    return;
                  }

                  void finishMatch3DTimeUp(match3dRun.runId)
                    .then(({ run }) => {
                      setMatch3DRun(run);
                    })
                    .catch((error) => {
                      setMatch3DError(
                        resolveMatch3DErrorMessage(
                          error,
                          '同步抓大鹅倒计时失败。',
                        ),
                      );
                    });
                }}
              />
            </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"
          >
            <Suspense
              fallback={<LazyPanelFallback label="正在加载拼图创作..." />}
            >
              <PuzzleAgentWorkspace
                session={puzzleSession}
                isBusy={isPuzzleBusy || isStreamingPuzzleReply}
                error={puzzleError}
                onBack={leavePuzzleFlow}
                onSubmitMessage={(payload) => {
                  void submitPuzzleMessage(payload);
                }}
                onExecuteAction={(payload) => {
                  executePuzzleWorkspaceAction(payload);
                }}
                initialFormPayload={puzzleFormDraftPayload}
                onCreateFromForm={(payload) => {
                  void createPuzzleDraftFromForm(payload);
                }}
                onAutoSaveForm={(payload) => {
                  void savePuzzleFormDraft(payload);
                }}
              />
            </Suspense>
          </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,
                  puzzleFormDraftPayload,
                )}
                progress={buildMiniGameDraftGenerationProgress(
                  puzzleGenerationState,
                )}
                isGenerating={isPuzzleBusy}
                error={puzzleError}
                onBack={leavePuzzleFlow}
                onEditSetting={() => {
                  setSelectionStage('puzzle-agent-workspace');
                }}
                onRetry={retryPuzzleDraftGeneration}
                onInterrupt={undefined}
                backLabel="返回创作中心"
                settingActionLabel={null}
                retryLabel="重新生成草稿"
                settingTitle="当前拼图信息"
                settingDescription={null}
                progressTitle="拼图草稿生成进度"
                activeBadgeLabel="草稿生成中"
                pausedBadgeLabel="草稿生成已暂停"
                idleBadgeLabel="等待返回工作区"
              />
            </Suspense>
          </motion.div>
        )}

        {selectionStage === 'puzzle-result' &&
          puzzleSession?.draft &&
          !isPuzzleFormOnlyDraft(puzzleSession) && (
            <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"
            >
              <Suspense
                fallback={<LazyPanelFallback label="正在加载拼图结果..." />}
              >
                <PuzzleResultView
                  session={puzzleSession}
                  profileId={
                    puzzleSession.publishedProfileId ??
                    buildPuzzleResultProfileId(puzzleSession.sessionId)
                  }
                  isBusy={isPuzzleBusy}
                  error={puzzleError}
                  onBack={() => {
                    setSelectionStage('puzzle-agent-workspace');
                  }}
                  onExecuteAction={(payload) => {
                    void executePuzzleAction(payload);
                  }}
                  onStartTestRun={startPuzzleTestRunFromDraft}
                />
              </Suspense>
            </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"
          >
            <Suspense
              fallback={<LazyPanelFallback label="正在加载拼图详情..." />}
            >
              <PuzzleGalleryDetailView
                item={selectedPuzzleDetail}
                isBusy={isPuzzleBusy}
                error={puzzleError}
                onBack={() => {
                  platformBootstrap.setPlatformTab(
                    puzzleDetailReturnTarget?.tab ?? 'home',
                  );
                  setPuzzleDetailReturnTarget(null);
                  setSelectionStage('platform');
                }}
                onEdit={
                  selectedPuzzleDetail.ownerUserId === authUi?.user?.id &&
                  Boolean(selectedPuzzleDetail.sourceSessionId?.trim())
                    ? () => {
                        runProtectedAction(() => {
                          void openPuzzleDraft(selectedPuzzleDetail);
                        });
                      }
                    : null
                }
                onStartGame={() => {
                  void startPuzzleRunFromProfile(
                    selectedPuzzleDetail.profileId,
                    'puzzle-gallery-detail',
                    selectedPuzzleDetail,
                  );
                }}
              />
            </Suspense>
          </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]"
          >
            <Suspense
              fallback={<LazyPanelFallback label="正在加载拼图玩法..." />}
            >
              <PuzzleRuntimeShell
                run={puzzleRun}
                isBusy={
                  isPuzzleBusy ||
                  isPuzzleNextLevelGenerating ||
                  isPuzzleLeaderboardBusy
                }
                error={puzzleError}
                onBack={() => {
                  setSelectionStage(puzzleRuntimeReturnStage);
                }}
                onSwapPieces={(payload) => {
                  void swapPuzzlePiecesInRun(payload);
                }}
                onDragPiece={(payload) => {
                  void dragPuzzlePiece(payload);
                }}
                onAdvanceNextLevel={(target) => {
                  void advancePuzzleLevel(target);
                }}
                onRestartLevel={() => {
                  void restartPuzzleCurrentLevel();
                }}
                onPauseChange={setPuzzleRuntimePaused}
                onUseProp={usePuzzleProp}
                onTimeExpired={syncPuzzleRuntimeTimeout}
              />
            </Suspense>
            {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(profile);
                  }}
                  onBack={
                    sessionController.isAgentDraftResultView
                      ? () => {
                          leaveAgentDraftResult();
                        }
                      : 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';
                          await autosaveCoordinator.executeAgentActionAndWait({
                            action,
                            count: 1,
                            ...(kind === 'playable'
                              ? { roleType: 'playable' as const }
                              : kind === 'story'
                                ? { roleType: 'story' as const }
                                : {}),
                          });
                          const latestView =
                            sessionController.activeAgentSessionId
                              ? await sessionController.syncAgentCreationResultView(
                                  sessionController.activeAgentSessionId,
                                )
                              : null;
                          const latestProfile =
                            rpgCreationPreviewAdapter.buildPreviewFromResultView(
                              latestView,
                            );
                          if (latestProfile) {
                            sessionController.setGeneratedCustomWorldProfile(
                              latestProfile,
                            );
                          }
                          return { profile: latestProfile };
                        }
                      : undefined
                  }
                  onDeleteEntities={
                    sessionController.isAgentDraftResultView
                      ? async (kind, ids) => {
                          if (ids.length === 0) return;
                          await autosaveCoordinator.executeAgentActionAndWait(
                            kind === 'story'
                              ? { action: 'delete_characters', roleIds: ids }
                              : { action: 'delete_landmarks', sceneIds: ids },
                          );
                          const latestView =
                            sessionController.activeAgentSessionId
                              ? await sessionController.syncAgentCreationResultView(
                                  sessionController.activeAgentSessionId,
                                )
                              : null;
                          const latestProfile =
                            rpgCreationPreviewAdapter.buildPreviewFromResultView(
                              latestView,
                            );
                          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 ||
          isMatch3DBusy ||
          isPuzzleBusy
        }
        error={
          bigFishError ??
          match3dError ??
          puzzleError ??
          sessionController.creationTypeError
        }
        onClose={() => {
          if (
            sessionController.isCreatingAgentSession ||
            isBigFishBusy ||
            isMatch3DBusy ||
            isPuzzleBusy
          ) {
            return;
          }
          setShowCreationTypeModal(false);
        }}
        onSelectRpg={() => {
          // RPG 创作入口当前为敬请期待；保留回调防御，避免旧入口绕过锁定态。
        }}
        onSelectBigFish={() => {
          runProtectedAction(() => {
            void openBigFishAgentWorkspace();
          });
        }}
        onSelectMatch3D={() => {
          runProtectedAction(() => {
            void openMatch3DAgentWorkspace();
          });
        }}
        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;
