/* @vitest-environment jsdom */

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

import type { CustomWorldGenerationProgress } from '../../packages/shared/src/contracts/runtime';
import { CustomWorldGenerationView } from './CustomWorldGenerationView';

function createProgress(
  overrides: Partial<CustomWorldGenerationProgress> = {},
): CustomWorldGenerationProgress {
  return {
    phaseId: 'draft_foundation',
    phaseLabel: '整理草稿',
    phaseDetail: '正在整理当前生成步骤。',
    batchLabel: '第 2 批',
    overallProgress: 42,
    completedWeight: 21,
    totalWeight: 50,
    elapsedMs: 125_000,
    estimatedRemainingMs: 75_000,
    activeStepIndex: 1,
    steps: [
      {
        id: 'step-1',
        label: '收集设定',
        detail: '整理初始输入。',
        completed: 1,
        total: 1,
        status: 'completed',
      },
      {
        id: 'step-2',
        label: '编译草稿',
        detail: '生成首版结构。',
        completed: 2,
        total: 4,
        status: 'active',
      },
      {
        id: 'step-3',
        label: '写回结果',
        detail: '同步结果页。',
        completed: 0,
        total: 4,
        status: 'pending',
      },
    ],
    ...overrides,
  };
}

describe('CustomWorldGenerationView', () => {
  test.each(['拼图草稿生成进度', '抓大鹅草稿生成进度'])(
    'renders the circular hero and only the current step summary for %s',
    (progressTitle) => {
      const { container } = render(
        <CustomWorldGenerationView
          settingText="竖屏生成题材"
          progress={createProgress()}
          isGenerating
          error={null}
          onBack={() => {}}
          onEditSetting={() => {}}
          onRetry={() => {}}
          backLabel="返回创作中心"
          settingDescription={null}
          settingActionLabel={null}
          progressTitle={progressTitle}
        />,
      );

      expect(container.firstChild).toBeTruthy();
      expect((container.firstChild as HTMLElement).className).toContain(
        'z-[1]',
      );
      expect((container.firstChild as HTMLElement).className).toContain(
        'overflow-hidden',
      );
      expect((container.firstChild as HTMLElement).className).not.toContain(
        'overflow-y-auto',
      );

      const pageVideo = screen.getByTestId(
        'generation-page-background-video',
      ) as HTMLVideoElement;
      expect(pageVideo.parentElement?.className).toContain('z-0');
      expect(pageVideo.parentElement?.className).toContain('bg-transparent');
      expect(pageVideo.parentElement?.className).not.toContain('bg-[#fff4ea]');
      expect((container.firstChild as HTMLElement).contains(pageVideo)).toBe(
        true,
      );
      expect(pageVideo.autoplay).toBe(true);
      expect(pageVideo.loop).toBe(true);
      expect(pageVideo.muted).toBe(true);
      expect(pageVideo.playsInline).toBe(true);
      expect(pageVideo.getAttribute('preload')).toBe('auto');
      expect(
        document.querySelector(
          'video[data-testid="generation-page-background-video"] source[type="video/mp4"]',
        ),
      ).toBeTruthy();
      expect(screen.getByRole('button', { name: '返回创作中心' })).toBeTruthy();
      expect(
        screen.getByRole('button', { name: '返回创作中心' }).className,
      ).toContain('text-xs');
      expect(
        screen.getByRole('button', { name: '返回创作中心' }).className,
      ).toContain('bg-transparent');
      expect(
        screen.getByRole('button', { name: '返回创作中心' }).className,
      ).toContain('gap-2');
      expect(screen.getByText('世界建设中')).toBeTruthy();
      expect(screen.getByText('世界建设中').className).toContain('text-xs');
      expect(screen.getByText('世界建设中').className).toContain(
        'border-[var(--platform-warm-border)]',
      );
      expect(screen.getByText('世界建设中').className).toContain(
        'bg-[var(--platform-warm-bg)]',
      );
      expect(
        screen.getByTestId('generation-hero-wait-card').className,
      ).toContain('text-center');
      expect(
        screen.getByTestId('generation-hero-elapsed-card').className,
      ).toContain('text-center');
      expect(
        screen.getByTestId('generation-hero-wait-card').className,
      ).toContain('bg-white/58');
      expect(
        screen.getByTestId('generation-hero-elapsed-card').className,
      ).toContain('bg-white/58');
      expect(
        screen.getByTestId('generation-hero-wait-card').parentElement
          ?.className,
      ).toContain('mt-3');
      expect(
        screen.getByTestId('generation-hero-wait-card').parentElement
          ?.className,
      ).toContain('px-0');
      expect(screen.getByText('预计等待').className).toContain('text-[9px]');
      expect(screen.getByText('已耗时').className).toContain('text-[9px]');
      expect(screen.getByText('预计等待').parentElement?.className).toContain(
        'justify-center',
      );
      expect(screen.getByText('已耗时').parentElement?.className).toContain(
        'justify-center',
      );
      expect(screen.getByText('1 分 15 秒')).toBeTruthy();
      expect(screen.getByText('2 分 5 秒')).toBeTruthy();
      expect(screen.queryByText('预计还需 1 分 15 秒')).toBeNull();
      expect(screen.queryByText('已耗时 2 分 5 秒')).toBeNull();
      expect(screen.queryByText('计时')).toBeNull();
      expect(
        screen.getByTestId('generation-hero-progress-content').className,
      ).toContain('justify-start');
      expect(
        screen.getByTestId('generation-hero-progress-content').className,
      ).toContain('z-30');
      expect(
        screen.getByTestId('generation-hero-progress-content').className,
      ).toContain('pt-[2%]');
      expect(screen.getByText('总进度').className).toContain('text-[9px]');
      expect(screen.getByText('42%').className).toContain('text-[1.15rem]');
      expect(
        screen.getByRole('progressbar', { name: progressTitle }).className,
      ).toContain('w-[min(400px,calc(100%_-_0.75rem))]');
      expect(
        screen.getByRole('progressbar', { name: progressTitle }).className,
      ).toContain('max-w-full');
      expect(
        screen.getByRole('progressbar', { name: progressTitle }).className,
      ).toContain('aspect-square');
      expect(
        screen
          .getByRole('progressbar', { name: progressTitle })
          .getAttribute('data-ring-start-degrees'),
      ).toBe('135');
      expect(
        screen
          .getByRole('progressbar', { name: progressTitle })
          .getAttribute('data-ring-fill-start-degrees'),
      ).toBe('135');
      expect(
        screen
          .getByRole('progressbar', { name: progressTitle })
          .getAttribute('data-ring-sweep-degrees'),
      ).toBe('270');
      expect(
        screen
          .getByRole('progressbar', { name: progressTitle })
          .getAttribute('data-ring-gap-degrees'),
      ).toBe('90');
      expect(
        screen
          .getByRole('progressbar', { name: progressTitle })
          .getAttribute('data-ring-fill-degrees'),
      ).toBe('113');
      expect(screen.getByTestId('generation-hero-progress-ring').tagName).toBe(
        'svg',
      );
      expect(
        screen
          .getByTestId('generation-hero-progress-ring')
          .getAttribute('class'),
      ).toContain('z-0');
      expect(
        screen
          .getByTestId('generation-hero-progress-ring')
          .getAttribute('viewBox'),
      ).toBe('0 0 400 400');
      expect(
        screen
          .getByTestId('generation-hero-progress-ring-track')
          .getAttribute('r'),
      ).toBe('166');
      expect(
        screen
          .getByTestId('generation-hero-progress-ring-track')
          .getAttribute('stroke-width'),
      ).toBe('18');
      expect(
        screen
          .getByTestId('generation-hero-progress-ring-track')
          .getAttribute('transform'),
      ).toBe('rotate(135 200 200)');
      expect(
        screen
          .getByTestId('generation-hero-progress-ring-fill')
          .getAttribute('transform'),
      ).toBe('rotate(135 200 200)');
      expect(
        screen
          .getByTestId('generation-hero-progress-ring-fill')
          .getAttribute('stroke-dasharray'),
      ).toMatch(/^328\.\d{2} 1043\.\d{2}$/u);
      expect(
        screen.getByRole('progressbar', { name: progressTitle }),
      ).toBeTruthy();
      expect(
        screen
          .getByRole('progressbar', { name: progressTitle })
          .getAttribute('aria-valuenow'),
      ).toBe('42');
      expect(screen.getByText('当前步骤')).toBeTruthy();
      expect(screen.getByText('当前步骤').className).toContain('text-[10px]');
      expect(screen.getByText('编译草稿')).toBeTruthy();
      expect(screen.getByText('编译草稿').className).toContain('text-[14px]');
      expect(screen.getByText('进行中 50%')).toBeTruthy();
      expect(screen.getByText('进行中 50%').className).toContain('text-[11px]');
      expect(
        screen.getByTestId('generation-current-step-card').className,
      ).toContain('bg-white/58');
      expect(
        screen.getByTestId('generation-current-step-card').parentElement
          ?.className,
      ).toContain('mt-5');
      expect(
        screen.getByRole('progressbar', { name: '编译草稿 进度' }).className,
      ).toContain('platform-progress-track');
      expect(screen.queryByText('收集设定')).toBeNull();
      expect(screen.queryByText('写回结果')).toBeNull();
      expect(screen.queryByText('当前批次')).toBeNull();
      expect(screen.queryByText('正在整理当前设定步骤')).toBeNull();
      expect(screen.queryByText('竖屏生成题材')).toBeNull();
    },
  );

  test('does not render setting information cards on generation pages', () => {
    render(
      <CustomWorldGenerationView
        settingText="大鱼吃小鱼题材"
        anchorEntries={[
          { id: 'topic', label: '题材', value: '火锅' },
          { id: 'count', label: '素材数量', value: '20 种素材' },
        ]}
        progress={createProgress()}
        isGenerating
        error={null}
        onBack={() => {}}
        onEditSetting={() => {}}
        onRetry={() => {}}
        backLabel="返回创作中心"
        settingDescription={null}
        settingActionLabel={null}
        progressTitle="大鱼吃小鱼草稿生成进度"
      />,
    );

    expect(screen.queryByText('当前大鱼吃小鱼信息')).toBeNull();
    expect(screen.queryByText('题材')).toBeNull();
    expect(screen.queryByText('火锅')).toBeNull();
    expect(screen.queryByText('素材数量')).toBeNull();
    expect(screen.queryByText('20 种素材')).toBeNull();
    expect(screen.queryByText('大鱼吃小鱼题材')).toBeNull();
    expect(screen.getByTestId('generation-page-background-video')).toBeTruthy();
  });

  test('keeps the shared generation back button click behavior', async () => {
    const user = userEvent.setup();
    const onBack = vi.fn();

    render(
      <CustomWorldGenerationView
        settingText="大鱼吃小鱼题材"
        progress={createProgress()}
        isGenerating
        error={null}
        onBack={onBack}
        onEditSetting={() => {}}
        onRetry={() => {}}
        backLabel="返回创作中心"
        settingDescription={null}
        settingActionLabel={null}
        progressTitle="大鱼吃小鱼草稿生成进度"
      />,
    );

    await user.click(screen.getByRole('button', { name: '返回创作中心' }));

    expect(onBack).toHaveBeenCalledTimes(1);
  });
});
