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

import { getCharacterById } from '../data/characterPresets';
import {
  formatCurrency,
  getInventoryItemValue,
} from '../data/economy';
import {
  getEquipmentSlotFromItem,
  getEquipmentSlotLabel,
} from '../data/equipmentEffects';
import { isInventoryItemUsable, resolveInventoryItemUseEffect } from '../data/inventoryEffects';
import {
  buildInventoryItemDescription,
  getInventoryTagLabels,
} from '../data/itemPresentation';
import {
  getRarityLabel,
} from '../data/npcInteractions';
import { StoryGenerationNpcUi } from '../hooks/rpg-runtime-story';
import {
  GameState,
  InventoryItem,
  RuntimeNpcGiftItemView,
  RuntimeNpcTradeItemView,
} from '../types';
import { getInventoryItemVisualSrc, getNineSliceStyle, UI_CHROME } from '../uiAssets';
import { PixelCloseButton } from './PixelCloseButton';
import { PixelIcon } from './PixelIcon';

interface NpcModalsProps {
  gameState: GameState;
  npcUi: StoryGenerationNpcUi;
}

type TradeDetailState = {
  itemId: string;
  source: 'buy' | 'sell';
} | null;

function getItemVisualSrc(item: InventoryItem) {
  return getInventoryItemVisualSrc(item);
}

function buildTradeUseEffectText(
  effect: ReturnType<typeof resolveInventoryItemUseEffect> | null,
) {
  if (!effect) return null;

  const parts = [
    effect.hpRestore > 0 ? `生命 +${effect.hpRestore}` : null,
    effect.manaRestore > 0 ? `灵力 +${effect.manaRestore}` : null,
    effect.cooldownReduction > 0 ? `冷却 -${effect.cooldownReduction}` : null,
  ].filter((part): part is string => Boolean(part));

  return parts.join(' / ') || '无直接效果';
}

function TradeItemRow({
  item,
  selected,
  unitPrice,
  currencyName,
  onClick,
}: {
  item: InventoryItem;
  selected: boolean;
  unitPrice: number;
  currencyName: string;
  onClick: () => void;
}) {
  return (
    <button
      type="button"
      onClick={onClick}
      className={`w-full rounded-xl border px-3 py-2.5 text-left transition ${
        selected
          ? 'border-emerald-400/45 bg-emerald-500/10'
          : 'border-white/8 bg-black/20 hover:border-white/15'
      }`}
    >
      <div className="flex items-center gap-3">
        <div className="flex h-11 w-11 shrink-0 items-center justify-center rounded-lg border border-white/10 bg-black/35">
          <PixelIcon src={getItemVisualSrc(item)} className="h-7 w-7" />
        </div>
        <div className="min-w-0 flex-1">
          <div className="truncate text-sm font-medium text-white">{item.name ?? item.id}</div>
          <div className="mt-1 text-[10px] text-zinc-500">
            {item.category} / {getRarityLabel(item.rarity)} / 单价 {unitPrice} {currencyName}
          </div>
        </div>
        <div className="rounded-full border border-white/10 bg-black/25 px-2 py-0.5 text-[10px] text-white">
          x{item.quantity}
        </div>
      </div>
    </button>
  );
}

function TradeQuantityStepper({
  quantity,
  maxQuantity,
  onChange,
}: {
  quantity: number;
  maxQuantity: number;
  onChange: (quantity: number) => void;
}) {
  const safeMax = Math.max(1, maxQuantity);
  return (
    <div className="flex items-center justify-between rounded-xl border border-white/8 bg-black/20 px-3 py-2">
      <div>
        <div className="text-[10px] uppercase tracking-[0.18em] text-zinc-500">数量</div>
        <div className="mt-1 text-xs text-zinc-400">最多 {safeMax}</div>
      </div>
      <div className="flex items-center gap-2">
        <button
          type="button"
          onClick={() => onChange(quantity - 1)}
          disabled={quantity <= 1}
          className={`h-8 w-8 rounded-lg border text-sm ${
            quantity > 1
              ? 'border-white/12 bg-white/6 text-white'
              : 'border-white/8 bg-black/20 text-zinc-600'
          }`}
        >
          -
        </button>
        <div className="min-w-[3rem] text-center text-sm font-semibold text-white">{quantity}</div>
        <button
          type="button"
          onClick={() => onChange(quantity + 1)}
          disabled={quantity >= safeMax}
          className={`h-8 w-8 rounded-lg border text-sm ${
            quantity < safeMax
              ? 'border-white/12 bg-white/6 text-white'
              : 'border-white/8 bg-black/20 text-zinc-600'
          }`}
        >
          +
        </button>
      </div>
    </div>
  );
}

