/* @vitest-environment jsdom */

import { fireEvent, render, screen } from '@testing-library/react';
import { act } from 'react';
import type { ImgHTMLAttributes } from 'react';
import { expect, test, vi } from 'vitest';

import type {
  PuzzleClearCardAsset,
  PuzzleClearPatternGroup,
  PuzzleClearWorkProfileResponse,
} from '../../../packages/shared/src/contracts/puzzleClear';
import { PuzzleClearResultView } from './PuzzleClearResultView';

vi.mock('../ResolvedAssetImage', () => ({
  ResolvedAssetImage: ({
    src,
    alt,
    className,
    ...rest
  }: {
    src?: string | null;
    alt?: string;
    className?: string;
    [key: string]: unknown;
  }) =>
    src ? (
      <img
        src={src}
        alt={alt}
        className={className}
        {...(rest as ImgHTMLAttributes<HTMLImageElement>)}
      />
    ) : null,
}));

function createPatternGroup(index: number): PuzzleClearPatternGroup {
  return {
    groupId: `group-${index}`,
    shape: '1x2',
    width: 2,
    height: 1,
    atlasX: index * 64,
    atlasY: 0,
    atlasWidth: 128,
    atlasHeight: 64,
  };
}

function createCard(index: number): PuzzleClearCardAsset {
  return {
    cardId: `card-${index}`,
    groupId: `group-${Math.floor(index / 2)}`,
    shape: '1x2',
    orientation: 'horizontal',
    partX: index % 2,
    partY: 0,
    imageSrc: `/cards/card-${index}.png`,
    imageObjectKey: `generated-puzzle-clear-assets/card-${index}.png`,
    assetObjectId: `assetobj_card_${index}`,
    sourceAtlasCell: `${index}:0:0`,
  };
}

function createProfile(
  overrides: Partial<PuzzleClearWorkProfileResponse['summary']> = {},
): PuzzleClearWorkProfileResponse {
  const atlasAsset = {
    assetId: 'atlas-1',
    imageSrc: '/atlas.png',
    imageObjectKey: 'generated-puzzle-clear-assets/atlas.png',
    assetObjectId: 'assetobj_atlas',
    generationProvider: 'gpt-image-2',
    prompt: '星港',
    width: 2560,
    height: 2560,
  };
  const boardBackgroundAsset = {
    ...atlasAsset,
    assetId: 'board-background-1',
    imageSrc: '/board-background.png',
    imageObjectKey: 'generated-puzzle-clear-assets/board-background.png',
    assetObjectId: 'assetobj_board_background',
  };
  const patternGroups = Array.from({ length: 35 }, (_, index) =>
    createPatternGroup(index),
  );
  const cardAssets = Array.from({ length: 95 }, (_, index) => createCard(index));
  const draft = {
    templateId: 'puzzle-clear',
    templateName: '拼消消',
    profileId: 'puzzle-clear-profile-12345678',
    workTitle: '星港拼消消',
    workDescription: '霓虹星港主题',
    themePrompt: '星港',
    boardBackgroundPrompt: '星港中央棋盘底图',
    generateBoardBackground: true,
    boardBackgroundAsset,
    cardBackImageSrc: '/creation-type-references/puzzle-clear-card-back.webp',
    atlasAsset,
    patternGroups,
    cardAssets,
    generationStatus: 'ready' as const,
  };

  return {
    summary: {
      runtimeKind: 'puzzle-clear',
      workId: 'puzzle-clear-work-12345678',
      profileId: 'puzzle-clear-profile-12345678',
      ownerUserId: 'user-1',
      sourceSessionId: 'puzzle-clear-session-1',
      workTitle: '星港拼消消',
      workDescription: '霓虹星港主题',
      themePrompt: '星港',
      coverImageSrc: '/atlas.png',
      publicationStatus: 'draft',
      playCount: 0,
      updatedAt: '2026-05-30T00:00:00.000Z',
      publishedAt: null,
      publishReady: true,
      generationStatus: 'ready',
      ...overrides,
    },
    draft,
    boardBackgroundAsset,
    atlasAsset,
    patternGroups,
    cardAssets,
  };
}

test('结果页展示 atlas、中央底图与卡牌预览，并触发试玩、发布和图集重试', async () => {
  const onStartTestRun = vi.fn();
  const onPublish = vi.fn();
  const onRegenerateAtlas = vi.fn();

  const { container } = render(
    <PuzzleClearResultView
      profile={createProfile()}
      onBack={vi.fn()}
      onEdit={vi.fn()}
      onStartTestRun={onStartTestRun}
      onPublish={onPublish}
      onRegenerateAtlas={onRegenerateAtlas}
    />,
  );

  expect(screen.getByAltText('场地底图').getAttribute('src')).toBe(
    '/board-background.png',
  );
  expect(screen.getByAltText('素材图集').getAttribute('src')).toBe('/atlas.png');
  expect(screen.getByText('35')).not.toBeNull();
  expect(screen.getByText('95')).not.toBeNull();
  expect(container.querySelectorAll('img[src^="/cards/"]')).toHaveLength(24);

  fireEvent.click(screen.getByRole('button', { name: /试玩/u }));
  await act(async () => {
    fireEvent.click(screen.getByRole('button', { name: /发布/u }));
  });
  fireEvent.click(screen.getByRole('button', { name: /图集/u }));

  expect(onStartTestRun).toHaveBeenCalledTimes(1);
  expect(onPublish).toHaveBeenCalledTimes(1);
  expect(onRegenerateAtlas).toHaveBeenCalledTimes(1);
});

test('结果页在素材未发布就绪时禁用发布，且不写入规则说明文案', () => {
  render(
    <PuzzleClearResultView
      profile={createProfile({ publishReady: false })}
      onBack={vi.fn()}
      onEdit={vi.fn()}
      onStartTestRun={vi.fn()}
      onPublish={vi.fn()}
      onRegenerateAtlas={vi.fn()}
    />,
  );

  expect(
    (screen.getByRole('button', { name: /发布/u }) as HTMLButtonElement).disabled,
  ).toBe(true);
  expect(screen.queryByText(/规则|玩法说明|拖动卡片|拼接完整/u)).toBeNull();
});
