import {
  Archive,
  ArrowRight,
  Bell,
  BookOpen,
  Camera,
  ChevronRight,
  Clock3,
  Coins,
  Copy,
  Crown,
  House,
  LogIn,
  MessageCircle,
  Pencil,
  Search,
  Settings,
  Sparkles,
  Tags,
  Ticket,
  UserPlus,
  UserRound,
} from 'lucide-react';
import {
  type ComponentType,
  type ReactNode,
  useEffect,
  useMemo,
  useState,
} from 'react';

import type {
  CustomWorldLibraryEntry,
  PlatformBrowseHistoryEntry,
  ProfileDashboardCardKey,
  ProfileDashboardSummary,
  ProfileWalletLedgerResponse,
  ProfileRechargeCenterResponse,
  ProfileRechargeProduct,
  ProfileReferralInviteCenterResponse,
  ProfileSaveArchiveSummary,
  RedeemProfileReferralInviteCodeResponse,
} from '../../../packages/shared/src/contracts/runtime';
import type { HydratedSavedGameSnapshot } from '../../persistence/runtimeSnapshotTypes';
import type { AuthUser } from '../../services/authService';
import {
  createRpgProfileRechargeOrder,
  getRpgProfileRechargeCenter,
  getRpgProfileReferralInviteCenter,
  getRpgProfileWalletLedger,
  redeemRpgProfileReferralInviteCode,
} from '../../services/rpg-entry/rpgProfileClient';
import type { CustomWorldProfile } from '../../types';
import { useAuthUi } from '../auth/AuthUiContext';
import { ResolvedAssetImage } from '../ResolvedAssetImage';
import { RpgEntryBrandLogo } from './RpgEntryBrandLogo';
import {
  buildPlatformWorldTags,
  describePlatformThemeLabel,
  formatPlatformWorldTime,
  isBigFishGalleryEntry,
  isPuzzleGalleryEntry,
  type PlatformPublicGalleryCard,
  type PlatformWorldCardLike,
  resolvePlatformWorldCoverImage,
  resolvePlatformWorldLeadPortrait,
} from './rpgEntryWorldPresentation';

export type PlatformHomeTab =
  | 'home'
  | 'category'
  | 'create'
  | 'saves'
  | 'profile';
export interface RpgEntryHomeViewProps {
  activeTab: PlatformHomeTab;
  onTabChange: (tab: PlatformHomeTab) => void;
  hasSavedGame: boolean;
  savedSnapshot: HydratedSavedGameSnapshot | null;
  saveEntries: ProfileSaveArchiveSummary[];
  saveError: string | null;
  featuredEntries: PlatformPublicGalleryCard[];
  latestEntries: PlatformPublicGalleryCard[];
  myEntries: CustomWorldLibraryEntry<CustomWorldProfile>[];
  historyEntries: PlatformBrowseHistoryEntry[];
  profileDashboard: ProfileDashboardSummary | null;
  isLoadingPlatform: boolean;
  isLoadingDashboard: boolean;
  isResumingSaveWorldKey: string | null;
  platformError: string | null;
  dashboardError: string | null;
  onContinueGame: (snapshot?: HydratedSavedGameSnapshot | null) => void;
  onResumeSave: (entry: ProfileSaveArchiveSummary) => void;
  onOpenCreateWorld: () => void;
  onOpenCreateTypePicker: () => void;
  onOpenGalleryDetail: (entry: PlatformPublicGalleryCard) => void;
  onOpenLibraryDetail: (
    entry: CustomWorldLibraryEntry<CustomWorldProfile>,
  ) => void;
  onDeleteLibraryEntry?: (
    entry: CustomWorldLibraryEntry<CustomWorldProfile>,
  ) => void;
  deletingLibraryEntryId?: string | null;
  onSearchPublicCode?: (keyword: string) => void | Promise<void>;
  isSearchingPublicCode?: boolean;
  onOpenProfileDashboardCard?: (cardKey: ProfileDashboardCardKey) => void;
  onRechargeSuccess?: () => void | Promise<void>;
  createTabContent?: ReactNode;
}

const PANEL_SURFACE_CLASS = 'platform-surface platform-surface--soft';
const HERO_SURFACE_CLASS =
  'platform-surface platform-surface--hero platform-interactive-card min-w-0';
const MOBILE_PAGE_STAGE_CLASS =
  'platform-page-stage platform-remap-surface min-w-0 space-y-4 overflow-hidden pb-2';
const DESKTOP_PAGE_STAGE_CLASS =
  'platform-page-stage platform-remap-surface min-w-0 space-y-5 pb-4';
const DESKTOP_LAYOUT_QUERY = '(min-width: 1024px)';
const PLATFORM_HOME_TABS: PlatformHomeTab[] = [
  'home',
  'category',
  'create',
  'saves',
  'profile',
];
type ProfilePopupPanel = 'invite' | 'redeem' | 'community';

function usePlatformDesktopLayout() {
  const [isDesktopLayout, setIsDesktopLayout] = useState(() => {
    if (
      typeof window === 'undefined' ||
      typeof window.matchMedia !== 'function'
    ) {
      return false;
    }

    return window.matchMedia(DESKTOP_LAYOUT_QUERY).matches;
  });

  useEffect(() => {
    if (
      typeof window === 'undefined' ||
      typeof window.matchMedia !== 'function'
    ) {
      return;
    }

    const mediaQuery = window.matchMedia(DESKTOP_LAYOUT_QUERY);
    const updateLayout = (event?: MediaQueryListEvent) => {
      setIsDesktopLayout(event?.matches ?? mediaQuery.matches);
    };

    updateLayout();

    // 平台页只挂载当前断点外壳，避免隐藏的移动端/桌面端内容重复抢占查询。
    if (typeof mediaQuery.addEventListener === 'function') {
      mediaQuery.addEventListener('change', updateLayout);
      return () => mediaQuery.removeEventListener('change', updateLayout);
    }

    mediaQuery.addListener(updateLayout);
    return () => mediaQuery.removeListener(updateLayout);
  }, []);

  return isDesktopLayout;
}

function ResolvedAssetBackdrop({
  src,
  alt,
  className,
  ariaHidden = false,
}: {
  src?: string | null;
  alt: string;
  className: string;
  ariaHidden?: boolean;
}) {
  return (
    <ResolvedAssetImage
      src={src}
      alt={alt}
      aria-hidden={ariaHidden}
      className={className}
    />
  );
}

function SectionHeader({ title, detail }: { title: string; detail: string }) {
  return (
    <div className="mb-3">
      <div className="text-[10px] font-semibold tracking-[0.26em] text-[var(--platform-text-soft)]">
        {detail}
      </div>
      <div className="mt-1 text-base font-semibold text-[var(--platform-text-strong)]">
        {title}
      </div>
    </div>
  );
}

function PublicCodeSearchBar({
  value,
  onChange,
  onSubmit,
  isSearching,
  className,
}: {
  value: string;
  onChange: (value: string) => void;
  onSubmit: () => void;
  isSearching: boolean;
  className?: string;
}) {
  return (
    <div
      className={`platform-desktop-search flex min-w-0 items-center gap-3 px-4 py-3 text-[var(--platform-text-soft)] ${className ?? ''}`}
    >
      <Search className="h-4 w-4 shrink-0" />
      <input
        value={value}
        onChange={(event) => onChange(event.target.value)}
        onKeyDown={(event) => {
          if (event.key === 'Enter') {
            event.preventDefault();
            onSubmit();
          }
        }}
        placeholder="输入 SY / CW / BF / PZ 编号"
        className="w-full min-w-0 bg-transparent text-sm text-[var(--platform-text-strong)] outline-none placeholder:text-[var(--platform-text-soft)]"
      />
      <button
        type="button"
        onClick={onSubmit}
        disabled={!value.trim() || isSearching}
        className="shrink-0 text-xs font-semibold text-[var(--platform-text-soft)] disabled:opacity-50"
      >
        {isSearching ? '搜索中' : '搜索'}
      </button>
    </div>
  );
}

function EmptyShelf({ text }: { text: string }) {
  return (
    <div
      className={`${PANEL_SURFACE_CLASS} min-w-0 rounded-[1.35rem] px-4 py-3 text-sm leading-6 text-[var(--platform-text-base)]`}
    >
      {text}
    </div>
  );
}

function SaveArchivePreview({
  entry,
  label,
  className,
}: {
  entry: ProfileSaveArchiveSummary;
  label: string;
  className: string;
}) {
  return (
    <div
      aria-hidden="true"
      className={`platform-remap-surface relative shrink-0 overflow-hidden rounded-[1.35rem] border border-white/12 bg-black/18 shadow-[var(--platform-desktop-hover-shadow)] ${className}`}
    >
      {entry.coverImageSrc ? (
        <ResolvedAssetBackdrop
          src={entry.coverImageSrc}
          alt=""
          className="absolute inset-0 h-full w-full object-cover"
        />
      ) : (
        <div className="absolute inset-0 bg-[radial-gradient(circle_at_top_left,rgba(255,255,255,0.18),transparent_34%),linear-gradient(145deg,rgba(255,94,125,0.92),rgba(255,150,116,0.88))]" />
      )}
      <div className="absolute inset-0 bg-[var(--platform-card-overlay-soft)]" />
      <div className="absolute inset-x-0 bottom-0 px-2.5 py-2">
        <span className="inline-flex max-w-full items-center rounded-full border border-white/15 bg-black/24 px-2.5 py-1 text-[9px] font-semibold tracking-[0.14em] text-[var(--platform-text-strong)]">
          {label}
        </span>
      </div>
    </div>
  );
}

function WorldCard({
  entry,
  badge,
  metaLabel,
  onClick,
  className,
}: {
  entry: PlatformWorldCardLike;
  badge: string;
  metaLabel: string;
  onClick: () => void;
  className?: string;
}) {
  const coverImage = resolvePlatformWorldCoverImage(entry);
  const leadPortrait = resolvePlatformWorldLeadPortrait(entry);
  const tags = [
    ...new Set(
      buildPlatformWorldTags(entry)
        .map((tag) => tag.trim())
        .filter(Boolean),
    ),
  ].slice(0, 3);

  return (
    <button
      type="button"
      onClick={onClick}
      className={`platform-surface platform-interactive-card relative flex h-[15rem] w-[min(15.25rem,78vw)] shrink-0 flex-col overflow-hidden px-3.5 py-3.5 text-left ${className ?? ''}`}
    >
      {coverImage ? (
        <ResolvedAssetBackdrop
          src={coverImage}
          alt={entry.worldName}
          className="absolute inset-0 h-full w-full object-cover opacity-40"
        />
      ) : null}
      {leadPortrait ? (
        <ResolvedAssetImage
          src={leadPortrait}
          alt=""
          aria-hidden="true"
          className="absolute bottom-2 right-2 h-24 w-24 object-contain opacity-25"
        />
      ) : null}
      <div className="absolute inset-0 bg-[var(--platform-card-overlay-strong)]" />
      <div className="relative z-10 flex h-full flex-col">
        <div className="flex items-start justify-between gap-3">
          <span className="platform-pill platform-pill--warm max-w-[8.5rem] truncate">
            {badge}
          </span>
          <span className="platform-pill platform-pill--neutral px-2.5">
            {metaLabel}
          </span>
        </div>
        <div className="mt-auto">
          <div className="line-clamp-1 text-xl font-black text-[var(--platform-text-strong)]">
            {entry.worldName}
          </div>
          {entry.subtitle ? (
            <div className="mt-1 line-clamp-1 text-[11px] tracking-[0.16em] text-[color:color-mix(in_srgb,var(--platform-text-base)_85%,transparent)]">
              {entry.subtitle}
            </div>
          ) : null}
          <div className="mt-2 line-clamp-2 text-xs leading-5 text-[color:color-mix(in_srgb,var(--platform-text-base)_90%,transparent)]">
            {entry.summaryText || '等待补充世界摘要。'}
          </div>
          <div className="mt-3 flex flex-wrap gap-2">
            {tags.length > 0 ? (
              tags.map((tag, index) => (
                <span
                  key={`world-tag-${index}-${tag || 'empty'}`}
                  className="platform-pill platform-pill--neutral px-2.5"
                >
                  {tag}
                </span>
              ))
            ) : (
              <span className="platform-pill platform-pill--neutral px-2.5">
                {describePublicGalleryCardKind(entry)}
              </span>
            )}
          </div>
        </div>
      </div>
    </button>
  );
}

