/* @vitest-environment jsdom */

import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import type { HTMLAttributes, ReactNode } from 'react';
import { expect, test, vi } from 'vitest';

import type { StoryGenerationNpcUi } from '../hooks/rpg-runtime-story';
import {
  type Encounter,
  type GameState,
  type InventoryItem,
  WorldType,
} from '../types';
import { NpcModals } from './NpcModals';

vi.mock('motion/react', () => ({
  AnimatePresence: ({ children }: { children: ReactNode }) => <>{children}</>,
  motion: {
    div: ({
      animate: _animate,
      children,
      exit: _exit,
      initial: _initial,
      ...props
    }: HTMLAttributes<HTMLDivElement> & {
      animate?: unknown;
      exit?: unknown;
      initial?: unknown;
    }) => <div {...props}>{children}</div>,
  },
}));

const encounter = {
  id: 'npc-merchant',
  kind: 'npc',
  npcName: '潮市商人',
} as Encounter;

const tradeItem: InventoryItem = {
  id: 'moon-shell',
  category: '材料',
  name: '月壳',
  quantity: 3,
  rarity: 'rare',
  tags: [],
};

const giftItem: InventoryItem = {
  id: 'rose-token',
  category: '礼物',
  name: '玫瑰信物',
  quantity: 1,
  rarity: 'rare',
  tags: [],
};

function createNpcUi(): StoryGenerationNpcUi {
  return {
    tradeModal: {
      encounter,
      actionText: '交易',
      introText: '商人压低声音提示你。',
      mode: 'buy',
      selectedNpcItemId: 'moon-shell',
      selectedPlayerItemId: null,
      selectedQuantity: 1,
    },
    giftModal: {
      encounter,
      actionText: '赠礼',
      introText: '她更喜欢有纪念意义的礼物。',
      selectedItemId: 'rose-token',
    },
    recruitModal: null,
    setTradeMode: vi.fn(),
    selectTradeNpcItem: vi.fn(),
    selectTradePlayerItem: vi.fn(),
    setTradeQuantity: vi.fn(),
    closeTradeModal: vi.fn(),
    confirmTrade: vi.fn(),
    selectGiftItem: vi.fn(),
    closeGiftModal: vi.fn(),
    confirmGift: vi.fn(),
    selectRecruitRelease: vi.fn(),
    closeRecruitModal: vi.fn(),
    confirmRecruit: vi.fn(),
  };
}

function createEmptyNpcUi(): StoryGenerationNpcUi {
  const ui = createNpcUi();

  return {
    ...ui,
    tradeModal: ui.tradeModal
      ? {
          ...ui.tradeModal,
          selectedNpcItemId: null,
          selectedPlayerItemId: null,
        }
      : null,
    giftModal: ui.giftModal
      ? {
          ...ui.giftModal,
          selectedItemId: null,
        }
      : null,
    recruitModal: {
      encounter,
      actionText: '邀请同行',
      introText: '同行名额已满，需要先让一人离队。',
      selectedReleaseNpcId: null,
    },
  };
}

function createGameState(): GameState {
  return {
    worldType: WorldType.CUSTOM,
    playerCurrency: 24,
    runtimeNpcInteraction: {
      npcId: 'npc-merchant',
      npcName: '潮市商人',
      playerCurrency: 24,
      currencyName: '贝币',
      trade: {
        buyItems: [
          {
            itemId: 'moon-shell',
            item: tradeItem,
            mode: 'buy',
            unitPrice: 5,
            maxQuantity: 3,
            canSubmit: true,
          },
        ],
        sellItems: [],
      },
      gift: {
        items: [
          {
            itemId: 'rose-token',
            item: giftItem,
            affinityGain: 8,
            canSubmit: true,
          },
        ],
      },
    },
  } as unknown as GameState;
}

function createEmptyGameState(): GameState {
  const state = createGameState();

  return {
    ...state,
    companions: [],
    runtimeNpcInteraction: state.runtimeNpcInteraction
      ? {
          ...state.runtimeNpcInteraction,
          trade: {
            buyItems: [],
            sellItems: [],
          },
          gift: {
            items: [],
          },
        }
      : state.runtimeNpcInteraction,
  } as GameState;
}

test('NPC 交易数量和赠礼好感复用暗色平台胶囊标签', () => {
  render(<NpcModals gameState={createGameState()} npcUi={createNpcUi()} />);

  const quantityBadge = screen.getByText('x3');
  const affinityBadge = screen.getByText('好感 +8');
  const buyModeCard = screen.getByRole('button', { name: '购买物品' });
  const tradeItemCard = screen.getByRole('button', { name: /月壳/ });
  const giftItemCard = screen.getByRole('button', { name: /玫瑰信物/ });

  expect(quantityBadge.className).toContain('rounded-full');
  expect(quantityBadge.className).toContain('font-black');
  expect(quantityBadge.className).toContain('bg-black/20');
  expect(affinityBadge.className).toContain('rounded-full');
  expect(affinityBadge.className).toContain('font-black');
  expect(affinityBadge.className).toContain('bg-rose-500/10');
  expect(buyModeCard.className).toContain('platform-dark-option-card');
  expect(buyModeCard.className).toContain('border-emerald-400/45');
  expect(tradeItemCard.className).toContain('platform-dark-option-card');
  expect(tradeItemCard.className).toContain('border-emerald-400/45');
  expect(giftItemCard.className).toContain('platform-dark-option-card');
  expect(giftItemCard.className).toContain('border-rose-400/60');
});