export function NpcModals({ gameState, npcUi }: NpcModalsProps) {
  const [tradeDetail, setTradeDetail] = useState<TradeDetailState>(null);
  const npcInteraction = gameState.runtimeNpcInteraction ?? null;
  const currencyName = npcInteraction?.currencyName ?? '钱币';
  const tradeModal = npcUi.tradeModal;
  const tradeMode = tradeModal?.mode ?? 'buy';
  const tradeItemViews: RuntimeNpcTradeItemView[] = tradeMode === 'buy'
    ? npcInteraction?.trade.buyItems ?? []
    : npcInteraction?.trade.sellItems ?? [];
  const activeTradeView = tradeModal
    ? tradeItemViews.find(view =>
      view.itemId === (tradeMode === 'buy'
        ? tradeModal.selectedNpcItemId
        : tradeModal.selectedPlayerItemId),
    ) ?? null
    : null;
  const activeTradeItem = activeTradeView?.item ?? null;
  const activeTradeUnitPrice = activeTradeView?.unitPrice ?? 0;
  const activeTradeMaxQuantity = activeTradeView?.maxQuantity ?? 0;
  const activeTradeQuantity = tradeModal
    ? Math.max(1, Math.min(tradeModal.selectedQuantity, Math.max(1, activeTradeMaxQuantity)))
    : 1;
  const activeTradeTotalPrice = activeTradeUnitPrice * activeTradeQuantity;
  const canConfirmTrade = Boolean(
    activeTradeView &&
    activeTradeView.canSubmit &&
    activeTradeQuantity >= 1,
  );
  const tradeItemList = tradeItemViews;
  const tradeDetailItem = tradeDetail
    ? (tradeDetail.source === 'buy'
      ? npcInteraction?.trade.buyItems ?? []
      : npcInteraction?.trade.sellItems ?? [])
      .find(view => view.itemId === tradeDetail.itemId)?.item ?? null
    : null;
  const tradeDetailView = tradeDetail
    ? (tradeDetail.source === 'buy'
      ? npcInteraction?.trade.buyItems ?? []
      : npcInteraction?.trade.sellItems ?? [])
      .find(view => view.itemId === tradeDetail.itemId) ?? null
    : null;
  const tradeDetailUseEffect = tradeDetailItem && gameState.playerCharacter
    ? resolveInventoryItemUseEffect(tradeDetailItem, gameState.playerCharacter)
    : null;
  const tradeDetailEquipSlot = tradeDetailItem ? getEquipmentSlotFromItem(tradeDetailItem) : null;
  const tradeDetailEffectText = buildTradeUseEffectText(tradeDetailUseEffect);
  const giftCandidates: RuntimeNpcGiftItemView[] = npcUi.giftModal
    ? npcInteraction?.gift.items ?? []
    : [];
  const activeGiftView =
    giftCandidates.find(item => item.itemId === npcUi.giftModal?.selectedItemId) ?? null;

  const handleTradeItemClick = (view: RuntimeNpcTradeItemView) => {
    if (tradeMode === 'buy') {
      npcUi.selectTradeNpcItem(view.itemId);
      setTradeDetail({ itemId: view.itemId, source: 'buy' });
      return;
    }

    npcUi.selectTradePlayerItem(view.itemId);
    setTradeDetail({ itemId: view.itemId, source: 'sell' });
  };

  return (
    <AnimatePresence>
      {tradeModal && (
        <motion.div
          initial={{ opacity: 0 }}
          animate={{ opacity: 1 }}
          exit={{ opacity: 0 }}
          className="fixed inset-0 z-[75] flex items-center justify-center bg-black/70 p-3 backdrop-blur-sm sm:p-4"
          onClick={npcUi.closeTradeModal}
        >
          <motion.div
            initial={{ opacity: 0, scale: 0.96, y: 8 }}
            animate={{ opacity: 1, scale: 1, y: 0 }}
            exit={{ opacity: 0, scale: 0.96, y: 8 }}
            className="pixel-nine-slice pixel-modal-shell flex max-h-[min(92vh,48rem)] w-full max-w-4xl flex-col overflow-hidden shadow-[0_24px_80px_rgba(0,0,0,0.55)]"
            style={getNineSliceStyle(UI_CHROME.modalPanel)}
            onClick={event => event.stopPropagation()}
          >
            <div className="flex items-center justify-between border-b border-white/10 px-4 py-3 sm:px-5 sm:py-4">
              <div className="min-w-0">
                <div className="text-sm font-semibold text-white">交易</div>
                <div className="mt-1 text-xs text-zinc-500">
                  {npcInteraction?.npcName ?? tradeModal.encounter.npcName} / 你当前{currencyName}：{npcInteraction?.playerCurrency ?? gameState.playerCurrency}
                </div>
              </div>
              <PixelCloseButton
                onClick={npcUi.closeTradeModal}
                label="关闭交易"
                placement="inline"
              />
            </div>

            <div className="flex-1 overflow-y-auto px-4 py-3 sm:px-5 sm:py-4">
              {tradeModal.introText && (
                <div className="mb-3 whitespace-pre-line rounded-xl border border-amber-300/15 bg-amber-500/10 px-3 py-2 text-xs leading-relaxed text-amber-50/90">
                  {tradeModal.introText}
                </div>
              )}
              <div className="grid gap-3 lg:grid-cols-[minmax(0,1.2fr)_minmax(18rem,0.8fr)]">
                <div className="min-h-0 space-y-3">
                  <div className="grid grid-cols-2 gap-2">
                    <button
                      type="button"
                      onClick={() => npcUi.setTradeMode('buy')}
                      className={`rounded-xl border px-3 py-2 text-sm transition ${
                        tradeMode === 'buy'
                          ? 'border-emerald-400/45 bg-emerald-500/10 text-emerald-100'
                          : 'border-white/10 bg-black/20 text-zinc-300'
                      }`}
                    >
                      购买物品
                    </button>
                    <button
                      type="button"
                      onClick={() => npcUi.setTradeMode('sell')}
                      className={`rounded-xl border px-3 py-2 text-sm transition ${
                        tradeMode === 'sell'
                          ? 'border-sky-400/45 bg-sky-500/10 text-sky-100'
                          : 'border-white/10 bg-black/20 text-zinc-300'
                      }`}
                    >
                      出售物品
                    </button>
                  </div>

                  <div className="flex items-center justify-between rounded-xl border border-white/8 bg-black/20 px-3 py-2 text-xs text-zinc-400">
                    <span>{tradeMode === 'buy' ? '对方库存' : '你的背包'}</span>
                    <span>{tradeItemList.length} 件</span>
                  </div>

                  <div className="max-h-[42vh] space-y-2 overflow-y-auto pr-1 scrollbar-hide">
                    {tradeItemList.length > 0 ? tradeItemList.map(view => (
                      <div key={view.itemId}>
                        <TradeItemRow
                          item={view.item}
                          selected={tradeMode === 'buy'
                            ? tradeModal.selectedNpcItemId === view.itemId
                            : tradeModal.selectedPlayerItemId === view.itemId}
                          unitPrice={view.unitPrice}
                          currencyName={currencyName}
                          onClick={() => handleTradeItemClick(view)}
                        />
                        {!view.canSubmit && view.reason && (
                          <div className="mt-1 px-1 text-[10px] text-rose-300">
                            {view.reason}
                          </div>
                        )}
                      </div>
                    )) : (
                      <div className="rounded-xl border border-dashed border-white/10 bg-black/20 px-4 py-6 text-sm text-zinc-500">
                        {tradeMode === 'buy' ? '对方暂时没有可出售的物品。' : '你当前没有可出售的物品。'}
                      </div>
                    )}
                  </div>
                </div>

                <div className="space-y-3">
                  <div className="rounded-xl border border-white/8 bg-black/20 p-3">
                    {activeTradeItem ? (
                      <div className="space-y-3">
                        <TradeQuantityStepper
                          quantity={activeTradeQuantity}
                          maxQuantity={activeTradeMaxQuantity}
                          onChange={npcUi.setTradeQuantity}
                        />

                        <div className="rounded-xl border border-white/8 bg-black/20 px-3 py-3 text-sm text-zinc-200">
                          <div className="flex items-center justify-between gap-3">
                            <span>{tradeMode === 'buy' ? '购买总价' : '出售总价'}</span>
                            <span className="font-semibold text-white">
                              {formatCurrency(activeTradeTotalPrice, gameState.worldType)}
                            </span>
                          </div>
                          {!activeTradeView?.canSubmit && activeTradeView?.reason && (
                            <div className="mt-2 text-xs text-rose-300">
                              {activeTradeView.reason}
                            </div>
                          )}
                        </div>
                      </div>
                    ) : (
                      <div className="px-2 py-8 text-center text-sm text-zinc-500">
                        请选择一件物品，右侧会显示数量、价格与详情。
                      </div>
                    )}
                  </div>
                </div>
              </div>
            </div>

            <div className="flex items-center justify-end gap-3 border-t border-white/10 px-4 py-3 sm:px-5 sm:py-4">
              <button
                type="button"
                onClick={npcUi.closeTradeModal}
                className="pixel-nine-slice pixel-pressable px-4 py-2 text-xs text-zinc-200"
                style={getNineSliceStyle(UI_CHROME.choiceButton, { paddingX: 14, paddingY: 8 })}
              >
                取消
              </button>
              <button
                type="button"
                disabled={!canConfirmTrade}
                onClick={npcUi.confirmTrade}
                className={`pixel-nine-slice pixel-pressable px-4 py-2 text-xs ${canConfirmTrade ? 'text-white' : 'text-zinc-600'}`}
                style={getNineSliceStyle(UI_CHROME.choiceButton, { paddingX: 14, paddingY: 8 })}
              >
                {tradeMode === 'buy' ? '确认购买' : '确认出售'}
              </button>
            </div>
          </motion.div>
        </motion.div>
      )}

      {tradeModal && tradeDetail && tradeDetailItem && (
        <motion.div
          initial={{ opacity: 0 }}
          animate={{ opacity: 1 }}
          exit={{ opacity: 0 }}
          className="fixed inset-0 z-[76] flex items-center justify-center bg-black/78 p-4 backdrop-blur-sm"
          onClick={() => setTradeDetail(null)}
        >
          <motion.div
            initial={{ opacity: 0, scale: 0.96, y: 8 }}
            animate={{ opacity: 1, scale: 1, y: 0 }}
            exit={{ opacity: 0, scale: 0.96, y: 8 }}
            className="pixel-nine-slice pixel-modal-shell flex max-h-[min(92vh,42rem)] w-full max-w-lg flex-col overflow-hidden shadow-[0_24px_80px_rgba(0,0,0,0.55)]"
            style={getNineSliceStyle(UI_CHROME.modalPanel)}
            onClick={event => event.stopPropagation()}
          >
            <div className="flex items-center justify-between border-b border-white/10 px-5 py-4">
              <div>
                <div className="text-sm font-semibold text-white">物品详情</div>
                <div className="mt-1 text-xs text-zinc-500">
                  {tradeDetail.source === 'buy' ? '对方物品' : '背包物品'}
                </div>
              </div>
              <PixelCloseButton
                onClick={() => setTradeDetail(null)}
                label="关闭物品详情"
                placement="inline"
              />
            </div>

            <div className="min-h-0 flex-1 space-y-4 overflow-y-auto p-5">
              <div className="flex items-start gap-4">
                <div className="flex h-20 w-20 shrink-0 items-center justify-center rounded-2xl border border-white/10 bg-black/25">
                  <PixelIcon src={getItemVisualSrc(tradeDetailItem)} className="h-12 w-12" />
                </div>
                <div className="min-w-0 flex-1">
                  <div className="text-base font-semibold text-white">{tradeDetailItem.name}</div>
                  <div className="mt-1 text-xs text-zinc-500">
                    {tradeDetailItem.category} / {getRarityLabel(tradeDetailItem.rarity)}
                  </div>
                  <div className="mt-2 space-y-1 text-sm text-zinc-300">
                    <div>库存: {tradeDetailItem.quantity}</div>
                    <div>估值: {getInventoryItemValue(tradeDetailItem)}</div>
                    <div>
                      {tradeDetail.source === 'buy'
                        ? `购买价格: ${formatCurrency(tradeDetailView?.unitPrice ?? 0, gameState.worldType)}`
                        : `回收价格: ${formatCurrency(tradeDetailView?.unitPrice ?? 0, gameState.worldType)}`}
                    </div>
                  </div>
                </div>
              </div>

              <p className="text-sm leading-relaxed text-zinc-300">
                {buildInventoryItemDescription(tradeDetailItem, tradeDetailUseEffect)}
              </p>

              <div className="grid grid-cols-2 gap-2 text-xs text-zinc-300">
                <div className="rounded-lg border border-white/8 bg-black/20 px-3 py-2">
                  {tradeDetailEquipSlot ? `装备位：${getEquipmentSlotLabel(tradeDetailEquipSlot)}` : '不可装备'}
                </div>
                <div className="rounded-lg border border-white/8 bg-black/20 px-3 py-2">
                  {isInventoryItemUsable(tradeDetailItem) ? '可立即使用' : '不可即时使用'}
                </div>
                <div className="col-span-2 rounded-lg border border-white/8 bg-black/20 px-3 py-2">
                  标签：{getInventoryTagLabels(tradeDetailItem.tags).join(' / ') || '无'}
                </div>
              </div>

              {tradeDetailEffectText && (
                <div className="rounded-lg border border-emerald-400/15 bg-emerald-500/10 px-3 py-2 text-xs text-emerald-100">
                  使用效果：{tradeDetailEffectText}
                </div>
              )}

              <div className="flex justify-end">
                <button
                  type="button"
                  onClick={() => setTradeDetail(null)}
                  className="pixel-nine-slice pixel-pressable px-4 py-2 text-xs text-zinc-200"
                  style={getNineSliceStyle(UI_CHROME.choiceButton, { paddingX: 14, paddingY: 8 })}
                >
                  关闭
                </button>
              </div>
            </div>
          </motion.div>
        </motion.div>
      )}

      {npcUi.giftModal && (
        <motion.div
          initial={{ opacity: 0 }}
          animate={{ opacity: 1 }}
          exit={{ opacity: 0 }}
          className="fixed inset-0 z-[75] flex items-center justify-center bg-black/70 p-4 backdrop-blur-sm"
          onClick={npcUi.closeGiftModal}
        >
          <motion.div
            initial={{ opacity: 0, scale: 0.96, y: 8 }}
            animate={{ opacity: 1, scale: 1, y: 0 }}
            exit={{ opacity: 0, scale: 0.96, y: 8 }}
            className="pixel-nine-slice pixel-modal-shell flex max-h-[min(92vh,48rem)] w-full max-w-3xl flex-col overflow-hidden shadow-[0_24px_80px_rgba(0,0,0,0.55)]"
            style={getNineSliceStyle(UI_CHROME.modalPanel)}
            onClick={event => event.stopPropagation()}
          >
            <div className="flex items-center justify-between border-b border-white/10 px-5 py-4">
              <div>
                <div className="text-sm font-semibold text-white">赠送礼物</div>
                <div className="mt-1 text-xs text-zinc-500">{npcUi.giftModal.encounter.npcName}</div>
              </div>
              <PixelCloseButton
                onClick={npcUi.closeGiftModal}
                label="关闭赠礼"
                placement="inline"
              />
            </div>

            <div className="min-h-0 flex-1 space-y-2 overflow-y-auto p-5">
              {npcUi.giftModal.introText && (
                <div className="whitespace-pre-line rounded-xl border border-rose-300/15 bg-rose-500/10 px-3 py-2 text-xs leading-relaxed text-rose-50/90">
                  {npcUi.giftModal.introText}
                </div>
              )}
              {giftCandidates.length > 0 ? giftCandidates.map(candidate => (
                <button
                  key={candidate.itemId}
                  type="button"
                  onClick={() => npcUi.selectGiftItem(candidate.itemId)}
                  className={`w-full rounded-lg border px-3 py-2 text-left transition-colors ${npcUi.giftModal?.selectedItemId === candidate.itemId ? 'border-rose-400/60 bg-rose-500/10' : 'border-white/5 bg-black/20 hover:border-white/15'}`}
                >
                  <div className="flex items-center justify-between gap-3">
                    <div className="flex items-center gap-3">
                      <PixelIcon src={getItemVisualSrc(candidate.item)} className="h-8 w-8" />
                      <div>
                        <div className="text-sm text-white">{candidate.item.name}</div>
                        <div className="mt-1 text-[10px] text-zinc-500">{candidate.item.category} / {getRarityLabel(candidate.item.rarity)}</div>
                        {!candidate.canSubmit && candidate.reason && (
                          <div className="mt-1 text-[10px] text-rose-200/80">
                            {candidate.reason}
                          </div>
                        )}
                      </div>
                    </div>
                    <div className="rounded-full border border-rose-500/20 bg-rose-500/10 px-2 py-0.5 text-[10px] text-rose-100">
                      好感 +{candidate.affinityGain}
                    </div>
                  </div>
                </button>
              )) : (
                <div className="rounded-xl border border-dashed border-white/10 bg-black/20 px-4 py-6 text-sm text-zinc-500">
                  当前没有适合送出的礼物。
                </div>
              )}
            </div>

            <div className="flex justify-end gap-3 px-5 pb-5">
              <button type="button" onClick={npcUi.closeGiftModal} className="pixel-nine-slice pixel-pressable px-4 py-2 text-xs text-zinc-200" style={getNineSliceStyle(UI_CHROME.choiceButton, { paddingX: 14, paddingY: 8 })}>
                取消
              </button>
              <button type="button" disabled={!activeGiftView?.canSubmit} onClick={npcUi.confirmGift} className={`pixel-nine-slice pixel-pressable px-4 py-2 text-xs ${activeGiftView?.canSubmit ? 'text-white' : 'text-zinc-600'}`} style={getNineSliceStyle(UI_CHROME.choiceButton, { paddingX: 14, paddingY: 8 })}>
                确认赠礼
              </button>
            </div>
          </motion.div>
        </motion.div>
      )}

      {npcUi.recruitModal && (
        <motion.div
          initial={{ opacity: 0 }}
          animate={{ opacity: 1 }}
          exit={{ opacity: 0 }}
          className="fixed inset-0 z-[75] flex items-center justify-center bg-black/70 p-4 backdrop-blur-sm"
          onClick={npcUi.closeRecruitModal}
        >
          <motion.div
            initial={{ opacity: 0, scale: 0.96, y: 8 }}
            animate={{ opacity: 1, scale: 1, y: 0 }}
            exit={{ opacity: 0, scale: 0.96, y: 8 }}
            className="pixel-nine-slice pixel-modal-shell flex max-h-[min(92vh,42rem)] w-full max-w-2xl flex-col overflow-hidden shadow-[0_24px_80px_rgba(0,0,0,0.55)]"
            style={getNineSliceStyle(UI_CHROME.modalPanel)}
            onClick={event => event.stopPropagation()}
          >
            <div className="flex items-center justify-between border-b border-white/10 px-5 py-4">
              <div>
                <div className="text-sm font-semibold text-white">调整同行位置</div>
                <div className="mt-1 text-xs text-zinc-500">队伍已满，请先选择一名当前同行角色离队，再邀请对方加入。</div>
              </div>
              <PixelCloseButton
                onClick={npcUi.closeRecruitModal}
                label="关闭招募"
                placement="inline"
              />
            </div>

            <div className="min-h-0 flex-1 space-y-2 overflow-y-auto p-5">
              {npcUi.recruitModal.introText && (
                <div className="whitespace-pre-line rounded-xl border border-amber-300/15 bg-amber-500/10 px-3 py-2 text-xs leading-relaxed text-amber-50/90">
                  {npcUi.recruitModal.introText}
                </div>
              )}
              {gameState.companions.length > 0 ? gameState.companions.map(companion => {
                const character = getCharacterById(companion.characterId);
                if (!character) return null;
                return (
                  <button
                    key={companion.npcId}
                    type="button"
                    onClick={() => npcUi.selectRecruitRelease(companion.npcId)}
                    className={`w-full rounded-lg border px-3 py-2 text-left transition-colors ${npcUi.recruitModal?.selectedReleaseNpcId === companion.npcId ? 'border-amber-400/60 bg-amber-500/10' : 'border-white/5 bg-black/20 hover:border-white/15'}`}
                  >
                    <div className="text-sm text-white">{character.name}</div>
                    <div className="mt-1 text-[10px] text-zinc-500">{character.title}</div>
                  </button>
                );
              }) : (
                <div className="rounded-xl border border-dashed border-white/10 bg-black/20 px-4 py-6 text-sm text-zinc-500">
                  当前没有可替换的同行角色。
                </div>
              )}
            </div>

            <div className="flex justify-end gap-3 px-5 pb-5">
              <button type="button" onClick={npcUi.closeRecruitModal} className="pixel-nine-slice pixel-pressable px-4 py-2 text-xs text-zinc-200" style={getNineSliceStyle(UI_CHROME.choiceButton, { paddingX: 14, paddingY: 8 })}>
                取消
              </button>
              <button type="button" disabled={!npcUi.recruitModal.selectedReleaseNpcId} onClick={npcUi.confirmRecruit} className={`pixel-nine-slice pixel-pressable px-4 py-2 text-xs ${npcUi.recruitModal.selectedReleaseNpcId ? 'text-white' : 'text-zinc-600'}`} style={getNineSliceStyle(UI_CHROME.choiceButton, { paddingX: 14, paddingY: 8 })}>
                确认招募
              </button>
            </div>
          </motion.div>
        </motion.div>
      )}
    </AnimatePresence>
  );
}
