/* @vitest-environment jsdom */

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

import {
  AnimationState,
  type Character,
  type CompanionRenderState,
  type EquipmentLoadout,
  WorldType,
} from '../types';
import { CharacterPanel } from './CharacterPanel';

vi.mock('./CharacterAnimator', () => ({
  CharacterAnimator: () => <div>角色动画</div>,
}));

vi.mock('./MedievalNpcAnimator', () => ({
  MedievalNpcAnimator: () => <div>NPC 动画</div>,
}));

vi.mock('./PixelCloseButton', () => ({
  PixelCloseButton: ({
    label,
    onClick,
  }: {
    label: string;
    onClick: () => void;
  }) => (
    <button type="button" onClick={onClick}>
      {label}
    </button>
  ),
}));

vi.mock('./PixelIcon', () => ({
  PixelIcon: ({ className }: { className?: string }) => (
    <span className={className}>像素图标</span>
  ),
}));

vi.mock('./ResolvedAssetImage', () => ({
  ResolvedAssetImage: ({ alt }: { alt: string }) => <img alt={alt} />,
}));

function createCharacter(id: string, name: string): Character {
  return {
    id,
    name,
    title: `${name}称号`,
    gender: 'female',
    description: `${name}描述`,
    backstory: `${name}背景故事`,
    avatar: `/${id}.png`,
    portrait: `/${id}.png`,
    assetFolder: 'roles',
    assetVariant: 'generated',
    attributes: {
      strength: 10,
      agility: 10,
      intelligence: 10,
      spirit: 10,
    },
    personality: `${name}性格`,
    skills: [],
    adventureOpenings: {},
  };
}

function findSharedDarkPanelForText(text: string) {
  let current: HTMLElement | null = screen.getByText(text);

  while (current) {
    if (
      current.className.includes('border-white/10') &&
      current.className.includes('bg-black/25')
    ) {
      return current;
    }
    current = current.parentElement;
  }

  return null;
}

test('角色面板详情静态信息复用暗色平台子面板和胶囊标签', async () => {
  const user = userEvent.setup();
  const playerCharacter = createCharacter('hero', '沈行');
  const companionCharacter = createCharacter('sword-princess', '闻雪');
  const companionRenderState: CompanionRenderState = {
    npcId: 'npc-companion-1',
    character: companionCharacter,
    hp: 42,
    maxHp: 60,
    mana: 18,
    maxMana: 30,
    skillCooldowns: {},
    animationState: AnimationState.IDLE,
    slot: 'upper',
  };

  render(
    <CharacterPanel
      worldType={WorldType.WUXIA}
      playerCharacter={playerCharacter}
      playerHp={80}
      playerMaxHp={100}
      playerMana={25}
      playerMaxMana={40}
      playerEquipment={{} as EquipmentLoadout}
      companionRenderStates={[companionRenderState]}
      companionArcStates={[
        {
          characterId: companionCharacter.id,
          arcTheme: '潮声里的信任',
          currentStage: 'opening',
          activeConflictTags: [],
          pendingEventIds: [],
          resolvedEventIds: [],
        },
      ]}
      companionResolutions={[
        {
          characterId: companionCharacter.id,
          resolutionType: 'bonded',
          summary: '闻雪与主角完成潮声誓约。',
          relatedThreadIds: ['thread-tide'],
        },
      ]}
    />,
  );

  const multiplierBadge = screen.getAllByText(/适配 x/u)[0];
  expect(multiplierBadge?.className).toContain('rounded-full');
  expect(multiplierBadge?.className).toContain('bg-emerald-500/10');

  await user.click(screen.getByRole('button', { name: /沈行/u }));

  const levelProgressPanel = screen.getByTestId(
    'character-panel-level-progress',
  );

  expect(levelProgressPanel.className).toContain('border-amber-300/18');
  expect(levelProgressPanel.className).toContain('bg-amber-500/8');
  expect(levelProgressPanel.className).toContain('rounded-xl');
  expect(findSharedDarkPanelForText('沈行背景故事')?.className).toContain(
    'bg-black/25',
  );
  expect(findSharedDarkPanelForText('沈行性格')?.className).toContain(
    'bg-black/25',
  );

  await user.click(screen.getByRole('button', { name: '关闭角色详情' }));
  await user.click(screen.getByRole('button', { name: /闻雪/u }));

  expect(findSharedDarkPanelForText('个人线阶段')?.className).toContain(
    'bg-black/25',
  );
  expect(findSharedDarkPanelForText('潮声里的信任')?.className).toContain(
    'bg-black/25',
  );
  const resolutionPanel = screen.getByTestId('character-panel-resolution');

  expect(resolutionPanel.className).toContain('border-emerald-400/18');
  expect(resolutionPanel.className).toContain('bg-emerald-500/8');
  expect(resolutionPanel.className).toContain('rounded-xl');
  expect(findSharedDarkPanelForText('王庭剑')?.className).toContain(
    'bg-black/25',
  );
});
