import { AnimatePresence, motion } from 'motion/react';
import { useEffect, useMemo, useRef, useState } from 'react';

import {
  buildCustomWorldPlayableCharacters,
} from '../../data/characterPresets';
import {
  readSavedCustomWorldProfiles,
  upsertSavedCustomWorldProfile,
} from '../../data/customWorldLibrary';
import { getScenePreset } from '../../data/scenePresets';
import {
  type CustomWorldGenerationProgress,
  generateCustomWorldProfile,
} from '../../services/ai';
import {
  buildCustomWorldCreatorIntentDisplayText,
  buildCustomWorldCreatorIntentGenerationText,
  createEmptyCustomWorldCreatorIntent,
} from '../../services/customWorldCreatorIntent';
import {
  type CustomWorldCreatorIntent,
  type CustomWorldGenerationMode,
  type CustomWorldProfile,
  type GameState,
  WorldType,
} from '../../types';
import {
  CHROME_ICONS,
  getNineSliceStyle,
  UI_CHROME,
  WORLD_SELECT_ICONS,
} from '../../uiAssets';
import { CustomWorldGenerationView } from '../CustomWorldGenerationView';
import { CustomWorldResultView } from '../CustomWorldResultView';
import { DeveloperTeamModal } from '../DeveloperTeamModal';
import { PixelIcon } from '../PixelIcon';
import { CustomWorldCreatorModal } from '../SelectionCustomizationModals';

export type SelectionStage =
  | 'start'
  | 'world'
  | 'custom-world-generating'
  | 'custom-world-result';

type WorldOnlineCounts = Partial<Record<WorldType, number>>;

type PreGameSelectionFlowProps = {
  selectionStage: SelectionStage;
  setSelectionStage: (stage: SelectionStage) => void;
  gameState: GameState;
  hasSavedGame: boolean;
  handleContinueGame: () => void;
  handleStartNewGame: () => void;
  handleWorldSelect: (
    type: WorldType,
    customWorldProfile?: GameState['customWorldProfile'],
  ) => void;
};

const DEVELOPER_TEAM_MESSAGE =
  '\u7a0b\u7b56\u7f8e\uff1a\u53d9\u4e16AI \u5305\u4ef2\u822a\n\u5408\u4f5c\u8bf7\u8054\u7cfb\u5fae\u4fe1\uff1abzh253518756';

const START_SCREEN_CONTACTS = [
  { label: 'QQ群', value: '1094580241' },
  { label: '微信', value: 'bzh253518756' },
] as const;

const WORLD_OPTIONS = [
  {
    id: WorldType.WUXIA,
    name: '武侠',
    subtitle: '刀剑江湖',
    icon: WORLD_SELECT_ICONS.wuxia,
    texture: UI_CHROME.worldButtonWuxia,
  },
  {
    id: WorldType.XIANXIA,
    name: '仙侠',
    subtitle: '云灵仙境',
    icon: WORLD_SELECT_ICONS.xianxia,
    texture: UI_CHROME.worldButtonXianxia,
  },
] as const;

function generateWorldOnlineCounts(): WorldOnlineCounts {
  const roll = (base: number) =>
    Math.max(100, Math.min(200, base + Math.floor(Math.random() * 19) - 9));
  return {
    [WorldType.WUXIA]: roll(146),
    [WorldType.XIANXIA]: roll(173),
  };
}

function buildLockedSeedNameSets(profile: CustomWorldProfile) {
  const lockedCharacterNames = new Set(
    profile.creatorIntent?.keyCharacters
      .filter((entry) => entry.locked)
      .map((entry) => entry.name.trim())
      .filter(Boolean) ?? [],
  );
  const lockedLandmarkNames = new Set(
    profile.creatorIntent?.keyLandmarks
      .filter((entry) => entry.locked)
      .map((entry) => entry.name.trim())
      .filter(Boolean) ?? [],
  );

  return {
    lockedCharacterNames,
    lockedLandmarkNames,
  };
}