function CreationLibraryCard({
  entry,
  onClick,
  onDelete,
  isDeleting = false,
}: {
  entry: CustomWorldLibraryEntry<CustomWorldProfile>;
  onClick: () => void;
  onDelete?: () => void;
  isDeleting?: boolean;
}) {
  const coverImage = resolvePlatformWorldCoverImage(entry);
  const leadPortrait = resolvePlatformWorldLeadPortrait(entry);
  const statusLabel = entry.visibility === 'published' ? '已发布' : '草稿';
  const metaLabel =
    entry.visibility === 'published'
      ? formatPlatformWorldTime(entry.publishedAt)
      : '仅自己可见';
  const primaryTag =
    buildPlatformWorldTags(entry)
      .map((tag) => tag.trim())
      .filter(Boolean)[0] ?? describePlatformThemeLabel(entry.themeMode);
  const summaryText =
    entry.summaryText || entry.subtitle || '继续补完这个世界的设定与游玩入口。';

  return (
    <button
      type="button"
      onClick={onClick}
      className="platform-surface platform-interactive-card relative flex min-h-[13rem] w-full min-w-0 flex-col overflow-hidden px-3 py-3 text-left sm:min-h-[14rem] sm:px-3.5 sm:py-3.5"
    >
      {coverImage ? (
        <ResolvedAssetBackdrop
          src={coverImage}
          alt={entry.worldName}
          className="absolute inset-0 h-full w-full object-cover opacity-38"
        />
      ) : null}
      {leadPortrait ? (
        <ResolvedAssetImage
          src={leadPortrait}
          alt=""
          aria-hidden="true"
          className="absolute bottom-1.5 right-1.5 h-16 w-16 object-contain opacity-24 sm:h-20 sm:w-20"
        />
      ) : null}
      <div className="absolute inset-0 bg-[var(--platform-card-overlay-strong)]" />
      {onDelete ? (
        <button
          type="button"
          onClick={(event) => {
            event.stopPropagation();
            onDelete();
          }}
          disabled={isDeleting}
          className="platform-button platform-button--danger absolute right-2 top-2 z-20 min-h-0 rounded-full px-2.5 py-1 text-[10px] disabled:cursor-not-allowed disabled:opacity-60"
        >
          {isDeleting ? '删除中' : '删除'}
        </button>
      ) : null}
      <div className="relative z-10 flex h-full min-w-0 flex-col">
        <div className="flex min-w-0 flex-wrap items-center gap-1.5">
          <span
            className={`inline-flex items-center rounded-full border px-2 py-1 text-[10px] font-semibold tracking-[0.12em] ${
              entry.visibility === 'published'
                ? 'border-emerald-300/25 bg-emerald-500/12 text-emerald-50'
                : 'border-amber-300/25 bg-amber-500/12 text-amber-50'
            }`}
          >
            {statusLabel}
          </span>
          <span className="inline-flex min-w-0 max-w-full items-center rounded-full border border-white/12 bg-black/18 px-2 py-1 text-[10px] font-medium text-[var(--platform-text-base)]">
            <span className="truncate">{metaLabel}</span>
          </span>
        </div>

        <div className="mt-auto min-w-0">
          <div className="line-clamp-2 break-words text-base font-black leading-[1.15] text-[var(--platform-text-strong)] sm:text-[1.12rem]">
            {entry.worldName}
          </div>
          {entry.subtitle ? (
            <div className="mt-1 line-clamp-1 break-words text-[11px] tracking-[0.08em] text-[color:color-mix(in_srgb,var(--platform-text-base)_84%,transparent)]">
              {entry.subtitle}
            </div>
          ) : null}
          <div className="mt-2 line-clamp-3 break-words text-[11px] leading-5 text-[color:color-mix(in_srgb,var(--platform-text-base)_88%,transparent)] sm:text-xs">
            {summaryText}
          </div>
          <div className="mt-3 flex flex-wrap items-center gap-1.5">
            <span className="inline-flex min-w-0 max-w-full items-center rounded-full border border-white/12 bg-black/18 px-2 py-1 text-[10px] font-semibold tracking-[0.1em] text-[color:color-mix(in_srgb,var(--platform-text-strong)_90%,transparent)]">
              <span className="truncate">{primaryTag}</span>
            </span>
            <span className="inline-flex items-center gap-1 text-[11px] font-semibold text-[var(--platform-text-base)]">
              <span>
                {entry.visibility === 'published' ? '进入世界' : '继续创作'}
              </span>
              <ArrowRight className="h-3.5 w-3.5 shrink-0" />
            </span>
          </div>
        </div>
      </div>
    </button>
  );
}

function SaveArchiveCard({
  entry,
  onClick,
  loading = false,
}: {
  entry: ProfileSaveArchiveSummary;
  onClick: () => void;
  loading?: boolean;
}) {
  const summaryText =
    entry.summaryText || entry.subtitle || '继续推进上一次保存的故事。';

  return (
    <button
      type="button"
      onClick={onClick}
      disabled={loading}
      className={`platform-surface platform-surface--soft platform-interactive-card relative flex min-h-[13rem] w-full overflow-hidden p-3.5 text-left sm:min-h-[12.5rem] sm:p-4 ${loading ? 'opacity-80' : ''}`}
    >
      <div className="absolute inset-0 bg-[var(--platform-card-overlay-deep)]" />
      <div className="relative z-10 flex h-full w-full flex-col gap-3">
        <div className="flex flex-wrap items-center justify-between gap-2">
          <span className="platform-pill platform-pill--cool">ARCHIVE</span>
          <span className="rounded-full border border-white/10 bg-black/18 px-2.5 py-1 text-[11px] font-medium text-[var(--platform-text-base)]">
            {loading ? '恢复中' : formatSnapshotTime(entry.lastPlayedAt)}
          </span>
        </div>
        <div className="flex min-w-0 flex-1 items-stretch gap-3 sm:gap-4">
          <div className="min-w-0 flex-1">
            <div className="line-clamp-2 break-words text-[1.15rem] font-black leading-tight text-[var(--platform-text-strong)] sm:text-xl">
              {entry.worldName}
            </div>
            {entry.subtitle ? (
              <div className="mt-1 line-clamp-1 break-words text-sm text-[var(--platform-text-base)]">
                {entry.subtitle}
              </div>
            ) : null}
            <div className="mt-2 line-clamp-3 break-words text-xs leading-5 text-[var(--platform-text-soft)] sm:text-sm">
              {summaryText}
            </div>
            <div className="mt-4 inline-flex items-center gap-1.5 text-xs font-semibold text-zinc-200">
              <span>{loading ? '正在恢复' : '继续游玩'}</span>
              <ArrowRight className="h-3.5 w-3.5 shrink-0" />
            </div>
          </div>
          <SaveArchivePreview
            entry={entry}
            label={loading ? '恢复中' : '最近存档'}
            className="h-[7.4rem] w-[5.6rem] sm:h-[8rem] sm:w-[6.4rem]"
          />
        </div>
      </div>
    </button>
  );
}

function PlatformTabButton({
  active,
  label,
  icon: Icon,
  onClick,
  emphasized = false,
}: {
  active: boolean;
  label: string;
  icon: ComponentType<{ className?: string }>;
  onClick: () => void;
  emphasized?: boolean;
}) {
  return (
    <button
      type="button"
      onClick={onClick}
      className={`platform-bottom-nav__button ${emphasized ? 'platform-bottom-nav__button--primary' : ''} ${active ? 'platform-bottom-nav__button--active' : ''}`}
    >
      <span className="platform-bottom-nav__button-content">
        <span className="platform-bottom-nav__icon-shell">
          <Icon className="platform-bottom-nav__icon" />
        </span>
        <span className="platform-bottom-nav__label">{label}</span>
      </span>
    </button>
  );
}

function DesktopTabButton({
  active,
  label,
  icon: Icon,
  onClick,
  emphasized = false,
}: {
  active: boolean;
  label: string;
  icon: ComponentType<{ className?: string }>;
  onClick: () => void;
  emphasized?: boolean;
}) {
  return (
    <button
      type="button"
      onClick={onClick}
      className={`platform-desktop-rail__button ${emphasized ? 'platform-desktop-rail__button--primary' : ''} ${active ? 'platform-desktop-rail__button--active' : ''}`}
    >
      <span className="platform-desktop-rail__icon-shell">
        <Icon className="platform-desktop-rail__icon h-[1.1rem] w-[1.1rem]" />
      </span>
      <span className="platform-desktop-rail__label text-[11px] font-semibold tracking-[0.2em]">
        {label}
      </span>
    </button>
  );
}

function PlatformTabPanel({
  tab,
  activeTab,
  children,
}: {
  tab: PlatformHomeTab;
  activeTab: PlatformHomeTab;
  children: ReactNode;
}) {
  const active = activeTab === tab;

  // 主 Tab 保持挂载，只切换可见性，避免重页面卸载重建造成首帧闪烁。
  return (
    <section
      id={`platform-tab-panel-${tab}`}
      aria-hidden={!active}
      className={`platform-tab-panel ${active ? 'platform-tab-panel--active' : 'platform-tab-panel--hidden'}`}
    >
      {children}
    </section>
  );
}

function DesktopTrendingItem({
  entry,
  rank,
  onClick,
}: {
  entry: PlatformPublicGalleryCard;
  rank: number;
  onClick: () => void;
}) {
  const coverImage = resolvePlatformWorldCoverImage(entry);
  const tags = buildPlatformWorldTags(entry).filter(Boolean).slice(0, 2);

  return (
    <button
      type="button"
      onClick={onClick}
      className="platform-desktop-trending-item flex items-center gap-4 px-4 py-4 text-left"
    >
      <div className="relative h-[5.5rem] w-[4.3rem] shrink-0 overflow-hidden rounded-[1rem] border border-[var(--platform-subpanel-border)] bg-[rgba(255,255,255,0.66)]">
        {coverImage ? (
          <ResolvedAssetBackdrop
            src={coverImage}
            alt={entry.worldName}
            className="h-full w-full object-cover"
          />
        ) : null}
        <div className="absolute inset-0 bg-[linear-gradient(180deg,rgba(255,255,255,0.04),rgba(91,24,46,0.26))]" />
      </div>

      <div className="min-w-0 flex-1">
        <div className="flex items-center gap-2 text-[10px] tracking-[0.18em] text-[var(--platform-text-soft)]">
          <span>{`${rank}`.padStart(2, '0')}</span>
          <span className="truncate">
            {describePublicGalleryCardKind(entry)}
          </span>
        </div>
        <div className="mt-2 line-clamp-1 text-lg font-semibold text-[var(--platform-text-strong)]">
          {entry.worldName}
        </div>
        <div className="mt-1 line-clamp-2 text-sm leading-6 text-[color:color-mix(in_srgb,var(--platform-text-base)_86%,transparent)]">
          {entry.summaryText || entry.subtitle || '等待补充世界摘要。'}
        </div>
        <div className="mt-3 flex flex-wrap gap-2">
          {tags.length > 0 ? (
            tags.map((tag, index) => (
              <span
                key={`${entry.profileId}-trend-tag-${index}-${tag}`}
                className="platform-pill platform-pill--neutral px-2.5"
              >
                {tag}
              </span>
            ))
          ) : (
            <span className="platform-pill platform-pill--neutral px-2.5">
              {isBigFishGalleryEntry(entry)
                ? '大鱼'
                : isPuzzleGalleryEntry(entry)
                  ? '拼图'
                  : describePlatformThemeLabel(entry.themeMode)}
            </span>
          )}
        </div>
      </div>

      <ChevronRight className="h-4 w-4 shrink-0 text-[var(--platform-text-soft)]" />
    </button>
  );
}

