import { lazy, Suspense, useEffect } from 'react';

import { normalizePlayerProgressionState } from '../../data/playerProgression';
import {
  APP_RUNTIME_ROUTES,
  pushAppHistoryPath,
} from '../../routing/appPageRoutes';
import { UI_CHROME } from '../../uiAssets';
import { useAuthUi } from '../auth/AuthUiContext';
import { RpgRuntimeStageRouter } from './RpgRuntimeStageRouter';
import type { RpgRuntimeShellProps as RpgRuntimeShellComponentProps } from './types';
import { useRpgRuntimeShellViewModel } from './useRpgRuntimeShellViewModel';

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

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

/**
 * RPG 运行态总外壳。
 * 这里承接运行时主布局、画布舞台、主阶段路由和 overlay host，
 * 保持原有 UI 结构不变，只把真实实现迁入 RPG 域目录。
 */
export function RpgRuntimeShell({
  session,
  story,
  entry,
  companions,
  audio,
  chrome,
  onExitTestRuntime,
}: RpgRuntimeShellComponentProps) {
  const authUi = useAuthUi();
  const isPlatformShell = !session.gameState.worldType;
  const platformThemeClass =
    authUi?.platformTheme === 'dark'
      ? 'platform-theme--dark'
      : 'platform-theme--light';
  const {
    gameState,
    isLoading,
    aiError,
    bottomTab,
    setBottomTab,
    isMapOpen,
    setIsMapOpen,
  } = session;
  const {
    displayedOptions,
    canRefreshOptions,
    handleRefreshOptions,
    handleNpcChatInput,
    refreshNpcChatOptions,
    exitNpcChat,
    handleMapTravelToScene,
    npcUi,
    characterChatUi,
    inventoryUi,
    battleRewardUi,
    questUi,
    npcChatQuestOfferUi,
    goalUi,
  } = story;
  const {
    hasSavedGame,
    savedSnapshot,
    handleContinueGame,
    handleStartNewGame,
    handleSaveAndExit,
    handleCustomWorldSelect,
    handleBackToWorldSelect,
    handleCharacterSelect,
  } = entry;
  const { companionRenderStates, onBenchCompanion, onActivateRosterCompanion } =
    companions;
  const { musicVolume, onMusicVolumeChange } = audio;
  const {
    selectionStage,
    setSelectionStage,
    overlayPanel,
    openOverlayPanel,
    closeOverlayPanel,
    selectedSceneEntity,
    setSelectedSceneEntity,
    openPartyMemberDetails,
    closeAdventureEntityModal,
    showTeamModal,
    openCampModal,
    closeCampModal,
    resetForSaveAndExit,
    shouldMountAdventureEntityModal,
    shouldMountCampModal,
    shouldMountMapModal,
    shouldMountCharacterChatModal,
    shouldMountNpcModals,
    visibleGameState,
    visibleCurrentStory,
    sceneTransitionPhase,
    sceneTransitionToken,
    setSceneTransitionDurations,
    isCharacterSelectionStage,
    shouldHideStoryOptions,
    hideSelectionHero,
    dialogueIndicator,
    characterChatSummaries,
    canvasCompanionRenderStates,
    adventureStatistics,
    handleSceneTransitionChoice,
  } = useRpgRuntimeShellViewModel({
    session,
    story,
    companions,
  });
  const playerProgression = normalizePlayerProgressionState(
    visibleGameState.playerProgression ?? null,
  );
  const playerProgressionRatio =
    playerProgression.xpToNextLevel <= 0
      ? 1
      : Math.max(
          0,
          Math.min(
            1,
            playerProgression.currentLevelXp / playerProgression.xpToNextLevel,
          ),
        );
  const isTestRuntime = gameState.runtimeMode === 'test';

  useEffect(() => {
    if (gameState.worldType && !gameState.playerCharacter) {
      pushAppHistoryPath(APP_RUNTIME_ROUTES['rpg-character-select']);
      return;
    }

    if (visibleGameState.playerCharacter && visibleCurrentStory) {
      pushAppHistoryPath(APP_RUNTIME_ROUTES['rpg-adventure']);
    }
  }, [
    gameState.playerCharacter,
    gameState.worldType,
    visibleCurrentStory,
    visibleGameState.playerCharacter,
  ]);

  return (
    <div
      className={`${isPlatformShell ? `platform-ui-shell platform-theme ${platformThemeClass} text-[var(--platform-text-strong)]` : 'fusion-pixel-app pixel-root-shell text-zinc-100'} flex h-screen max-h-screen flex-col overflow-hidden font-sans`}
      style={{
        backgroundImage: isPlatformShell
          ? 'var(--platform-body-fill)'
          : `linear-gradient(rgba(8, 10, 14, 0.82), rgba(8, 10, 14, 0.82)), url("${UI_CHROME.appBackground}")`,
        backgroundPosition: isPlatformShell ? undefined : 'center',
        backgroundRepeat: isPlatformShell ? undefined : 'repeat',
      }}
    >
      {gameState.worldType ? (
        <Suspense fallback={null}>
          <RpgRuntimeCanvasStage
            gameState={gameState}
            visibleGameState={visibleGameState}
            hideSelectionHero={hideSelectionHero}
            canvasCompanionRenderStates={canvasCompanionRenderStates}
            dialogueIndicator={dialogueIndicator}
            sceneTransitionPhase={sceneTransitionPhase}
            sceneTransitionToken={sceneTransitionToken}
            setSelectedSceneEntity={setSelectedSceneEntity}
            setIsMapOpen={setIsMapOpen}
            setSceneTransitionDurations={setSceneTransitionDurations}
          />
        </Suspense>
      ) : null}

      {visibleGameState.playerCharacter && !chrome?.hidePlayerLevelBadge && (
        <div
          className="pointer-events-none fixed z-[26] w-[4.5rem] drop-shadow-[0_2px_8px_rgba(0,0,0,0.75)]"
          style={{
            top: 'calc(env(safe-area-inset-top, 0px) + 0.65rem)',
            left: 'calc(env(safe-area-inset-left, 0px) + 0.7rem)',
          }}
        >
          <div className="flex items-end gap-1.5 text-amber-50">
            <span className="text-[10px] font-semibold uppercase leading-none tracking-[0.14em] text-amber-100/80">
              Lv
            </span>
            <span className="text-2xl font-black leading-none tracking-[-0.08em] text-white">
              {playerProgression.level}
            </span>
          </div>
          <div className="mt-1 h-1 overflow-hidden rounded-full bg-black/45">
            <div
              className="h-full rounded-full bg-[linear-gradient(90deg,rgba(251,191,36,0.65),rgba(254,240,138,0.95))]"
              style={{
                width:
                  playerProgressionRatio <= 0
                    ? '0%'
                    : `${Math.max(8, playerProgressionRatio * 100)}%`,
              }}
            />
          </div>
        </div>
      )}

      {gameState.worldType && isTestRuntime && onExitTestRuntime ? (
        <div
          className="fixed inset-x-0 z-[170] flex justify-center px-4"
          style={{
            top: 'calc(36vh - 3.25rem)',
          }}
        >
          <button
            type="button"
            onClick={onExitTestRuntime}
            className="inline-flex min-h-[2.75rem] items-center justify-center rounded-full border border-white/15 bg-black/65 px-5 text-sm font-semibold text-white shadow-[0_12px_30px_rgba(0,0,0,0.38)] backdrop-blur-sm transition hover:border-white/28 hover:bg-black/78"
          >
            结束测试
          </button>
        </div>
      ) : null}

      <RpgRuntimeStageRouter
        gameState={gameState}
        visibleGameState={visibleGameState}
        visibleCurrentStory={visibleCurrentStory}
        isLoading={isLoading}
        aiError={aiError}
        bottomTab={bottomTab}
        setBottomTab={setBottomTab}
        selectionStage={selectionStage}
        setSelectionStage={setSelectionStage}
        isCharacterSelectionStage={isCharacterSelectionStage}
        hasSavedGame={hasSavedGame}
        savedSnapshot={savedSnapshot}
        handleContinueGame={handleContinueGame}
        handleStartNewGame={handleStartNewGame}
        handleCustomWorldSelect={handleCustomWorldSelect}
        handleBackToWorldSelect={handleBackToWorldSelect}
        handleCharacterSelect={handleCharacterSelect}
        displayedOptions={displayedOptions}
        hideStoryOptions={shouldHideStoryOptions}
        canRefreshOptions={canRefreshOptions}
        handleRefreshOptions={handleRefreshOptions}
        refreshNpcChatOptions={refreshNpcChatOptions}
        handleSceneTransitionChoice={handleSceneTransitionChoice}
        handleNpcChatInput={handleNpcChatInput}
        exitNpcChat={exitNpcChat}
        characterChatUi={characterChatUi}
        inventoryUi={inventoryUi}
        battleRewardUi={battleRewardUi}
        questUi={questUi}
        npcChatQuestOfferUi={npcChatQuestOfferUi}
        goalUi={goalUi}
        companionRenderStates={companionRenderStates}
        characterChatSummaries={characterChatSummaries}
        openOverlayPanel={openOverlayPanel}
        openCampModal={openCampModal}
        openPartyMemberDetails={openPartyMemberDetails}
        adventureStatistics={adventureStatistics}
        musicVolume={musicVolume}
        onMusicVolumeChange={onMusicVolumeChange}
        resetForSaveAndExit={resetForSaveAndExit}
        handleSaveAndExit={handleSaveAndExit}
      />

      {gameState.worldType ? (
        <Suspense fallback={null}>
          <RpgRuntimeOverlayHost
            gameState={gameState}
            isLoading={isLoading}
            isMapOpen={isMapOpen}
            setIsMapOpen={setIsMapOpen}
            npcUi={npcUi}
            characterChatUi={characterChatUi}
            inventoryUi={inventoryUi}
            companionRenderStates={companionRenderStates}
            characterChatSummaries={characterChatSummaries}
            overlayPanel={overlayPanel}
            closeOverlayPanel={closeOverlayPanel}
            openCampModal={openCampModal}
            openPartyMemberDetails={openPartyMemberDetails}
            shouldMountAdventureEntityModal={shouldMountAdventureEntityModal}
            selectedSceneEntity={selectedSceneEntity}
            closeAdventureEntityModal={closeAdventureEntityModal}
            shouldMountCampModal={shouldMountCampModal}
            showTeamModal={showTeamModal}
            closeCampModal={closeCampModal}
            onBenchCompanion={onBenchCompanion}
            onActivateRosterCompanion={onActivateRosterCompanion}
            shouldMountMapModal={shouldMountMapModal}
            handleMapTravelToScene={handleMapTravelToScene}
            shouldMountCharacterChatModal={shouldMountCharacterChatModal}
            shouldMountNpcModals={shouldMountNpcModals}
          />
        </Suspense>
      ) : null}
    </div>
  );
}

export type RpgRuntimeShellProps = RpgRuntimeShellComponentProps;

export default RpgRuntimeShell;