function mergeLockedProfileContent(
  currentProfile: CustomWorldProfile,
  nextProfile: CustomWorldProfile,
) {
  const { lockedCharacterNames, lockedLandmarkNames } =
    buildLockedSeedNameSets(currentProfile);

  const nextPlayableNpcs = nextProfile.playableNpcs.map((npc) => {
    if (!lockedCharacterNames.has(npc.name.trim())) {
      return npc;
    }
    return (
      currentProfile.playableNpcs.find(
        (currentNpc) => currentNpc.name.trim() === npc.name.trim(),
      ) ?? npc
    );
  });
  const nextStoryNpcs = nextProfile.storyNpcs.map((npc) => {
    if (!lockedCharacterNames.has(npc.name.trim())) {
      return npc;
    }
    return (
      currentProfile.storyNpcs.find(
        (currentNpc) => currentNpc.name.trim() === npc.name.trim(),
      ) ?? npc
    );
  });
  const nextLandmarks = nextProfile.landmarks.map((landmark) => {
    if (!lockedLandmarkNames.has(landmark.name.trim())) {
      return landmark;
    }
    return (
      currentProfile.landmarks.find(
        (currentLandmark) =>
          currentLandmark.name.trim() === landmark.name.trim(),
      ) ?? landmark
    );
  });

  return {
    ...nextProfile,
    playableNpcs: nextPlayableNpcs,
    storyNpcs: nextStoryNpcs,
    landmarks: nextLandmarks,
  } satisfies CustomWorldProfile;
}