function buildPublicCategoryGroups(
  featuredEntries: PlatformPublicGalleryCard[],
  latestEntries: PlatformPublicGalleryCard[],
) {
  const publicEntryMap = new Map<string, PlatformPublicGalleryCard>();

  [...featuredEntries, ...latestEntries].forEach((entry) => {
    publicEntryMap.set(buildPublicGalleryCardKey(entry), entry);
  });

  const categoryMap = new Map<string, PlatformPublicGalleryCard[]>();
  Array.from(publicEntryMap.values()).forEach((entry) => {
    const tags = buildPlatformWorldTags(entry)
      .map((tag) => tag.trim())
      .filter(Boolean);
    const normalizedTags = tags.length > 0 ? tags : ['回响'];

    normalizedTags.forEach((tag) => {
      const entries = categoryMap.get(tag) ?? [];
      entries.push(entry);
      categoryMap.set(tag, entries);
    });
  });

  return Array.from(categoryMap.entries())
    .map(([tag, entries]) => ({ tag, entries }))
    .sort((left, right) => {
      if (right.entries.length !== left.entries.length) {
        return right.entries.length - left.entries.length;
      }

      return left.tag.localeCompare(right.tag, 'zh-CN');
    });
}

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

function describePublicGalleryCardKind(entry: PlatformPublicGalleryCard) {
  return isBigFishGalleryEntry(entry)
    ? '大鱼'
    : isPuzzleGalleryEntry(entry)
      ? '拼图'
      : describePlatformThemeLabel(entry.themeMode);
}

function formatSnapshotTime(value: string | null | undefined) {
  if (!value) {
    return '刚刚保存';
  }

  const date = new Date(value);
  if (Number.isNaN(date.getTime())) {
    return value;
  }

  return date.toLocaleString('zh-CN', {
    month: '2-digit',
    day: '2-digit',
    hour: '2-digit',
    minute: '2-digit',
  });
}

function describeLoginMethod(loginMethod: AuthUser['loginMethod']) {
  switch (loginMethod) {
    case 'phone':
      return '手机号';
    case 'wechat':
      return '微信';
    default:
      return '账号密码';
  }
}

function describeBindingStatus(bindingStatus: AuthUser['bindingStatus']) {
  return bindingStatus === 'pending_bind_phone' ? '待绑定手机号' : '正常';
}

function formatCompactPlayTime(playTimeMs: number) {
  const totalMinutes = Math.max(0, Math.floor(playTimeMs / 60000));
  const days = totalMinutes / 1440;

  if (days >= 10) {
    return `${Math.floor(days)}天`;
  }
  if (days >= 1) {
    return `${days.toFixed(days >= 3 ? 0 : 1)}天`;
  }

  const hours = totalMinutes / 60;
  if (hours >= 1) {
    return `${hours.toFixed(hours >= 10 ? 0 : 1)}小时`;
  }

  return `${Math.max(0, totalMinutes)}分`;
}

function formatDashboardCount(value: number) {
  const normalizedValue = Math.max(0, Math.round(value));
  if (normalizedValue >= 100000000) {
    return `${(normalizedValue / 100000000).toFixed(1)}亿`;
  }
  if (normalizedValue >= 10000) {
    return `${(normalizedValue / 10000).toFixed(1)}万`;
  }

  return normalizedValue.toLocaleString('zh-CN');
}

function formatDashboardUpdatedAt(value: string | null | undefined) {
  if (!value) {
    return '暂无更新记录';
  }

  const date = new Date(value);
  if (Number.isNaN(date.getTime())) {
    return value;
  }

  return date.toLocaleString('zh-CN', {
    month: '2-digit',
    day: '2-digit',
    hour: '2-digit',
    minute: '2-digit',
  });
}

function buildPublicUserCode(user: AuthUser | null | undefined) {
  if (user?.publicUserCode?.trim()) {
    return user.publicUserCode.trim();
  }

  const raw =
    user?.id.replace(/[^a-zA-Z0-9]/gu, '').toUpperCase() ||
    user?.username.replace(/[^a-zA-Z0-9]/gu, '').toUpperCase() ||
    '00000000';

  return `SY-${raw.slice(-8).padStart(8, '0')}`;
}

function getUserAvatarLabel(user: AuthUser | null | undefined) {
  return (user?.displayName || user?.username || '叙')
    .slice(0, 1)
    .toUpperCase();
}

function copyText(value: string) {
  if (typeof navigator === 'undefined' || !navigator.clipboard?.writeText) {
    return;
  }

  void navigator.clipboard.writeText(value);
}

function ProfileStatCard({
  cardKey,
  label,
  value,
  onClick,
  icon,
}: {
  cardKey: ProfileDashboardCardKey;
  label: string;
  value: string;
  onClick?: ((cardKey: ProfileDashboardCardKey) => void) | null;
  icon: ComponentType<{ className?: string }>;
}) {
  const Icon = icon;

  return (
    <button
      type="button"
      onClick={onClick ? () => onClick(cardKey) : undefined}
      className="platform-subpanel rounded-[1.35rem] px-4 py-3 text-left transition hover:border-[var(--platform-surface-hover-border)] hover:bg-[var(--platform-button-secondary-fill)]"
    >
      <div className="flex items-center gap-2 text-[var(--platform-text-soft)]">
        <Icon className="h-4 w-4" />
        <span className="text-[11px] tracking-[0.16em]">{label}</span>
      </div>
      <div className="mt-3 text-lg font-black text-[var(--platform-text-strong)]">
        {value}
      </div>
    </button>
  );
}

function ProfileStatCardSkeleton() {
  return (
    <div className="platform-subpanel rounded-[1.35rem] px-4 py-3">
      <div className="h-4 w-20 animate-pulse rounded-full bg-[var(--platform-subpanel-border)]" />
      <div className="mt-3 h-7 w-16 animate-pulse rounded-full bg-[var(--platform-line-soft)]" />
    </div>
  );
}

function ProfileShortcutButton({
  label,
  icon,
  onClick,
}: {
  label: string;
  icon: ComponentType<{ className?: string }>;
  onClick?: (() => void) | null;
}) {
  const Icon = icon;

  return (
    <button
      type="button"
      onClick={onClick ?? undefined}
      className="platform-subpanel flex min-h-[5.25rem] flex-col items-center justify-center gap-2 rounded-[1.2rem] px-3 py-3 text-center transition hover:border-[var(--platform-surface-hover-border)] hover:bg-[var(--platform-button-secondary-fill)]"
    >
      <div className="platform-profile-chip flex h-10 w-10 items-center justify-center rounded-full">
        <Icon className="h-[1.125rem] w-[1.125rem]" />
      </div>
      <div className="text-sm font-semibold text-[var(--platform-text-strong)]">
        {label}
      </div>
    </button>
  );
}

function formatRechargePrice(priceCents: number) {
  const yuan = priceCents / 100;
  return Number.isInteger(yuan) ? `¥${yuan}` : `¥${yuan.toFixed(2)}`;
}

function formatMembershipDuration(days: number) {
  if (days >= 365) {
    return '365天';
  }

  return `${days}天`;
}

const WALLET_LEDGER_SOURCE_LABELS: Record<string, string> = {
  points_recharge: '叙世币充值',
  invite_inviter_reward: '邀请奖励',
  invite_invitee_reward: '填写邀请码奖励',
  snapshot_sync: '账户同步',
  asset_operation_consume: '资产操作消耗',
  asset_operation_refund: '资产操作退回',
};

function formatWalletLedgerAmount(amountDelta: number) {
  return amountDelta > 0 ? `+${amountDelta}` : `${amountDelta}`;
}