test('NPC 交易静态信息卡复用暗色 PlatformSubpanel chrome', () => {
  render(<NpcModals gameState={createGameState()} npcUi={createNpcUi()} />);

  [
    'npc-trade-list-summary',
    'npc-trade-detail-panel',
    'npc-trade-quantity-stepper',
    'npc-trade-total-panel',
  ].forEach((testId) => {
    const panel = screen.getByTestId(testId);

    expect(panel.className).toContain('border-white/10');
    expect(panel.className).toContain('bg-black/25');
    expect(panel.className).toContain('rounded-xl');
  });
});

test('NPC 弹窗叙事提示复用暗色平台状态条', () => {
  render(<NpcModals gameState={createGameState()} npcUi={createNpcUi()} />);

  const tradeIntro = screen.getByText('商人压低声音提示你。');
  const giftIntro = screen.getByText('她更喜欢有纪念意义的礼物。');

  expect(tradeIntro.className).toContain('platform-status-message');
  expect(tradeIntro.className).toContain('border-amber-300/15');
  expect(tradeIntro.className).toContain('bg-amber-500/10');
  expect(giftIntro.className).toContain('platform-status-message');
  expect(giftIntro.className).toContain('border-rose-300/15');
  expect(giftIntro.className).toContain('bg-rose-500/10');
});

test('NPC 交易详情静态属性复用暗色 PlatformSubpanel chrome', async () => {
  const user = userEvent.setup();

  render(<NpcModals gameState={createGameState()} npcUi={createNpcUi()} />);

  await user.click(screen.getByRole('button', { name: /月壳/ }));

  ['不可装备', '不可即时使用', '标签：无'].forEach((text) => {
    const panel = screen.getByText(text);

    expect(panel.className).toContain('border-white/10');
    expect(panel.className).toContain('bg-black/25');
    expect(panel.className).toContain('rounded-xl');
  });
});

test('NPC 弹窗空态复用暗色平台空态', () => {
  render(
    <NpcModals gameState={createEmptyGameState()} npcUi={createEmptyNpcUi()} />,
  );

  [
    '对方暂时没有可出售的物品。',
    '当前没有适合送出的礼物。',
    '当前没有可替换的同行角色。',
  ].forEach((text) => {
    const emptyState = screen.getByText(text);

    expect(emptyState.className).toContain('platform-empty-state');
    expect(emptyState.className).toContain('border-dashed');
    expect(emptyState.className).toContain('bg-black/20');
  });

  const recruitIntro = screen.getByText('同行名额已满，需要先让一人离队。');
  const tradeDetailEmptyState = screen.getByText(
    '请选择一件物品，右侧会显示数量、价格与详情。',
  );

  expect(recruitIntro.className).toContain('platform-status-message');
  expect(recruitIntro.className).toContain('border-amber-300/15');
  expect(tradeDetailEmptyState.className).toContain('platform-empty-state');
  expect(tradeDetailEmptyState.className).toContain('border-dashed');
});

test('NPC 弹窗标准 dark footer CTA 复用 PlatformActionButton', async () => {
  const user = userEvent.setup();

  const { unmount } = render(
    <NpcModals gameState={createEmptyGameState()} npcUi={createEmptyNpcUi()} />,
  );
  const tradeFooter = screen.getByTestId('npc-trade-footer');
  const giftFooter = screen.getByTestId('npc-gift-footer');
  const recruitFooter = screen.getByTestId('npc-recruit-footer');

  const cancelButtons = screen.getAllByRole('button', { name: '取消' });
  const tradeConfirmButton = screen.getByRole('button', { name: '确认购买' });
  const giftConfirmButton = screen.getByRole('button', { name: '确认赠礼' });
  const recruitConfirmButton = screen.getByRole('button', { name: '确认招募' });
  const footerButtons = [
    cancelButtons[0],
    tradeConfirmButton,
    cancelButtons[1],
    giftConfirmButton,
    cancelButtons[2],
    recruitConfirmButton,
  ].filter((button): button is HTMLElement => Boolean(button));

  expect(footerButtons).toHaveLength(6);
  expect(tradeFooter.className).toContain('platform-dark-modal-footer');
  expect(tradeFooter.className).toContain('border-t');
  expect(giftFooter.className).toContain('platform-dark-modal-footer');
  expect(giftFooter.className).toContain('pb-5');
  expect(recruitFooter.className).toContain('platform-dark-modal-footer');
  expect(recruitFooter.className).toContain('pb-5');

  footerButtons.forEach((button) => {
    expect(button.className).toContain('platform-action-button--editor-dark');
    expect(button.className).toContain('rounded-2xl');
  });

  unmount();
  render(<NpcModals gameState={createGameState()} npcUi={createNpcUi()} />);

  await user.click(screen.getByRole('button', { name: /月壳/ }));

  const tradeDetailFooter = screen.getByTestId('npc-trade-detail-footer');
  const closeButton = screen.getByRole('button', { name: '关闭' });

  expect(tradeDetailFooter.className).toContain('platform-dark-modal-footer');
  expect(tradeDetailFooter.className).toContain('px-5');
  expect(tradeDetailFooter.className).toContain('py-4');
  expect(closeButton.className).toContain('platform-action-button--editor-dark');
  expect(closeButton.className).toContain('rounded-2xl');
});