export function PreGameSelectionFlow({
  selectionStage,
  setSelectionStage,
  gameState,
  hasSavedGame,
  handleContinueGame,
  handleStartNewGame,
  handleWorldSelect,
}: PreGameSelectionFlowProps) {
  const [generatedCustomWorldProfile, setGeneratedCustomWorldProfile] =
    useState<GameState['customWorldProfile']>(null);
  const [savedCustomWorldProfiles, setSavedCustomWorldProfiles] = useState<
    CustomWorldProfile[]
  >(() => readSavedCustomWorldProfiles());
  const [showDeveloperTeamModal, setShowDeveloperTeamModal] = useState(false);
  const [worldOnlineCounts, setWorldOnlineCounts] = useState<WorldOnlineCounts>(
    () => generateWorldOnlineCounts(),
  );
  const [showCustomWorldModal, setShowCustomWorldModal] = useState(false);
  const [customWorldCreatorIntent, setCustomWorldCreatorIntent] =
    useState<CustomWorldCreatorIntent>(() =>
      createEmptyCustomWorldCreatorIntent('freeform'),
    );
  const [customWorldGenerationMode, setCustomWorldGenerationMode] =
    useState<CustomWorldGenerationMode>('fast');
  const [customWorldError, setCustomWorldError] = useState<string | null>(null);
  const [isGeneratingCustomWorld, setIsGeneratingCustomWorld] = useState(false);
  const [customWorldProgress, setCustomWorldProgress] =
    useState<CustomWorldGenerationProgress | null>(null);
  const customWorldAbortControllerRef = useRef<AbortController | null>(null);

  const previewCustomWorldCharacters = useMemo(
    () =>
      generatedCustomWorldProfile
        ? buildCustomWorldPlayableCharacters(generatedCustomWorldProfile)
        : [],
    [generatedCustomWorldProfile],
  );

  const worldCards = useMemo(
    () =>
      WORLD_OPTIONS.map((world, index) => ({
        ...world,
        sceneImage:
          getScenePreset(world.id, index + 1)?.imageSrc ??
          getScenePreset(world.id, 0)?.imageSrc ??
          '',
        featureIcon:
          world.id === WorldType.WUXIA
            ? '/Icons/03_Torch.png'
            : '/Icons/19_Mana_potion.png',
        onlineCount: worldOnlineCounts[world.id] ?? 0,
      })),
    [worldOnlineCounts],
  );

  const savedCustomWorldCards = useMemo(
    () =>
      savedCustomWorldProfiles.map((profile, index) => {
        const anchorWorldType = profile.templateWorldType;
        const leadCharacter =
          buildCustomWorldPlayableCharacters(profile)[0] ?? null;

        return {
          id: profile.id,
          profile,
          texture:
            anchorWorldType === WorldType.WUXIA
              ? UI_CHROME.worldButtonWuxia
              : UI_CHROME.worldButtonXianxia,
          sceneImage:
            profile.landmarks[0]?.imageSrc ??
            getScenePreset(anchorWorldType, (index % 3) + 1)?.imageSrc ??
            getScenePreset(anchorWorldType, 0)?.imageSrc ??
            '',
          featurePortrait: leadCharacter?.portrait ?? '',
          featureIcon:
            anchorWorldType === WorldType.WUXIA
              ? WORLD_SELECT_ICONS.wuxia
              : WORLD_SELECT_ICONS.xianxia,
          accentLabel:
            anchorWorldType === WorldType.WUXIA ? '武侠基础' : '仙侠基础',
        };
      }),
    [savedCustomWorldProfiles],
  );

  const customWorldSettingPreview = useMemo(() => {
    if (customWorldCreatorIntent.sourceMode === 'freeform') {
      return customWorldCreatorIntent.rawSettingText.trim();
    }
    const intentSummary = buildCustomWorldCreatorIntentDisplayText(
      customWorldCreatorIntent,
    ).trim();
    if (intentSummary) {
      return intentSummary;
    }
    return customWorldCreatorIntent.rawSettingText.trim();
  }, [customWorldCreatorIntent]);

  useEffect(() => {
    if (!gameState.worldType && selectionStage === 'world') {
      setWorldOnlineCounts(generateWorldOnlineCounts());
    }
  }, [gameState.worldType, selectionStage]);

  useEffect(() => {
    if (
      selectionStage === 'custom-world-result' &&
      !generatedCustomWorldProfile
    ) {
      setSelectionStage('world');
    }
  }, [generatedCustomWorldProfile, selectionStage, setSelectionStage]);

  useEffect(
    () => () => {
      customWorldAbortControllerRef.current?.abort();
    },
    [],
  );

  const leaveCustomWorldResult = () => {
    setGeneratedCustomWorldProfile(null);
    setCustomWorldError(null);
    setCustomWorldProgress(null);
    setSelectionStage('world');
  };

  const leaveCustomWorldGeneration = () => {
    if (isGeneratingCustomWorld) {
      return;
    }

    setCustomWorldError(null);
    setCustomWorldProgress(null);
    setSelectionStage('world');
  };

  const openCustomWorldCreator = () => {
    if (isGeneratingCustomWorld) {
      return;
    }

    setCustomWorldError(null);
    setCustomWorldProgress(null);
    setShowCustomWorldModal(true);
  };

  const editCustomWorldSetting = () => {
    if (isGeneratingCustomWorld) {
      return;
    }

    if (generatedCustomWorldProfile) {
      setCustomWorldCreatorIntent(
        generatedCustomWorldProfile.creatorIntent ??
          ({
            ...createEmptyCustomWorldCreatorIntent('freeform'),
            rawSettingText: generatedCustomWorldProfile.settingText,
          } satisfies CustomWorldCreatorIntent),
      );
      setCustomWorldGenerationMode(
        generatedCustomWorldProfile.generationMode ?? 'full',
      );
    }
    setCustomWorldError(null);
    setCustomWorldProgress(null);
    setSelectionStage('world');
    setShowCustomWorldModal(true);
  };

  const saveGeneratedCustomWorld = () => {
    if (!generatedCustomWorldProfile) {
      return;
    }

    try {
      setSavedCustomWorldProfiles(
        upsertSavedCustomWorldProfile(generatedCustomWorldProfile),
      );
    } catch (error) {
      setCustomWorldError(
        error instanceof Error ? error.message : '本地保存自定义世界失败。',
      );
      return;
    }

    handleWorldSelect(WorldType.CUSTOM, generatedCustomWorldProfile);
    setGeneratedCustomWorldProfile(null);
    setCustomWorldError(null);
    setCustomWorldProgress(null);
    setSelectionStage('world');
  };

  const openSavedCustomWorldEditor = (profile: CustomWorldProfile) => {
    if (isGeneratingCustomWorld) {
      return;
    }

    setGeneratedCustomWorldProfile(profile);
    setCustomWorldCreatorIntent(
      profile.creatorIntent ??
        ({
          ...createEmptyCustomWorldCreatorIntent('freeform'),
          rawSettingText: profile.settingText,
        } satisfies CustomWorldCreatorIntent),
    );
    setCustomWorldGenerationMode(profile.generationMode ?? 'full');
    setCustomWorldError(null);
    setCustomWorldProgress(null);
    setSelectionStage('custom-world-result');
  };

  const regenerateFromCurrentProfile = async (
    applyProfile: (
      currentProfile: CustomWorldProfile,
      regeneratedProfile: CustomWorldProfile,
    ) => CustomWorldProfile,
    options: {
      confirmMessage: string;
      generationMode?: CustomWorldGenerationMode;
    },
  ) => {
    if (!generatedCustomWorldProfile || isGeneratingCustomWorld) {
      return;
    }

    const confirmed = window.confirm(options.confirmMessage);
    if (!confirmed) {
      return;
    }

    const abortController = new AbortController();
    customWorldAbortControllerRef.current?.abort();
    customWorldAbortControllerRef.current = abortController;
    setIsGeneratingCustomWorld(true);
    setCustomWorldError(null);

    try {
      const regeneratedProfile = await generateCustomWorldProfile(
        {
          settingText:
            generatedCustomWorldProfile.settingText.trim() ||
            customWorldSettingPreview,
          creatorIntent: generatedCustomWorldProfile.creatorIntent,
          generationMode:
            options.generationMode ??
            generatedCustomWorldProfile.generationMode ??
            'full',
        },
        {
          signal: abortController.signal,
          onProgress: setCustomWorldProgress,
        },
      );

      if (abortController.signal.aborted) {
        return;
      }

      const mergedProfile = applyProfile(
        generatedCustomWorldProfile,
        mergeLockedProfileContent(generatedCustomWorldProfile, regeneratedProfile),
      );
      setGeneratedCustomWorldProfile(mergedProfile);
      setCustomWorldProgress(null);
      setCustomWorldError(null);
    } catch (error) {
      if (abortController.signal.aborted) {
        setCustomWorldError('世界生成已中断。你可以重新尝试本次操作。');
        return;
      }
      setCustomWorldError(
        error instanceof Error ? error.message : '局部重生成失败。',
      );
    } finally {
      if (customWorldAbortControllerRef.current === abortController) {
        customWorldAbortControllerRef.current = null;
      }
      setIsGeneratingCustomWorld(false);
    }
  };

  const continueExpandCustomWorld = async () => {
    await regenerateFromCurrentProfile(
      (_currentProfile, regeneratedProfile) => ({
        ...regeneratedProfile,
        generationMode: 'full',
        generationStatus: 'complete',
      }),
      {
        confirmMessage:
          '确认继续补全当前世界吗？系统会在保留已锁定锚点的前提下，继续生成长尾角色和场景网络。',
        generationMode: 'full',
      },
    );
  };

  const regeneratePlayableNpc = async (id: string) => {
    await regenerateFromCurrentProfile(
      (currentProfile, regeneratedProfile) => {
        const targetIndex = currentProfile.playableNpcs.findIndex(
          (entry) => entry.id === id,
        );
        if (targetIndex < 0) {
          return currentProfile;
        }
        const nextNpc =
          regeneratedProfile.playableNpcs[targetIndex] ??
          regeneratedProfile.playableNpcs.find(
            (entry) =>
              entry.name === currentProfile.playableNpcs[targetIndex]?.name,
          );
        if (!nextNpc) {
          return currentProfile;
        }

        return {
          ...currentProfile,
          playableNpcs: currentProfile.playableNpcs.map((entry, index) =>
            index === targetIndex ? nextNpc : entry,
          ),
        };
      },
      {
        confirmMessage: '确认重新生成这个可扮演角色吗？当前角色的 AI 生成内容会被替换。',
        generationMode: 'full',
      },
    );
  };

  const regenerateStoryNpc = async (id: string) => {
    await regenerateFromCurrentProfile(
      (currentProfile, regeneratedProfile) => {
        const targetIndex = currentProfile.storyNpcs.findIndex(
          (entry) => entry.id === id,
        );
        if (targetIndex < 0) {
          return currentProfile;
        }
        const nextNpc =
          regeneratedProfile.storyNpcs[targetIndex] ??
          regeneratedProfile.storyNpcs.find(
            (entry) => entry.name === currentProfile.storyNpcs[targetIndex]?.name,
          );
        if (!nextNpc) {
          return currentProfile;
        }

        const nextStoryNpcs = currentProfile.storyNpcs.map((entry, index) =>
          index === targetIndex ? nextNpc : entry,
        );

        return {
          ...currentProfile,
          storyNpcs: nextStoryNpcs,
          landmarks: currentProfile.landmarks.map((landmark) => ({
            ...landmark,
            sceneNpcIds: landmark.sceneNpcIds.map((npcId) =>
              npcId === id ? nextNpc.id : npcId,
            ),
          })),
        };
      },
      {
        confirmMessage: '确认重新生成这个场景角色吗？当前角色的 AI 生成内容会被替换。',
        generationMode: 'full',
      },
    );
  };

  const regenerateLandmark = async (id: string) => {
    await regenerateFromCurrentProfile(
      (currentProfile, regeneratedProfile) => {
        const targetIndex = currentProfile.landmarks.findIndex(
          (entry) => entry.id === id,
        );
        if (targetIndex < 0) {
          return currentProfile;
        }
        const nextLandmark =
          regeneratedProfile.landmarks[targetIndex] ??
          regeneratedProfile.landmarks.find(
            (entry) => entry.name === currentProfile.landmarks[targetIndex]?.name,
          );
        if (!nextLandmark) {
          return currentProfile;
        }

        return {
          ...currentProfile,
          landmarks: currentProfile.landmarks.map((entry, index) =>
            index === targetIndex ? nextLandmark : entry,
          ),
        };
      },
      {
        confirmMessage: '确认重新生成这个关键地点吗？当前场景的 AI 生成内容会被替换。',
        generationMode: 'full',
      },
    );
  };

  const regenerateStoryExpansion = async () => {
    await regenerateFromCurrentProfile(
      (currentProfile, regeneratedProfile) => ({
        ...currentProfile,
        storyNpcs: regeneratedProfile.storyNpcs,
      }),
      {
        confirmMessage:
          '确认重新生成长尾场景角色吗？已锁定锚点会保留，其余场景角色会被新的生成结果替换。',
        generationMode: 'full',
      },
    );
  };

  const regenerateLandmarkNetwork = async () => {
    await regenerateFromCurrentProfile(
      (currentProfile, regeneratedProfile) => ({
        ...currentProfile,
        landmarks: currentProfile.landmarks.map((landmark, index) => ({
          ...landmark,
          sceneNpcIds:
            regeneratedProfile.landmarks[index]?.sceneNpcIds ??
            landmark.sceneNpcIds,
          connections:
            regeneratedProfile.landmarks[index]?.connections ??
            landmark.connections,
        })),
      }),
      {
        confirmMessage:
          '确认重新生成场景网络吗？已锁定场景名称与描述会保留，但 NPC 分布和连接关系会按最新结果刷新。',
        generationMode: 'full',
      },
    );
  };

  const createCustomWorld = async () => {
    if (isGeneratingCustomWorld) {
      return;
    }

    const generationText =
      buildCustomWorldCreatorIntentGenerationText(
        customWorldCreatorIntent,
      ).trim() || customWorldCreatorIntent.rawSettingText.trim();
    const settingText = customWorldSettingPreview.trim() || generationText;

    if (!generationText) {
      setCustomWorldError(
        customWorldCreatorIntent.sourceMode === 'card'
          ? '请至少填写一个世界锚点。'
          : '请先输入世界设置。',
      );
      return;
    }

    const abortController = new AbortController();
    customWorldAbortControllerRef.current?.abort();
    customWorldAbortControllerRef.current = abortController;
    setCustomWorldError(null);
    setGeneratedCustomWorldProfile(null);
    setCustomWorldProgress(null);
    setShowCustomWorldModal(false);
    setSelectionStage('custom-world-generating');
    setIsGeneratingCustomWorld(true);

    try {
      const profile = await generateCustomWorldProfile(
        {
          settingText,
          creatorIntent: customWorldCreatorIntent,
          generationMode: customWorldGenerationMode,
        },
        {
          signal: abortController.signal,
          onProgress: setCustomWorldProgress,
        },
      );
      if (abortController.signal.aborted) {
        return;
      }
      const persistedProfile = generatedCustomWorldProfile
        ? {
            ...profile,
            id: generatedCustomWorldProfile.id,
          }
        : profile;
      const savedProfiles = upsertSavedCustomWorldProfile(persistedProfile);
      setSavedCustomWorldProfiles(savedProfiles);
      setGeneratedCustomWorldProfile(null);
      setCustomWorldError(null);
      setCustomWorldProgress(null);
      setSelectionStage('world');
    } catch (error) {
      if (abortController.signal.aborted) {
        setCustomWorldError('世界生成已中断。你可以返回修改设定，或重新开始。');
        return;
      }
      setCustomWorldError(
        error instanceof Error ? error.message : '生成自定义世界失败。',
      );
    } finally {
      if (customWorldAbortControllerRef.current === abortController) {
        customWorldAbortControllerRef.current = null;
      }
      setIsGeneratingCustomWorld(false);
    }
  };

  const interruptCustomWorldGeneration = () => {
    if (!isGeneratingCustomWorld || !customWorldAbortControllerRef.current) {
      return;
    }

    const confirmed = window.confirm(
      '确认中断当前世界生成吗？本轮未完成的内容不会保留。',
    );
    if (!confirmed) {
      return;
    }

    customWorldAbortControllerRef.current.abort(new Error('世界生成已中断。'));
  };

  return (
    <>
      <AnimatePresence mode="wait">
        {!gameState.worldType && selectionStage === 'start' && (
          <motion.div
            key="start-screen"
            initial={{ opacity: 0, y: 12 }}
            animate={{ opacity: 1, y: 0 }}
            exit={{ opacity: 0, y: -12 }}
            className="flex h-full w-full items-center justify-center"
          >
            <div className="flex h-full w-full max-w-sm flex-col gap-5 py-4 sm:py-6">
              <div className="flex min-h-0 flex-1 items-center">
                <div className="flex w-full flex-col gap-3">
                  {hasSavedGame && (
                    <button
                      type="button"
                      onClick={handleContinueGame}
                      className="pixel-nine-slice pixel-pressable w-full text-left"
                      style={getNineSliceStyle(UI_CHROME.choiceButton, {
                        paddingX: 18,
                        paddingY: 13,
                      })}
                    >
                      <div className="flex items-center justify-between">
                        <span className="text-base font-semibold text-white">
                          继续游戏
                        </span>
                        <span className="text-white/60">开始</span>
                      </div>
                    </button>
                  )}
                  <button
                    type="button"
                    onClick={() => {
                      handleStartNewGame();
                      setGeneratedCustomWorldProfile(null);
                      setCustomWorldCreatorIntent(
                        createEmptyCustomWorldCreatorIntent('freeform'),
                      );
                      setCustomWorldGenerationMode('fast');
                      setCustomWorldError(null);
                      setCustomWorldProgress(null);
                      setShowCustomWorldModal(false);
                      setSelectionStage('world');
                    }}
                    className="pixel-nine-slice pixel-pressable w-full text-left"
                    style={getNineSliceStyle(UI_CHROME.choiceButton, {
                      paddingX: 18,
                      paddingY: 13,
                    })}
                  >
                    <div className="flex items-center justify-between">
                      <span className="text-base font-semibold text-white">
                        {hasSavedGame ? '新游戏' : '开始游戏'}
                      </span>
                      <span className="text-white/60">开始</span>
                    </div>
                  </button>
                  <button
                    type="button"
                    onClick={() => setShowDeveloperTeamModal(true)}
                    className="pixel-nine-slice pixel-pressable w-full text-left"
                    style={getNineSliceStyle(UI_CHROME.choiceButton, {
                      paddingX: 18,
                      paddingY: 13,
                    })}
                  >
                    <div className="flex items-center justify-between">
                      <span className="text-base font-semibold text-white">
                        开发团队
                      </span>
                      <span className="text-white/60">查看</span>
                    </div>
                  </button>
                </div>
              </div>
              <div
                className="pixel-nine-slice pixel-panel w-full"
                style={getNineSliceStyle(UI_CHROME.panel, {
                  paddingX: 12,
                  paddingY: 10,
                })}
              >
                <div className="text-[10px] font-bold tracking-[0.2em] text-emerald-200/75">
                  联系方式
                </div>
                <div className="mt-3 space-y-2">
                  {START_SCREEN_CONTACTS.map((contact) => (
                    <div
                      key={contact.label}
                      className="flex items-center justify-between gap-3 rounded-xl border border-white/8 bg-black/20 px-3 py-2 text-sm text-zinc-200"
                    >
                      <span className="text-zinc-400">
                        {contact.label}
                      </span>
                      <span className="font-semibold text-white">
                        {contact.value}
                      </span>
                    </div>
                  ))}
                </div>
              </div>
            </div>
          </motion.div>
        )}

        {!gameState.worldType && selectionStage === 'world' && (
          <motion.div
            key="world-select"
            initial={{ opacity: 0, y: 12 }}
            animate={{ opacity: 1, y: 0 }}
            exit={{ opacity: 0, y: -12 }}
            className="flex h-full min-h-0 flex-col"
          >
            <div className="mb-4 flex items-center justify-between gap-3">
              <div className="text-sm font-bold tracking-[0.2em] text-zinc-400">
                选择世界
              </div>
              <button
                type="button"
                onClick={() => {
                  setGeneratedCustomWorldProfile(null);
                  setSelectionStage('start');
                }}
                className="rounded-full border border-white/10 bg-black/18 px-3 py-1.5 text-[11px] text-zinc-300 transition-colors hover:text-white"
              >
                返回
              </button>
            </div>

            <div className="min-h-0 flex-1 overflow-y-auto pr-1">
              <div className="grid gap-3 pb-1 md:grid-cols-2 xl:grid-cols-3">
                {worldCards.map((world) => (
                  <button
                    key={world.id}
                    type="button"
                    onClick={() => handleWorldSelect(world.id)}
                    className="pixel-nine-slice pixel-pressable order-2 relative flex min-h-[12.5rem] flex-col items-start justify-between overflow-hidden text-left"
                    style={getNineSliceStyle(world.texture, {
                      paddingX: 18,
                      paddingY: 16,
                    })}
                  >
                    {world.sceneImage && (
                      <img
                        src={world.sceneImage}
                        alt={world.subtitle}
                        className="absolute inset-0 h-full w-full object-cover opacity-25"
                        style={{ imageRendering: 'pixelated' }}
                      />
                    )}
                    <div className="absolute inset-0 bg-[linear-gradient(180deg,rgba(8,10,14,0.12),rgba(8,10,14,0.82))]" />
                    <div className="absolute right-3 top-3 flex h-9 w-9 items-center justify-center rounded-full border border-white/10 bg-black/25">
                      <PixelIcon
                        src={world.featureIcon}
                        className="h-5 w-5 opacity-95"
                      />
                    </div>
                    <div className="relative z-10 flex h-full w-full flex-col">
                      <div className="flex items-start justify-between gap-3">
                        <div className="rounded-full border border-white/10 bg-black/24 px-3 py-1 text-[10px] tracking-[0.2em] text-zinc-100">
                          {world.name}
                        </div>
                        <PixelIcon
                          src={world.icon}
                          className="h-10 w-10 opacity-95"
                        />
                      </div>
                      <div className="mt-auto">
                        <div className="text-3xl font-black text-white">
                          {world.subtitle}
                        </div>
                        <div className="mt-2 flex items-center gap-2">
                          <span className="rounded-full border border-emerald-400/20 bg-emerald-500/10 px-3 py-1 text-[10px] text-emerald-100">
                            在线 {world.onlineCount}
                          </span>
                          <span className="rounded-full border border-white/10 bg-black/24 px-2.5 py-1 text-[10px] text-zinc-100">
                            推荐
                          </span>
                        </div>
                      </div>
                    </div>
                  </button>
                ))}

                {savedCustomWorldCards.map((world) => (
                  <div key={world.id} className="order-1 relative">
                    <button
                      type="button"
                      onClick={() =>
                        handleWorldSelect(WorldType.CUSTOM, world.profile)
                      }
                      className="pixel-nine-slice pixel-pressable relative flex min-h-[12.5rem] w-full flex-col items-start justify-between overflow-hidden text-left"
                      style={getNineSliceStyle(world.texture, {
                        paddingX: 18,
                        paddingY: 16,
                      })}
                    >
                      {world.sceneImage && (
                        <img
                          src={world.sceneImage}
                          alt={world.profile.name}
                          className="absolute inset-0 h-full w-full object-cover opacity-25"
                          style={{ imageRendering: 'pixelated' }}
                        />
                      )}
                      <div className="absolute inset-0 bg-[linear-gradient(180deg,rgba(8,10,14,0.14),rgba(8,10,14,0.84))]" />
                      <div className="relative z-10 flex h-full w-full flex-col">
                        <div className="flex items-start justify-between gap-3 pr-16">
                          <div className="rounded-full border border-sky-300/20 bg-sky-500/10 px-3 py-1 text-[10px] tracking-[0.2em] text-sky-100">
                            已保存
                          </div>
                          <div className="rounded-full border border-white/10 bg-black/24 px-2.5 py-1 text-[10px] text-zinc-100">
                            {world.accentLabel === '武侠基础'
                              ? '武侠'
                              : '仙侠'}
                          </div>
                        </div>
                        <div className="mt-auto">
                          <div className="text-2xl font-black text-white sm:text-[1.7rem]">
                            {world.profile.name}
                          </div>
                          <div className="mt-2 line-clamp-2 max-w-[18rem] text-xs leading-5 text-zinc-200/90">
                            {world.profile.summary}
                          </div>
                          <div className="mt-3 flex flex-wrap gap-2">
                            <span className="rounded-full border border-emerald-400/20 bg-emerald-500/10 px-3 py-1 text-[10px] text-emerald-100">
                              可玩角色 {world.profile.playableNpcs.length}
                            </span>
                            <span className="rounded-full border border-white/10 bg-black/24 px-2.5 py-1 text-[10px] text-zinc-100">
                              地标 {world.profile.landmarks.length}
                            </span>
                          </div>
                        </div>
                      </div>
                    </button>
                    <button
                      type="button"
                      onClick={() => openSavedCustomWorldEditor(world.profile)}
                      className="absolute right-3 top-3 z-20 rounded-full border border-white/10 bg-black/35 px-3 py-1.5 text-[11px] text-zinc-100 transition-colors hover:text-white"
                    >
                      编辑
                    </button>
                  </div>
                ))}

                <button
                  type="button"
                  onClick={openCustomWorldCreator}
                  className="pixel-nine-slice pixel-pressable order-first relative flex min-h-[12.5rem] flex-col items-start justify-between overflow-hidden text-left"
                  style={getNineSliceStyle(UI_CHROME.panel, {
                    paddingX: 18,
                    paddingY: 16,
                  })}
                >
                  <div className="absolute inset-0 bg-[radial-gradient(circle_at_top_left,rgba(125,211,252,0.18),transparent_42%),linear-gradient(180deg,rgba(8,10,14,0.18),rgba(8,10,14,0.82))]" />
                  <div className="absolute right-3 top-3 flex h-9 w-9 items-center justify-center rounded-full border border-sky-300/20 bg-sky-500/10">
                    <PixelIcon
                      src={CHROME_ICONS.refreshOptions}
                      className="h-5 w-5 opacity-95"
                    />
                  </div>
                  <div className="relative z-10 flex h-full w-full flex-col">
                    <div className="rounded-full border border-sky-300/20 bg-sky-500/10 px-3 py-1 text-[10px] tracking-[0.2em] text-sky-100">
                      自定义
                    </div>
                    <div className="mt-auto">
                      <div className="text-3xl font-black text-white">
                        创建自定义世界
                      </div>
                      <div className="mt-2 max-w-[16rem] text-sm leading-6 text-zinc-300">
                        输入世界设置，让系统生成可玩角色、场景角色、场景内 NPC 分布与场景连接关系。
                      </div>
                    </div>
                  </div>
                </button>
              </div>
            </div>
          </motion.div>
        )}

        {!gameState.worldType &&
          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"
            >
              <CustomWorldGenerationView
                settingText={customWorldSettingPreview}
                progress={customWorldProgress}
                isGenerating={isGeneratingCustomWorld}
                error={customWorldError}
                onBack={leaveCustomWorldGeneration}
                onEditSetting={editCustomWorldSetting}
                onRetry={() => {
                  void createCustomWorld();
                }}
                onInterrupt={interruptCustomWorldGeneration}
              />
            </motion.div>
          )}

        {!gameState.worldType &&
          selectionStage === 'custom-world-result' &&
          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"
            >
              <CustomWorldResultView
                profile={generatedCustomWorldProfile}
                previewCharacters={previewCustomWorldCharacters}
                isGenerating={isGeneratingCustomWorld}
                progress={customWorldProgress?.overallProgress ?? 0}
                progressLabel={customWorldProgress?.phaseLabel ?? ''}
                error={customWorldError}
                onProfileChange={setGeneratedCustomWorldProfile}
                onBack={leaveCustomWorldResult}
                onEditSetting={editCustomWorldSetting}
                onRegenerate={() => {
                  void createCustomWorld();
                }}
                onContinueExpand={() => {
                  void continueExpandCustomWorld();
                }}
                onRegeneratePlayableNpc={(id) => {
                  void regeneratePlayableNpc(id);
                }}
                onRegenerateStoryNpc={(id) => {
                  void regenerateStoryNpc(id);
                }}
                onRegenerateLandmark={(id) => {
                  void regenerateLandmark(id);
                }}
                onRegenerateStoryExpansion={() => {
                  void regenerateStoryExpansion();
                }}
                onRegenerateLandmarkNetwork={() => {
                  void regenerateLandmarkNetwork();
                }}
                onSave={saveGeneratedCustomWorld}
              />
            </motion.div>
          )}
      </AnimatePresence>

      <CustomWorldCreatorModal
        isOpen={showCustomWorldModal}
        creatorIntent={customWorldCreatorIntent}
        onCreatorIntentChange={(value) => {
          setCustomWorldCreatorIntent(value);
          if (customWorldError) setCustomWorldError(null);
        }}
        generationMode={customWorldGenerationMode}
        onGenerationModeChange={setCustomWorldGenerationMode}
        onClose={() => {
          if (isGeneratingCustomWorld) return;
          setShowCustomWorldModal(false);
        }}
        onSubmit={() => {
          void createCustomWorld();
        }}
        isGenerating={isGeneratingCustomWorld}
        progress={customWorldProgress?.overallProgress ?? 0}
        progressLabel={customWorldProgress?.phaseLabel ?? '正在准备生成'}
        error={customWorldError}
      />

      <DeveloperTeamModal
        isOpen={showDeveloperTeamModal}
        message={DEVELOPER_TEAM_MESSAGE}
        onClose={() => setShowDeveloperTeamModal(false)}
      />
    </>
  );
}
