/* @vitest-environment jsdom */

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

import { AnimationState, type Character } from '../types';
import {
  CharacterIdentityBadges,
  CharacterSkillsList,
  PlayerLevelProgress,
} from './CharacterInfoShared';

function createSkill(
  name: string,
  style: Character['skills'][number]['style'],
): Character['skills'][number] {
  return {
    id: '',
    name,
    animation: AnimationState.IDLE,
    damage: 12,
    manaCost: 4,
    cooldownTurns: 2,
    range: 1,
    style,
  };
}

afterEach(() => {
  vi.restoreAllMocks();
});

test('CharacterSkillsList falls back to stable render ids when skill ids are empty', async () => {
  const user = userEvent.setup();
  const handleSelectSkill = vi.fn();
  const consoleErrorSpy = vi
    .spyOn(console, 'error')
    .mockImplementation(() => undefined);

  render(
    <CharacterSkillsList
      skills={[
        createSkill('潮刃突进', 'burst'),
        createSkill('雾行转位', 'mobility'),
      ]}
      onSelectSkill={handleSelectSkill}
    />,
  );

  const buttons = screen.getAllByRole('button');
  await user.click(buttons[0]!);
  await user.click(buttons[1]!);

  expect(handleSelectSkill).toHaveBeenNthCalledWith(1, 'skill-潮刃突进-0');
  expect(handleSelectSkill).toHaveBeenNthCalledWith(2, 'skill-雾行转位-1');

  const duplicateKeyCalls = consoleErrorSpy.mock.calls.filter((call) =>
    call.some(
      (arg) =>
        typeof arg === 'string' &&
        arg.includes('Encountered two children with the same key'),
    ),
  );

  expect(duplicateKeyCalls).toHaveLength(0);
});

test('CharacterIdentityBadges renders role and level chips together', () => {
  render(
    <CharacterIdentityBadges
      roleLabel="队长"
      roleTone="amber"
      levelText="Lv.7"
    />,
  );

  expect(screen.getByText('队长')).toBeTruthy();
  expect(screen.getByText('Lv.7')).toBeTruthy();
});

test('PlayerLevelProgress renders xp progress details', () => {
  render(
    <PlayerLevelProgress level={6} currentLevelXp={72} xpToNextLevel={120} />,
  );

  expect(screen.getByText('Lv.6')).toBeTruthy();
  expect(screen.getByText('72/120')).toBeTruthy();
});