function WalletLedgerModal({
  ledger,
  fallbackBalance,
  isLoading,
  error,
  onClose,
  onRetry,
}: {
  ledger: ProfileWalletLedgerResponse | null;
  fallbackBalance: number;
  isLoading: boolean;
  error: string | null;
  onClose: () => void;
  onRetry: () => void;
}) {
  const entries = ledger?.entries ?? [];
  const balance = entries[0]?.balanceAfter ?? fallbackBalance;

  return (
    <div className="fixed inset-0 z-[80] flex items-center justify-center bg-black/48 px-3 py-5">
      <div className="relative max-h-[min(92vh,42rem)] w-full max-w-[30rem] overflow-hidden rounded-[1.35rem] bg-[linear-gradient(180deg,#fff7f8_0%,#ffffff_38%,#f8fafc_100%)] text-zinc-950 shadow-2xl">
        <button
          type="button"
          onClick={onClose}
          className="absolute right-3 top-3 z-10 flex h-8 w-8 items-center justify-center rounded-full bg-white/78 text-[#ff4056] shadow-sm"
          aria-label="关闭叙世币账单"
        >
          ×
        </button>
        <div className="max-h-[min(92vh,42rem)] overflow-y-auto px-4 pb-5 pt-4 sm:px-5">
          <div className="pr-10">
            <div className="text-[10px] font-black tracking-[0.22em] text-[#ff4056]">
              LEDGER
            </div>
            <div className="mt-1 text-2xl font-black">叙世币账单</div>
            <div className="mt-3 inline-flex items-center gap-2 rounded-full border border-rose-100 bg-white/70 px-3 py-1.5 text-xs font-bold text-zinc-600">
              <Coins className="h-3.5 w-3.5 text-[#ff4056]" />
              <span>{balance}叙世币</span>
            </div>
          </div>

          {error ? (
            <div className="mt-4 rounded-xl border border-rose-200 bg-rose-50 px-3 py-3 text-sm text-rose-700">
              <div>{error}</div>
              <button
                type="button"
                onClick={onRetry}
                className="mt-3 rounded-full bg-[#ff4056] px-4 py-2 text-xs font-black text-white"
              >
                重新加载
              </button>
            </div>
          ) : isLoading ? (
            <div className="mt-5 space-y-3">
              {Array.from({ length: 5 }).map((_, index) => (
                <div
                  key={index}
                  className="h-16 animate-pulse rounded-xl bg-zinc-100"
                />
              ))}
            </div>
          ) : entries.length === 0 ? (
            <div className="mt-5 rounded-xl border border-zinc-200 bg-white px-4 py-8 text-center text-sm font-semibold text-zinc-500">
              暂无账单记录
            </div>
          ) : (
            <div className="mt-5 space-y-2.5">
              {entries.map((entry) => {
                const isIncome = entry.amountDelta > 0;
                const label =
                  WALLET_LEDGER_SOURCE_LABELS[entry.sourceType] ??
                  entry.sourceType;

                return (
                  <div
                    key={entry.id}
                    className="flex items-center justify-between gap-3 rounded-xl border border-zinc-200 bg-white px-3 py-3 shadow-sm"
                  >
                    <div className="min-w-0">
                      <div className="truncate text-sm font-black text-zinc-900">
                        {label}
                      </div>
                      <div className="mt-1 text-xs font-semibold text-zinc-500">
                        {formatPlatformWorldTime(entry.createdAt)}
                      </div>
                    </div>
                    <div className="shrink-0 text-right">
                      <div
                        className={`text-base font-black ${
                          isIncome ? 'text-emerald-600' : 'text-rose-500'
                        }`}
                      >
                        {formatWalletLedgerAmount(entry.amountDelta)}
                      </div>
                      <div className="mt-1 text-[11px] font-semibold text-zinc-400">
                        余额 {entry.balanceAfter}
                      </div>
                    </div>
                  </div>
                );
              })}
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

function AccountRechargeModal({
  center,
  activeTab,
  isLoading,
  isSubmitting,
  error,
  onTabChange,
  onClose,
  onSelectProduct,
}: {
  center: ProfileRechargeCenterResponse | null;
  activeTab: 'points' | 'membership';
  isLoading: boolean;
  isSubmitting: string | null;
  error: string | null;
  onTabChange: (tab: 'points' | 'membership') => void;
  onClose: () => void;
  onSelectProduct: (product: ProfileRechargeProduct) => void;
}) {
  const visibleProducts =
    activeTab === 'points'
      ? (center?.pointProducts ?? [])
      : (center?.membershipProducts ?? []);

  return (
    <div className="fixed inset-0 z-[80] flex items-center justify-center bg-black/48 px-3 py-5">
      <div className="relative max-h-[min(92vh,46rem)] w-full max-w-[32rem] overflow-hidden rounded-[1.35rem] bg-[linear-gradient(180deg,#fff7f8_0%,#ffffff_34%,#f8fafc_100%)] text-zinc-950 shadow-2xl">
        <button
          type="button"
          onClick={onClose}
          className="absolute right-3 top-3 z-10 flex h-8 w-8 items-center justify-center rounded-full bg-white/78 text-[#ff4056] shadow-sm"
          aria-label="关闭账户充值"
        >
          ×
        </button>
        <div className="max-h-[min(92vh,46rem)] overflow-y-auto px-4 pb-5 pt-4 sm:px-5">
          <div className="pr-10">
            <div className="text-[10px] font-black tracking-[0.22em] text-[#ff4056]">
              WALLET
            </div>
            <div className="mt-1 text-2xl font-black">账户充值</div>
            <div className="mt-2 inline-flex items-center gap-2 rounded-full border border-rose-100 bg-white/70 px-3 py-1.5 text-xs font-bold text-zinc-600">
              <Coins className="h-3.5 w-3.5 text-[#ff4056]" />
              <span>
                {center ? `${center.walletBalance}叙世币` : '叙世币账户'}
              </span>
            </div>
          </div>

          <div className="mt-4 grid grid-cols-2 rounded-2xl bg-zinc-100/90 p-1">
            <button
              type="button"
              onClick={() => onTabChange('points')}
              className={`rounded-xl px-4 py-3 text-sm font-black transition ${
                activeTab === 'points'
                  ? 'bg-white text-[#ff4056] shadow-sm'
                  : 'text-zinc-500'
              }`}
            >
              叙世币充值
            </button>
            <button
              type="button"
              onClick={() => onTabChange('membership')}
              className={`rounded-xl px-4 py-3 text-sm font-black transition ${
                activeTab === 'membership'
                  ? 'bg-white text-[#ff4056] shadow-sm'
                  : 'text-zinc-500'
              }`}
            >
              会员卡充值
            </button>
          </div>

          {error ? (
            <div className="mt-4 rounded-xl border border-rose-200 bg-rose-50 px-3 py-2 text-sm text-rose-700">
              {error}
            </div>
          ) : null}

          {isLoading ? (
            <div className="mt-5 grid grid-cols-2 gap-3 sm:grid-cols-3">
              {Array.from({ length: activeTab === 'points' ? 6 : 3 }).map(
                (_, index) => (
                  <div
                    key={index}
                    className="h-24 animate-pulse rounded-xl bg-zinc-100"
                  />
                ),
              )}
            </div>
          ) : activeTab === 'points' ? (
            <div className="mt-5 grid grid-cols-2 gap-3 sm:grid-cols-3">
              {visibleProducts.map((product) => (
                <button
                  type="button"
                  key={product.productId}
                  disabled={Boolean(isSubmitting)}
                  onClick={() => onSelectProduct(product)}
                  className="relative min-h-[8.45rem] overflow-hidden rounded-2xl border border-zinc-200 bg-white text-center shadow-sm transition hover:border-[#ff4056] disabled:opacity-70"
                >
                  <div className="h-8 bg-[#ff4056] px-2 py-1.5 text-xs font-black text-white">
                    {product.badgeLabel}
                  </div>
                  <div className="px-2 py-3">
                    <div className="text-xl font-black">
                      {product.pointsAmount}叙世币
                    </div>
                    <div className="mt-1 text-xs text-zinc-500">
                      金额：{formatRechargePrice(product.priceCents)}
                    </div>
                    <div className="my-2 h-px bg-zinc-100" />
                    <div className="text-sm text-zinc-800">
                      {isSubmitting === product.productId
                        ? '处理中'
                        : product.description}
                    </div>
                  </div>
                </button>
              ))}
            </div>
          ) : (
            <>
              <div className="mt-5 grid gap-3 sm:grid-cols-3">
                {visibleProducts.map((product) => (
                  <button
                    type="button"
                    key={product.productId}
                    disabled={Boolean(isSubmitting)}
                    onClick={() => onSelectProduct(product)}
                    className="group relative min-h-[7.75rem] overflow-hidden rounded-2xl border border-zinc-200 bg-white px-4 py-4 text-left shadow-sm transition hover:border-[#ff4056] hover:shadow-md disabled:opacity-70"
                  >
                    <div className="absolute right-0 top-0 h-16 w-16 rounded-bl-[2rem] bg-[#ff4056]/10 transition group-hover:bg-[#ff4056]/16" />
                    <div className="relative">
                      <div className="flex items-start justify-between gap-3">
                        <div>
                          <div className="text-lg font-black">
                            {product.title}
                          </div>
                          <div className="mt-1 text-xs font-bold text-zinc-500">
                            {formatMembershipDuration(product.durationDays)}
                          </div>
                        </div>
                        <Crown className="h-5 w-5 shrink-0 text-[#ff4056]" />
                      </div>
                      <div className="mt-4 text-2xl font-black text-[#ff4056]">
                        {formatRechargePrice(product.priceCents)}
                      </div>
                      <div className="mt-2 text-xs font-semibold text-zinc-500">
                        {isSubmitting === product.productId
                          ? '处理中'
                          : product.description}
                      </div>
                    </div>
                  </button>
                ))}
              </div>
              <div className="mt-5 overflow-hidden rounded-2xl border border-zinc-200 bg-white shadow-sm">
                <div className="border-b border-zinc-200 px-4 py-3 text-sm font-black">
                  用户等级特权
                </div>
                <div className="overflow-x-auto">
                  <div className="grid min-w-[30rem] grid-cols-5 text-center text-sm">
                    {center?.benefits.map((benefit) => (
                      <div key={benefit.benefitName} className="contents">
                        <div className="border-b border-zinc-100 bg-zinc-50 px-2 py-3 text-left text-zinc-600">
                          {benefit.benefitName}
                        </div>
                        <div className="border-b border-zinc-100 px-2 py-3 text-zinc-500">
                          {benefit.normalValue}
                        </div>
                        <div className="border-b border-zinc-100 px-2 py-3 font-bold text-emerald-700">
                          {benefit.monthValue}
                        </div>
                        <div className="border-b border-zinc-100 px-2 py-3 font-bold text-rose-500">
                          {benefit.seasonValue}
                        </div>
                        <div className="border-b border-zinc-100 px-2 py-3 font-bold text-amber-600">
                          {benefit.yearValue}
                        </div>
                      </div>
                    ))}
                  </div>
                </div>
              </div>
            </>
          )}
        </div>
      </div>
    </div>
  );
}

function ProfileReferralModal({
  panel,
  center,
  inviteCodeInput,
  isLoading,
  isSubmitting,
  error,
  success,
  onClose,
  onInputChange,
  onCopyInvite,
  onSubmitRedeem,
}: {
  panel: ProfilePopupPanel;
  center: ProfileReferralInviteCenterResponse | null;
  inviteCodeInput: string;
  isLoading: boolean;
  isSubmitting: boolean;
  error: string | null;
  success: string | null;
  onClose: () => void;
  onInputChange: (value: string) => void;
  onCopyInvite: () => void;
  onSubmitRedeem: () => void;
}) {
  const title =
    panel === 'invite'
      ? '邀请好友'
      : panel === 'redeem'
        ? '填邀请码'
        : '玩家社区';

  return (
    <div className="fixed inset-0 z-[80] flex items-center justify-center bg-black/42 px-3 py-5">
      <div className="relative w-full max-w-[24rem] overflow-hidden rounded-[1.35rem] bg-white text-zinc-950 shadow-2xl">
        <button
          type="button"
          onClick={onClose}
          className="absolute right-3 top-2 z-10 flex h-8 w-8 items-center justify-center rounded-full text-[#ff4056]"
          aria-label={`关闭${title}`}
        >
          ×
        </button>
        <div className="px-5 pb-5 pt-4">
          <div className="text-center text-xl font-black">{title}</div>

          {panel === 'community' ? (
            <div className="mt-5 grid grid-cols-2 gap-3">
              {['微信群', 'QQ群'].map((label) => (
                <div
                  key={label}
                  className="rounded-xl border border-zinc-200 bg-zinc-50 p-3 text-center"
                >
                  <div className="aspect-square rounded-lg border border-dashed border-zinc-300 bg-white" />
                  <div className="mt-2 text-sm font-bold text-zinc-700">
                    {label}
                  </div>
                </div>
              ))}
            </div>
          ) : isLoading ? (
            <div className="mt-5 space-y-3">
              <div className="h-20 animate-pulse rounded-xl bg-zinc-100" />
              <div className="h-10 animate-pulse rounded-xl bg-zinc-100" />
            </div>
          ) : panel === 'invite' ? (
            <div className="mt-5 space-y-3">
              <div className="rounded-xl bg-zinc-50 px-4 py-4 text-center">
                <div className="text-[11px] font-bold text-zinc-500">
                  邀请码
                </div>
                <div className="mt-1 text-3xl font-black tracking-[0.16em] text-[#ff4056]">
                  {center?.inviteCode ?? '--------'}
                </div>
              </div>
              <button
                type="button"
                onClick={onCopyInvite}
                disabled={!center?.inviteCode}
                className="flex w-full items-center justify-center gap-2 rounded-xl bg-[#ff4056] px-4 py-3 text-sm font-black text-white disabled:opacity-60"
              >
                <Copy className="h-4 w-4" />
                复制邀请
              </button>
              <div className="grid grid-cols-3 gap-2 text-center text-xs text-zinc-500">
                <div className="rounded-lg bg-zinc-50 px-2 py-2">
                  <div className="font-black text-zinc-900">
                    {center?.invitedCount ?? 0}
                  </div>
                  邀请
                </div>
                <div className="rounded-lg bg-zinc-50 px-2 py-2">
                  <div className="font-black text-zinc-900">
                    {center?.rewardedInviteCount ?? 0}
                  </div>
                  已奖
                </div>
                <div className="rounded-lg bg-zinc-50 px-2 py-2">
                  <div className="font-black text-zinc-900">
                    {center?.todayInviterRewardRemaining ?? 0}
                  </div>
                  今日
                </div>
              </div>
            </div>
          ) : (
            <div className="mt-5 space-y-3">
              {center?.hasRedeemedCode ? (
                <div className="rounded-xl bg-emerald-50 px-4 py-4 text-center text-sm font-bold text-emerald-700">
                  已填写邀请码
                </div>
              ) : (
                <>
                  <input
                    value={inviteCodeInput}
                    onChange={(event) => onInputChange(event.target.value)}
                    placeholder="输入邀请码"
                    className="w-full rounded-xl border border-zinc-200 bg-zinc-50 px-4 py-3 text-center text-base font-black tracking-[0.14em] outline-none focus:border-[#ff4056]"
                  />
                  <button
                    type="button"
                    onClick={onSubmitRedeem}
                    disabled={isSubmitting || !inviteCodeInput.trim()}
                    className="w-full rounded-xl bg-[#ff4056] px-4 py-3 text-sm font-black text-white disabled:opacity-60"
                  >
                    {isSubmitting ? '提交中' : '确认填写'}
                  </button>
                </>
              )}
            </div>
          )}

          {error ? (
            <div className="mt-4 rounded-xl border border-rose-200 bg-rose-50 px-3 py-2 text-sm text-rose-700">
              {error}
            </div>
          ) : null}
          {success ? (
            <div className="mt-4 rounded-xl border border-emerald-200 bg-emerald-50 px-3 py-2 text-sm text-emerald-700">
              {success}
            </div>
          ) : null}
        </div>
      </div>
    </div>
  );
}

export function RpgEntryHomeView({
  activeTab,
  onTabChange,
  saveEntries,
  saveError,
  featuredEntries,
  latestEntries,
  myEntries,
  historyEntries,
  profileDashboard,
  isLoadingPlatform,
  isLoadingDashboard,
  isResumingSaveWorldKey,
  platformError,
  dashboardError,
  onResumeSave,
  onOpenCreateTypePicker,
  onOpenGalleryDetail,
  onOpenLibraryDetail,
  onDeleteLibraryEntry,
  deletingLibraryEntryId = null,
  onSearchPublicCode,
  isSearchingPublicCode = false,
  onOpenProfileDashboardCard,
  onRechargeSuccess,
  createTabContent,
}: RpgEntryHomeViewProps) {
  const authUi = useAuthUi();
  const [desktopSearchKeyword, setDesktopSearchKeyword] = useState('');
  const [mobileSearchKeyword, setMobileSearchKeyword] = useState('');
  const [isRechargeOpen, setIsRechargeOpen] = useState(false);
  const [rechargeTab, setRechargeTab] = useState<'points' | 'membership'>(
    'points',
  );
  const [rechargeCenter, setRechargeCenter] =
    useState<ProfileRechargeCenterResponse | null>(null);
  const [rechargeError, setRechargeError] = useState<string | null>(null);
  const [isLoadingRecharge, setIsLoadingRecharge] = useState(false);
  const [submittingRechargeProductId, setSubmittingRechargeProductId] =
    useState<string | null>(null);
  const [isWalletLedgerOpen, setIsWalletLedgerOpen] = useState(false);
  const [walletLedger, setWalletLedger] =
    useState<ProfileWalletLedgerResponse | null>(null);
  const [walletLedgerError, setWalletLedgerError] = useState<string | null>(
    null,
  );
  const [isLoadingWalletLedger, setIsLoadingWalletLedger] = useState(false);
  const [profilePopupPanel, setProfilePopupPanel] =
    useState<ProfilePopupPanel | null>(null);
  const [referralCenter, setReferralCenter] =
    useState<ProfileReferralInviteCenterResponse | null>(null);
  const [isLoadingReferral, setIsLoadingReferral] = useState(false);
  const [isSubmittingReferral, setIsSubmittingReferral] = useState(false);
  const [referralError, setReferralError] = useState<string | null>(null);
  const [referralSuccess, setReferralSuccess] = useState<string | null>(null);
  const [inviteCodeInput, setInviteCodeInput] = useState('');
  const [selectedCategoryTag, setSelectedCategoryTag] = useState<string | null>(
    null,
  );
  const [visitedTabs, setVisitedTabs] = useState<Set<PlatformHomeTab>>(
    () => new Set([activeTab]),
  );
  const isAuthenticated = Boolean(authUi?.user);
  const isDesktopLayout = usePlatformDesktopLayout();
  const featuredShelf = useMemo(
    () => featuredEntries.slice(0, 6),
    [featuredEntries],
  );
  const categoryGroups = useMemo(
    () => buildPublicCategoryGroups(featuredEntries, latestEntries),
    [featuredEntries, latestEntries],
  );
  const activeCategoryGroup =
    categoryGroups.find((group) => group.tag === selectedCategoryTag) ??
    categoryGroups[0] ??
    null;
  const visibleTabs = useMemo<PlatformHomeTab[]>(
    () =>
      isAuthenticated
        ? ['home', 'category', 'create', 'saves', 'profile']
        : ['home', 'create', 'category'],
    [isAuthenticated],
  );
  const publicUserCode = buildPublicUserCode(authUi?.user);
  const avatarLabel = getUserAvatarLabel(authUi?.user);
  const remainingNarrativeCoins = profileDashboard?.walletBalance ?? 0;
  const totalPlayTime = formatCompactPlayTime(
    profileDashboard?.totalPlayTimeMs ?? 0,
  );
  const playedWorkCount = profileDashboard?.playedWorldCount ?? 0;
  const tabIcons = {
    home: House,
    category: Tags,
    create: Sparkles,
    saves: Archive,
    profile: UserRound,
  } as const;
  const tabLabels = {
    home: '首页',
    category: '分类',
    create: '创作',
    saves: '存档',
    profile: '我的',
  } as const;

  useEffect(() => {
    if (!visibleTabs.includes(activeTab)) {
      onTabChange('home');
    }
  }, [activeTab, onTabChange, visibleTabs]);

  useEffect(() => {
    setVisitedTabs((currentTabs) => {
      if (currentTabs.has(activeTab)) {
        return currentTabs;
      }

      const nextTabs = new Set(currentTabs);
      nextTabs.add(activeTab);
      return nextTabs;
    });
  }, [activeTab]);

  useEffect(() => {
    if (categoryGroups.length === 0) {
      setSelectedCategoryTag(null);
      return;
    }

    const firstCategoryGroup = categoryGroups[0];
    if (
      firstCategoryGroup &&
      !categoryGroups.some((group) => group.tag === selectedCategoryTag)
    ) {
      setSelectedCategoryTag(firstCategoryGroup.tag);
    }
  }, [categoryGroups, selectedCategoryTag]);
  const openUserSurface = () => {
    if (authUi?.user) {
      authUi.openAccountModal();
      return;
    }
    authUi?.openLoginModal();
  };
  const openRechargePanel = () => {
    setIsRechargeOpen(true);
    setRechargeError(null);
    setIsLoadingRecharge(true);
    void getRpgProfileRechargeCenter()
      .then(setRechargeCenter)
      .catch((error: unknown) => {
        setRechargeCenter(null);
        setRechargeError(
          error instanceof Error ? error.message : '读取账户充值失败',
        );
      })
      .finally(() => setIsLoadingRecharge(false));
  };
  const loadWalletLedger = () => {
    setWalletLedgerError(null);
    setIsLoadingWalletLedger(true);
    void getRpgProfileWalletLedger()
      .then(setWalletLedger)
      .catch((error: unknown) => {
        setWalletLedger(null);
        setWalletLedgerError(
          error instanceof Error ? error.message : '读取叙世币账单失败',
        );
      })
      .finally(() => setIsLoadingWalletLedger(false));
  };
  const openWalletLedgerPanel = () => {
    setIsWalletLedgerOpen(true);
    loadWalletLedger();
  };
  const submitRechargeProduct = (product: ProfileRechargeProduct) => {
    if (submittingRechargeProductId) {
      return;
    }
    setSubmittingRechargeProductId(product.productId);
    setRechargeError(null);
    void createRpgProfileRechargeOrder(product.productId)
      .then((response) => {
        setRechargeCenter(response.center);
        void onRechargeSuccess?.();
      })
      .catch((error: unknown) => {
        setRechargeError(error instanceof Error ? error.message : '充值失败');
      })
      .finally(() => setSubmittingRechargeProductId(null));
  };
  const openProfilePopupPanel = (panel: ProfilePopupPanel) => {
    setProfilePopupPanel(panel);
    setReferralError(null);
    setReferralSuccess(null);
    if (panel === 'community') {
      return;
    }

    setIsLoadingReferral(true);
    void getRpgProfileReferralInviteCenter()
      .then(setReferralCenter)
      .catch((error: unknown) => {
        setReferralCenter(null);
        setReferralError(
          error instanceof Error ? error.message : '读取邀请码失败',
        );
      })
      .finally(() => setIsLoadingReferral(false));
  };
  const copyInviteInfo = () => {
    if (!referralCenter?.inviteCode) {
      return;
    }

    const inviteUrl =
      typeof window === 'undefined'
        ? referralCenter.inviteLinkPath
        : new URL(referralCenter.inviteLinkPath, window.location.origin).href;
    copyText(`${referralCenter.inviteCode} ${inviteUrl}`);
    setReferralSuccess('已复制');
  };
  const submitReferralInviteCode = () => {
    if (isSubmittingReferral || !inviteCodeInput.trim()) {
      return;
    }

    setIsSubmittingReferral(true);
    setReferralError(null);
    setReferralSuccess(null);
    void redeemRpgProfileReferralInviteCode(inviteCodeInput)
      .then((response: RedeemProfileReferralInviteCodeResponse) => {
        setReferralCenter(response.center);
        setInviteCodeInput('');
        setReferralSuccess(
          response.inviteeRewardGranted ? '已获得30叙世币' : '填写成功',
        );
        void onRechargeSuccess?.();
      })
      .catch((error: unknown) => {
        setReferralError(
          error instanceof Error ? error.message : '填写邀请码失败',
        );
      })
      .finally(() => setIsSubmittingReferral(false));
  };
  const submitDesktopSearch = () => {
    const keyword = desktopSearchKeyword.trim();
    if (!keyword || !onSearchPublicCode || isSearchingPublicCode) {
      return;
    }

    void onSearchPublicCode(keyword);
  };
  const submitMobileSearch = () => {
    const keyword = mobileSearchKeyword.trim();
    if (!keyword || !onSearchPublicCode || isSearchingPublicCode) {
      return;
    }

    void onSearchPublicCode(keyword);
  };
  const desktopHeroEntry =
    featuredShelf[0] ?? latestEntries[0] ?? myEntries[0] ?? null;
  const desktopHeroCover = desktopHeroEntry
    ? resolvePlatformWorldCoverImage(desktopHeroEntry)
    : null;
  const desktopHeroStripEntries = (
    featuredShelf.length > 0 ? featuredShelf : latestEntries
  ).slice(0, 5);
  const desktopTrendingEntries = latestEntries.slice(0, 3);
  const desktopFeaturedGrid = featuredShelf.slice(0, 4);
  const desktopReleaseGrid = latestEntries.slice(0, 6);
  const desktopLibraryPreview = myEntries.slice(0, 2);
  const categoryPageClass = isDesktopLayout
    ? DESKTOP_PAGE_STAGE_CLASS
    : MOBILE_PAGE_STAGE_CLASS;
  const leadPublicEntry = featuredShelf[0] ?? latestEntries[0] ?? null;
  const openLeadPublicEntry = () => {
    if (leadPublicEntry) {
      onOpenGalleryDetail(leadPublicEntry);
      return;
    }

    onTabChange('category');
  };

  const mobileHomeContent: ReactNode = (
    <div className={`${MOBILE_PAGE_STAGE_CLASS} platform-mobile-home-stage`}>
      <PublicCodeSearchBar
        value={mobileSearchKeyword}
        onChange={setMobileSearchKeyword}
        onSubmit={submitMobileSearch}
        isSearching={isSearchingPublicCode}
      />

      <button
        type="button"
        onClick={openLeadPublicEntry}
        className={`${HERO_SURFACE_CLASS} relative block w-full overflow-hidden px-4 py-4 text-left`}
      >
        <div className="absolute inset-0 bg-[var(--platform-hero-overlay-strong)]" />
        <div className="relative z-10 flex min-h-[10rem] flex-col justify-between">
          <div className="flex min-w-0 flex-wrap items-start justify-between gap-2">
            <span className="platform-pill platform-pill--warm shrink-0">
              作品
            </span>
            <div className="platform-mobile-hero-secondary platform-pill platform-pill--neutral max-w-full px-3 text-[11px] tracking-[0.08em]">
              {leadPublicEntry
                ? describePublicGalleryCardKind(leadPublicEntry)
                : '作品广场'}
            </div>
          </div>
          <div className="min-w-0">
            <div className="break-all text-[clamp(1.6rem,7.4vw,1.92rem)] font-black leading-tight text-white">
              {leadPublicEntry?.worldName ?? '浏览玩家作品'}
            </div>
            <div className="mt-2 max-w-[28rem] break-all text-sm leading-6 text-zinc-200/88">
              {leadPublicEntry?.summaryText ||
                leadPublicEntry?.subtitle ||
                '从公开广场进入作品详情，挑一个世界开始游玩。'}
            </div>
            <div className="mt-4 flex min-w-0 items-center gap-2 text-sm font-semibold text-white/90">
              <span className="min-w-0 break-all">查看作品</span>
              <ArrowRight className="h-4 w-4" />
            </div>
          </div>
        </div>
      </button>

      {platformError ? (
        <div className="rounded-2xl border border-rose-400/20 bg-rose-500/10 px-4 py-3 text-sm leading-6 text-rose-700">
          {platformError}
        </div>
      ) : null}

      <section>
        <SectionHeader title="精选推荐" detail="为你挑选" />
        {isLoadingPlatform ? (
          <EmptyShelf text="正在读取精选作品..." />
        ) : featuredShelf.length > 0 ? (
          <div className="flex min-w-0 gap-3 overflow-x-auto pb-1 scrollbar-hide">
            {featuredShelf.map((entry: PlatformPublicGalleryCard) => (
              <WorldCard
                key={`${buildPublicGalleryCardKey(entry)}:featured`}
                entry={entry}
                badge="推荐"
                metaLabel={describePublicGalleryCardKind(entry)}
                onClick={() => onOpenGalleryDetail(entry)}
              />
            ))}
          </div>
        ) : (
          <EmptyShelf text="公开广场暂时还没有精选作品。" />
        )}
      </section>

      <section>
        <SectionHeader title="最新发布" detail="玩家广场" />
        {isLoadingPlatform ? (
          <EmptyShelf text="正在读取最新发布..." />
        ) : latestEntries.length > 0 ? (
          <div className="flex min-w-0 gap-3 overflow-x-auto pb-1 scrollbar-hide">
            {latestEntries.map((entry: PlatformPublicGalleryCard) => (
              <WorldCard
                key={`${buildPublicGalleryCardKey(entry)}:latest`}
                entry={entry}
                badge={describePublicGalleryCardKind(entry)}
                metaLabel={entry.authorDisplayName}
                onClick={() => onOpenGalleryDetail(entry)}
              />
            ))}
          </div>
        ) : (
          <EmptyShelf text="公开广场暂时还没有新作品。" />
        )}
      </section>
    </div>
  );

  const categoryContent: ReactNode = (
    <div className={categoryPageClass}>
      <section className={`${PANEL_SURFACE_CLASS} px-4 py-3.5`}>
        <SectionHeader title="分类" detail="按标签浏览" />
        {isLoadingPlatform ? (
          <EmptyShelf text="正在读取公开作品..." />
        ) : categoryGroups.length > 0 && activeCategoryGroup ? (
          <>
            <div className="flex min-w-0 gap-2 overflow-x-auto pb-1 scrollbar-hide">
              {categoryGroups.map((group) => {
                const active = group.tag === activeCategoryGroup.tag;

                return (
                  <button
                    key={group.tag}
                    type="button"
                    onClick={() => setSelectedCategoryTag(group.tag)}
                    className={`platform-pill shrink-0 px-3 py-1.5 ${active ? 'platform-pill--warm' : 'platform-pill--neutral'}`}
                  >
                    {group.tag} · {group.entries.length}
                  </button>
                );
              })}
            </div>

            <div className="mt-4 grid grid-cols-2 gap-2.5 sm:gap-3 lg:grid-cols-3 xl:grid-cols-4">
              {activeCategoryGroup.entries.map((entry) => (
                <WorldCard
                  key={`${buildPublicGalleryCardKey(entry)}:category:${activeCategoryGroup.tag}`}
                  entry={entry}
                  badge={activeCategoryGroup.tag}
                  metaLabel={entry.authorDisplayName}
                  onClick={() => onOpenGalleryDetail(entry)}
                  className="h-[15rem] w-full min-w-0 sm:h-[16rem]"
                />
              ))}
            </div>
          </>
        ) : (
          <EmptyShelf text="公开广场暂时还没有可分类的作品。" />
        )}
      </section>
    </div>
  );

  const createContent: ReactNode = createTabContent ?? (
    <div className={MOBILE_PAGE_STAGE_CLASS}>
      <button
        type="button"
        onClick={onOpenCreateTypePicker}
        className={`${HERO_SURFACE_CLASS} relative block w-full overflow-hidden px-4 py-4 text-left`}
      >
        <div className="absolute inset-0 bg-[var(--platform-hero-overlay-strong)]" />
        <div className="relative z-10 flex min-h-[10rem] flex-col justify-between">
          <span className="platform-pill platform-pill--cool w-fit">
            CREATE
          </span>
          <div className="min-w-0">
            <div className="break-all text-[clamp(1.6rem,7.4vw,1.92rem)] font-black leading-tight text-white">
              开启新的创作
            </div>
            <div className="mt-2 max-w-[28rem] break-all text-sm leading-6 text-zinc-200/88">
              先选择游戏类型，再进入对应的创作工作台继续推进。
            </div>
            <div className="mt-4 flex items-center gap-2 text-sm font-semibold text-white/90">
              <span>选择类型并继续</span>
              <ArrowRight className="h-4 w-4" />
            </div>
          </div>
        </div>
      </button>

      <section>
        <SectionHeader title="我的创作" detail="草稿与已发布" />
        {isLoadingPlatform ? (
          <EmptyShelf text="正在读取你的作品..." />
        ) : myEntries.length > 0 ? (
          <div className="grid grid-cols-2 gap-2.5 sm:gap-3 xl:grid-cols-3">
            {myEntries.map(
              (entry: CustomWorldLibraryEntry<CustomWorldProfile>) => (
                <CreationLibraryCard
                  key={`${entry.ownerUserId}:${entry.profileId}:mine`}
                  entry={entry}
                  onClick={() => onOpenLibraryDetail(entry)}
                  onDelete={
                    onDeleteLibraryEntry
                      ? () => onDeleteLibraryEntry(entry)
                      : undefined
                  }
                  isDeleting={deletingLibraryEntryId === entry.profileId}
                />
              ),
            )}
          </div>
        ) : (
          <EmptyShelf
            text={
              isAuthenticated
                ? '你还没有保存任何自定义世界，先创建一个草稿开始吧。'
                : '登录后查看你的作品。'
            }
          />
        )}
      </section>
    </div>
  );

  const savesContent: ReactNode = (
    <div className={MOBILE_PAGE_STAGE_CLASS}>
      {authUi?.user ? (
        <>
          {saveError ? (
            <div className="rounded-2xl border border-rose-400/20 bg-rose-500/10 px-4 py-3 text-sm leading-6 text-rose-700">
              {saveError}
            </div>
          ) : null}

          <section className={`${PANEL_SURFACE_CLASS} px-4 py-3.5`}>
            <SectionHeader title="全部存档" detail="最近更新时间排序" />
            {isLoadingPlatform ? (
              <EmptyShelf text="正在读取存档..." />
            ) : saveEntries.length > 0 ? (
              <div className="grid gap-3 md:grid-cols-2">
                {saveEntries.map((entry) => (
                  <SaveArchiveCard
                    key={entry.worldKey}
                    entry={entry}
                    loading={isResumingSaveWorldKey === entry.worldKey}
                    onClick={() => onResumeSave(entry)}
                  />
                ))}
              </div>
            ) : (
              <EmptyShelf text="还没有可恢复的存档，去首页开始一段新的游玩吧。" />
            )}
          </section>
        </>
      ) : (
        <section className={`${PANEL_SURFACE_CLASS} px-4 py-3.5`}>
          <div className="platform-subpanel rounded-[1.35rem] px-4 py-4">
            <div className="text-base font-semibold text-[var(--platform-text-strong)]">
              尚未登录
            </div>
            <button
              type="button"
              onClick={() => authUi?.openLoginModal()}
              className="platform-button platform-button--primary mt-4"
            >
              登录
            </button>
          </div>
        </section>
      )}
    </div>
  );

  const profileContent: ReactNode = (
    <div className={MOBILE_PAGE_STAGE_CLASS}>
      {authUi?.user ? (
        <>
          <section className="platform-profile-hero rounded-[1.8rem] p-4">
            <div className="flex items-start justify-between gap-3">
              <div className="flex min-w-0 items-center gap-3">
                <button
                  type="button"
                  onClick={() => authUi.openAccountModal()}
                  className="platform-profile-avatar relative h-16 w-16 shrink-0 rounded-[1.4rem]"
                >
                  <span className="flex h-full w-full items-center justify-center text-2xl font-black">
                    {avatarLabel}
                  </span>
                  <span className="platform-profile-camera absolute -bottom-1 -right-1 flex h-6 w-6 items-center justify-center rounded-full">
                    <Camera className="h-3.5 w-3.5" />
                  </span>
                </button>

                <div className="min-w-0">
                  <div className="flex items-center gap-2">
                    <div className="truncate text-xl font-black text-[var(--platform-text-strong)]">
                      {authUi.user.displayName}
                    </div>
                    <button
                      type="button"
                      onClick={() => authUi.openAccountModal()}
                      className="platform-profile-icon-button flex h-7 w-7 items-center justify-center rounded-full"
                    >
                      <Pencil className="h-3.5 w-3.5" />
                    </button>
                  </div>
                  <div className="mt-1 flex flex-wrap items-center gap-2 text-xs text-[var(--platform-text-soft)]">
                    <span>叙世号 {publicUserCode}</span>
                    <button
                      type="button"
                      onClick={() => copyText(publicUserCode)}
                      className="platform-profile-chip flex items-center gap-1 rounded-full px-2 py-1"
                    >
                      <Copy className="h-3 w-3" />
                      复制
                    </button>
                  </div>
                  <div className="mt-2 flex flex-wrap items-center gap-2 text-xs">
                    <span className="platform-profile-chip rounded-full px-2.5 py-1">
                      {describeLoginMethod(authUi.user.loginMethod)}
                    </span>
                    <span className="platform-profile-chip rounded-full px-2.5 py-1">
                      {describeBindingStatus(authUi.user.bindingStatus)}
                    </span>
                  </div>
                </div>
              </div>

              <button
                type="button"
                onClick={openRechargePanel}
                className="platform-profile-action flex shrink-0 items-center gap-2 rounded-[1.1rem] px-3 py-2 text-left"
              >
                <Crown className="h-4 w-4" />
                <div>
                  <div className="text-xs font-bold">会员充值</div>
                  <div className="text-[10px] opacity-80">
                    {rechargeCenter?.membership.status === 'active'
                      ? '叙世会员'
                      : '普通用户'}
                  </div>
                </div>
                <ChevronRight className="h-4 w-4 opacity-80" />
              </button>
            </div>
          </section>

          <section className={`${PANEL_SURFACE_CLASS} px-4 py-3.5`}>
            <div className="grid grid-cols-3 gap-3">
              {isLoadingDashboard ? (
                <>
                  <ProfileStatCardSkeleton />
                  <ProfileStatCardSkeleton />
                  <ProfileStatCardSkeleton />
                </>
              ) : dashboardError ? (
                <>
                  <ProfileStatCard
                    cardKey="wallet"
                    label="剩余叙世币"
                    value="暂不可用"
                    icon={Coins}
                    onClick={openWalletLedgerPanel}
                  />
                  <ProfileStatCard
                    cardKey="playTime"
                    label="总游戏时长"
                    value="暂不可用"
                    icon={Clock3}
                    onClick={onOpenProfileDashboardCard}
                  />
                  <ProfileStatCard
                    cardKey="playedWorks"
                    label="玩过作品"
                    value="暂不可用"
                    icon={BookOpen}
                    onClick={onOpenProfileDashboardCard}
                  />
                </>
              ) : (
                <>
                  <ProfileStatCard
                    cardKey="wallet"
                    label="剩余叙世币"
                    value={formatDashboardCount(remainingNarrativeCoins)}
                    icon={Coins}
                    onClick={openWalletLedgerPanel}
                  />
                  <ProfileStatCard
                    cardKey="playTime"
                    label="总游戏时长"
                    value={totalPlayTime}
                    icon={Clock3}
                    onClick={onOpenProfileDashboardCard}
                  />
                  <ProfileStatCard
                    cardKey="playedWorks"
                    label="玩过作品"
                    value={formatDashboardCount(playedWorkCount)}
                    icon={BookOpen}
                    onClick={onOpenProfileDashboardCard}
                  />
                </>
              )}
            </div>
            <div className="mt-3 text-[11px] text-[var(--platform-text-soft)]">
              {dashboardError
                ? dashboardError
                : `更新于 ${formatDashboardUpdatedAt(profileDashboard?.updatedAt)}`}
            </div>
          </section>

          <section className={`${PANEL_SURFACE_CLASS} px-4 py-3.5`}>
            <SectionHeader title="常用功能" detail="快捷入口" />
            <div className="grid grid-cols-3 gap-3">
              <ProfileShortcutButton
                label="邀请好友"
                icon={UserPlus}
                onClick={() => openProfilePopupPanel('invite')}
              />
              <ProfileShortcutButton
                label="填邀请码"
                icon={Ticket}
                onClick={() => openProfilePopupPanel('redeem')}
              />
              <ProfileShortcutButton
                label="玩家社区"
                icon={MessageCircle}
                onClick={() => openProfilePopupPanel('community')}
              />
            </div>
          </section>

          <section className={`${PANEL_SURFACE_CLASS} px-4 py-3.5`}>
            <button
              type="button"
              onClick={() => authUi.openSettingsModal()}
              className="platform-subpanel platform-interactive-card flex w-full items-center justify-between gap-3 rounded-[1.25rem] px-4 py-4 text-left transition hover:border-[var(--platform-surface-hover-border)] hover:bg-[var(--platform-button-secondary-fill)]"
            >
              <div className="flex items-center gap-3">
                <div className="platform-profile-chip flex h-10 w-10 items-center justify-center rounded-full">
                  <Settings className="h-[1.125rem] w-[1.125rem]" />
                </div>
                <div>
                  <div className="text-base font-semibold text-[var(--platform-text-strong)]">
                    设置
                  </div>
                  <div className="text-xs text-[var(--platform-text-soft)]">
                    主题与账号
                  </div>
                </div>
              </div>
              <ChevronRight className="h-4 w-4 text-[var(--platform-text-soft)]" />
            </button>
          </section>
        </>
      ) : (
        <section className={`${PANEL_SURFACE_CLASS} px-4 py-3.5`}>
          <div className="platform-subpanel rounded-[1.35rem] px-4 py-4">
            <div className="text-base font-semibold text-[var(--platform-text-strong)]">
              尚未登录
            </div>
            <button
              type="button"
              onClick={() => authUi?.openLoginModal()}
              className="platform-button platform-button--primary mt-4"
            >
              登录
            </button>
          </div>
        </section>
      )}
    </div>
  );

  const desktopHomeContent: ReactNode = (
    <div className={DESKTOP_PAGE_STAGE_CLASS}>
      {platformError ? (
        <div className="rounded-[1.5rem] border border-rose-400/20 bg-rose-500/10 px-4 py-3 text-sm leading-6 text-rose-700">
          {platformError}
        </div>
      ) : null}

      <div className="grid gap-5 xl:grid-cols-[minmax(0,1.55fr)_22rem]">
        <button
          type="button"
          onClick={openLeadPublicEntry}
          className={`${HERO_SURFACE_CLASS} relative block overflow-hidden px-7 py-6 text-left`}
        >
          {desktopHeroCover ? (
            <ResolvedAssetBackdrop
              src={desktopHeroCover}
              alt=""
              aria-hidden="true"
              className="absolute inset-0 h-full w-full object-cover opacity-34"
            />
          ) : null}
          <div className="absolute inset-0 bg-[var(--platform-hero-overlay-strong)]" />
          <div className="relative z-10 flex min-h-[24rem] flex-col justify-between">
            <div className="flex items-start justify-between gap-4">
              <span className="platform-pill platform-pill--warm">作品</span>
              <span className="platform-pill platform-pill--neutral px-3">
                {leadPublicEntry
                  ? describePublicGalleryCardKind(leadPublicEntry)
                  : '作品广场'}
              </span>
            </div>

            <div className="max-w-[35rem]">
              <div className="text-5xl font-semibold leading-[1.08] text-white">
                {leadPublicEntry?.worldName ?? '浏览玩家作品'}
              </div>
              <div className="mt-4 text-base leading-8 text-zinc-200/86">
                {leadPublicEntry?.summaryText ||
                  leadPublicEntry?.subtitle ||
                  '从公开广场进入作品详情，挑一个世界开始游玩。'}
              </div>
              <div className="mt-5 inline-flex items-center gap-2 rounded-full border border-white/18 bg-white/18 px-4 py-2 text-sm font-semibold text-white/92">
                <span>查看作品</span>
                <ArrowRight className="h-4 w-4" />
              </div>
            </div>

            {desktopHeroStripEntries.length > 0 ? (
              <div className="grid gap-3 sm:grid-cols-5">
                {desktopHeroStripEntries.map((entry, index) => {
                  const coverImage = resolvePlatformWorldCoverImage(entry);
                  return (
                    <div
                      key={`${entry.ownerUserId}:${entry.profileId}:hero-strip`}
                      className="platform-subpanel overflow-hidden rounded-[1.15rem]"
                    >
                      <div className="relative aspect-[1.35/1] overflow-hidden">
                        {coverImage ? (
                          <ResolvedAssetBackdrop
                            src={coverImage}
                            alt=""
                            aria-hidden="true"
                            className="h-full w-full object-cover"
                          />
                        ) : null}
                        <div className="absolute inset-0 bg-[linear-gradient(180deg,rgba(255,255,255,0.04),rgba(91,24,46,0.34))]" />
                      </div>
                      <div className="flex items-center gap-2 px-3 py-2 text-[11px] text-[color:color-mix(in_srgb,var(--platform-text-base)_82%,transparent)]">
                        <span className="text-[var(--platform-text-soft)]">
                          {`${index + 1}`.padStart(2, '0')}
                        </span>
                        <span className="line-clamp-1">{entry.worldName}</span>
                      </div>
                    </div>
                  );
                })}
              </div>
            ) : null}
          </div>
        </button>

        <section className="platform-desktop-panel px-5 py-5">
          <div className="mb-4 flex items-start justify-between gap-3">
            <SectionHeader title="趋势关注" detail="TRENDING NOW" />
            <span className="platform-pill platform-pill--neutral px-3">
              LIVE
            </span>
          </div>
          {isLoadingPlatform ? (
            <EmptyShelf text="正在整理趋势作品..." />
          ) : desktopTrendingEntries.length > 0 ? (
            <div className="space-y-3">
              {desktopTrendingEntries.map((entry, index) => (
                <DesktopTrendingItem
                  key={`${buildPublicGalleryCardKey(entry)}:desktop-trend`}
                  entry={entry}
                  rank={index + 1}
                  onClick={() => onOpenGalleryDetail(entry)}
                />
              ))}
            </div>
          ) : (
            <EmptyShelf text="公开广场暂时还没有趋势作品。" />
          )}
        </section>
      </div>

      <div className="grid gap-5 2xl:grid-cols-[minmax(0,1.2fr)_minmax(22rem,0.8fr)]">
        <section className="platform-desktop-panel px-5 py-5">
          <SectionHeader title="精选推荐" detail="CURATED WORLDS" />
          {isLoadingPlatform ? (
            <EmptyShelf text="正在读取精选作品..." />
          ) : desktopFeaturedGrid.length > 0 ? (
            <div className="grid gap-4 xl:grid-cols-2">
              {desktopFeaturedGrid.map((entry) => (
                <WorldCard
                  key={`${buildPublicGalleryCardKey(entry)}:desktop-featured`}
                  entry={entry}
                  badge="推荐"
                  metaLabel={describePublicGalleryCardKind(entry)}
                  onClick={() => onOpenGalleryDetail(entry)}
                  className="h-[16rem] w-full min-w-0"
                />
              ))}
            </div>
          ) : (
            <EmptyShelf text="公开广场暂时还没有精选作品。" />
          )}
        </section>

        <section className="platform-desktop-panel px-5 py-5">
          <SectionHeader
            title={
              desktopLibraryPreview.length > 0
                ? '最近作品'
                : historyEntries.length > 0
                  ? '最近浏览'
                  : '作品广场'
            }
            detail="QUICK ACCESS"
          />

          <div>
            <div className="text-[10px] font-semibold tracking-[0.24em] text-[var(--platform-text-soft)]">
              {desktopLibraryPreview.length > 0
                ? '最近作品'
                : historyEntries.length > 0
                  ? '最近浏览'
                  : '公开作品'}
            </div>

            {desktopLibraryPreview.length > 0 ? (
              <div className="mt-3 space-y-3">
                {desktopLibraryPreview.map((entry) => (
                  <button
                    key={`${entry.ownerUserId}:${entry.profileId}:desktop-mine`}
                    type="button"
                    onClick={() => onOpenLibraryDetail(entry)}
                    className="platform-desktop-trending-item flex w-full items-center justify-between gap-3 px-4 py-4 text-left"
                  >
                    <div className="min-w-0">
                      <div className="line-clamp-1 text-base font-semibold text-[var(--platform-text-strong)]">
                        {entry.worldName}
                      </div>
                      <div className="mt-1 text-sm text-[var(--platform-text-soft)]">
                        {entry.visibility === 'published'
                          ? `发布于 ${formatPlatformWorldTime(entry.publishedAt)}`
                          : '草稿待完善'}
                      </div>
                    </div>
                    <span className="platform-pill platform-pill--neutral px-3">
                      {entry.visibility === 'published' ? '已发布' : '草稿'}
                    </span>
                  </button>
                ))}
              </div>
            ) : historyEntries.length > 0 ? (
              <div className="mt-3 space-y-3">
                {historyEntries.slice(0, 2).map((entry) => (
                  <button
                    key={`${entry.ownerUserId}:${entry.profileId}:desktop-history`}
                    type="button"
                    onClick={() =>
                      onOpenGalleryDetail({
                        ownerUserId: entry.ownerUserId,
                        profileId: entry.profileId,
                        publicWorkCode: null,
                        authorPublicUserCode: null,
                        visibility: 'published',
                        publishedAt: entry.visitedAt,
                        updatedAt: entry.visitedAt,
                        worldName: entry.worldName,
                        subtitle: entry.subtitle,
                        summaryText: entry.summaryText,
                        coverImageSrc: entry.coverImageSrc,
                        themeMode: entry.themeMode,
                        authorDisplayName: entry.authorDisplayName,
                        playableNpcCount: 0,
                        landmarkCount: 0,
                      })
                    }
                    className="platform-desktop-trending-item flex w-full items-center justify-between gap-3 px-4 py-4 text-left"
                  >
                    <div className="min-w-0">
                      <div className="line-clamp-1 text-base font-semibold text-[var(--platform-text-strong)]">
                        {entry.worldName}
                      </div>
                      <div className="mt-1 text-sm text-[var(--platform-text-soft)]">
                        作者：{entry.authorDisplayName}
                      </div>
                    </div>
                    <span className="platform-pill platform-pill--neutral px-3">
                      浏览
                    </span>
                  </button>
                ))}
              </div>
            ) : (
              <div className="platform-subpanel mt-3 rounded-[1.35rem] px-4 py-4 text-sm leading-6 text-[var(--platform-text-base)]">
                公开广场暂时还没有可展示的作品。
              </div>
            )}
          </div>
        </section>
      </div>

      <section className="platform-desktop-panel px-5 py-5">
        <SectionHeader title="最新发布" detail="PLAYER SQUARE" />
        {isLoadingPlatform ? (
          <EmptyShelf text="正在读取最新发布..." />
        ) : desktopReleaseGrid.length > 0 ? (
          <div className="grid gap-4 xl:grid-cols-3">
            {desktopReleaseGrid.map((entry) => (
              <WorldCard
                key={`${buildPublicGalleryCardKey(entry)}:desktop-latest`}
                entry={entry}
                badge={describePublicGalleryCardKind(entry)}
                metaLabel={entry.authorDisplayName}
                onClick={() => onOpenGalleryDetail(entry)}
                className="h-[17rem] w-full min-w-0"
              />
            ))}
          </div>
        ) : (
          <EmptyShelf text="公开广场暂时还没有新作品。" />
        )}
      </section>
    </div>
  );

  const tabContentById = {
    home: isDesktopLayout ? desktopHomeContent : mobileHomeContent,
    category: categoryContent,
    create: createContent,
    saves: savesContent,
    profile: profileContent,
  } satisfies Record<PlatformHomeTab, ReactNode>;
  const tabPanels = PLATFORM_HOME_TABS.filter((tab) =>
    visibleTabs.includes(tab),
  ).map((tab) => {
    const shouldMountPanel = tab === activeTab || visitedTabs.has(tab);

    return (
      <PlatformTabPanel key={tab} tab={tab} activeTab={activeTab}>
        {shouldMountPanel ? tabContentById[tab] : null}
      </PlatformTabPanel>
    );
  });

  if (!isDesktopLayout) {
    return (
      <div className="platform-mobile-entry-shell flex h-full min-h-0 min-w-0 flex-col overflow-hidden">
        <div className="mb-3 flex shrink-0 items-center justify-between gap-3 px-0.5">
          <RpgEntryBrandLogo />
          {!isAuthenticated ? (
            <button
              type="button"
              onClick={openUserSurface}
              className="platform-button platform-button--primary shrink-0 px-3 py-2 text-xs"
            >
              <LogIn className="h-3.5 w-3.5" />
              登录
            </button>
          ) : null}
        </div>

        <div className="platform-tab-panel-stack min-w-0 flex-1">
          {tabPanels}
        </div>

        <div
          className="mt-3 min-w-0 shrink-0 border-t pt-2"
          style={{
            borderColor: 'var(--platform-line-soft)',
            paddingBottom: 'calc(env(safe-area-inset-bottom) + 0.2rem)',
          }}
        >
          <div
            className={`platform-bottom-nav grid ${visibleTabs.length === 5 ? 'grid-cols-5' : visibleTabs.length === 4 ? 'grid-cols-4' : visibleTabs.length === 3 ? 'grid-cols-3' : 'grid-cols-2'}`}
          >
            {visibleTabs.map((tab) => (
              <PlatformTabButton
                key={tab}
                active={activeTab === tab}
                label={tabLabels[tab]}
                icon={tabIcons[tab]}
                emphasized={tab === 'create'}
                onClick={() => onTabChange(tab)}
              />
            ))}
          </div>
        </div>
        {isRechargeOpen ? (
          <AccountRechargeModal
            center={rechargeCenter}
            activeTab={rechargeTab}
            isLoading={isLoadingRecharge}
            isSubmitting={submittingRechargeProductId}
            error={rechargeError}
            onTabChange={setRechargeTab}
            onClose={() => setIsRechargeOpen(false)}
            onSelectProduct={submitRechargeProduct}
          />
        ) : null}
        {profilePopupPanel ? (
          <ProfileReferralModal
            panel={profilePopupPanel}
            center={referralCenter}
            inviteCodeInput={inviteCodeInput}
            isLoading={isLoadingReferral}
            isSubmitting={isSubmittingReferral}
            error={referralError}
            success={referralSuccess}
            onClose={() => setProfilePopupPanel(null)}
            onInputChange={setInviteCodeInput}
            onCopyInvite={copyInviteInfo}
            onSubmitRedeem={submitReferralInviteCode}
          />
        ) : null}
        {isWalletLedgerOpen ? (
          <WalletLedgerModal
            ledger={walletLedger}
            fallbackBalance={remainingNarrativeCoins}
            isLoading={isLoadingWalletLedger}
            error={walletLedgerError}
            onClose={() => setIsWalletLedgerOpen(false)}
            onRetry={loadWalletLedger}
          />
        ) : null}
      </div>
    );
  }

  return (
    <div className="flex h-full min-h-0 flex-col">
      <div className="flex h-full min-h-0 flex-col">
        <div className="platform-desktop-shell flex h-full min-h-0 flex-col p-5 xl:p-6">
          <div className="platform-desktop-topbar flex items-center gap-4 px-5 py-4">
            <div className="flex min-w-0 flex-1 items-center gap-5">
              <RpgEntryBrandLogo className="shrink-0" decorative />
              <PublicCodeSearchBar
                value={desktopSearchKeyword}
                onChange={setDesktopSearchKeyword}
                onSubmit={submitDesktopSearch}
                isSearching={
                  !onSearchPublicCode || Boolean(isSearchingPublicCode)
                }
                className="max-w-[34rem] flex-1"
              />
            </div>

            <div className="flex items-center gap-3">
              <button
                type="button"
                onClick={openUserSurface}
                className="platform-icon-button"
                aria-label="通知与账户"
              >
                <Bell className="h-4 w-4" />
              </button>
              <button
                type="button"
                onClick={openUserSurface}
                className="platform-desktop-search flex items-center gap-3 px-3 py-2.5 text-left"
              >
                <span
                  className="flex h-11 w-11 items-center justify-center rounded-full text-base font-black text-white"
                  style={{
                    background: 'var(--platform-profile-avatar-fill)',
                    boxShadow: 'var(--platform-profile-avatar-shadow)',
                  }}
                >
                  {avatarLabel}
                </span>
                <span className="min-w-0">
                  <span className="block truncate text-sm font-semibold text-[var(--platform-text-strong)]">
                    {authUi?.user?.displayName || '登录'}
                  </span>
                  <span className="block truncate text-xs text-[var(--platform-text-soft)]">
                    {authUi?.user ? publicUserCode : '账号入口'}
                  </span>
                </span>
              </button>
            </div>
          </div>

          <div className="mt-5 flex min-h-0 gap-5">
            <aside className="platform-desktop-rail flex w-[5.8rem] shrink-0 flex-col gap-3 p-3">
              {visibleTabs.map((tab) => (
                <DesktopTabButton
                  key={tab}
                  active={activeTab === tab}
                  label={tabLabels[tab]}
                  icon={tabIcons[tab]}
                  emphasized={tab === 'create'}
                  onClick={() => onTabChange(tab)}
                />
              ))}
            </aside>

            <div className="platform-tab-panel-stack min-w-0 flex-1">
              {tabPanels}
            </div>
          </div>
        </div>
      </div>
      {isRechargeOpen ? (
        <AccountRechargeModal
          center={rechargeCenter}
          activeTab={rechargeTab}
          isLoading={isLoadingRecharge}
          isSubmitting={submittingRechargeProductId}
          error={rechargeError}
          onTabChange={setRechargeTab}
          onClose={() => setIsRechargeOpen(false)}
          onSelectProduct={submitRechargeProduct}
        />
      ) : null}
      {profilePopupPanel ? (
        <ProfileReferralModal
          panel={profilePopupPanel}
          center={referralCenter}
          inviteCodeInput={inviteCodeInput}
          isLoading={isLoadingReferral}
          isSubmitting={isSubmittingReferral}
          error={referralError}
          success={referralSuccess}
          onClose={() => setProfilePopupPanel(null)}
          onInputChange={setInviteCodeInput}
          onCopyInvite={copyInviteInfo}
          onSubmitRedeem={submitReferralInviteCode}
        />
      ) : null}
      {isWalletLedgerOpen ? (
        <WalletLedgerModal
          ledger={walletLedger}
          fallbackBalance={remainingNarrativeCoins}
          isLoading={isLoadingWalletLedger}
          error={walletLedgerError}
          onClose={() => setIsWalletLedgerOpen(false)}
          onRetry={loadWalletLedger}
        />
      ) : null}
    </div>
  );
}

export const PlatformHomeView = RpgEntryHomeView;
