import { renderToStaticMarkup } from 'react-dom/server';
import { describe, expect, it, vi } from 'vitest';
import type { ApiDocSection, TaskForm } from '../types';
import { ApiDocsPage } from './ApiDocsPage';

describe('ApiDocsPage extended task documentation', () => {
  it.each([
    ['guideBaseUrl', '前往创建 API Key'],
    ['guideWebhook', 'TASK_PROGRESS_CALLBACK_ENABLED'],
    ['guideErrors', '400 invalid_parameter'],
    ['guideTesting', 'simulated=true'],
  ] as const)('renders the clickable guide page %s', (section, expectedContent) => {
    const html = renderDocs(section, { kind: 'chat.completions', model: 'gpt-4o-mini', prompt: '你好' });

    expect(html).toContain('data-active="true"');
    expect(html).toContain(expectedContent);
    expect(html).toContain('指南导航');
    expect(html).not.toContain('/v1/chat/completions');
  });

  it('documents the OpenAI-compatible Responses request and continuity fields', () => {
    const html = renderDocs('responses', { kind: 'responses', model: 'gpt-4o-mini', prompt: '你好' });

    expect(html).toContain('/v1/responses');
    expect(html).toContain('previous_response_id');
    expect(html).toContain('X-Async');
    expect(html).toContain('连续对话与状态归属');
  });

  it('documents video generation parameters and async retrieval guidance', () => {
    const html = renderDocs('videoGeneration', { kind: 'videos.generations', model: '豆包Seedance-2.0', prompt: '雪山日出' });

    expect(html).toContain('/api/v1/videos/generations');
    expect(html).toContain('aspect_ratio');
    expect(html).toContain('reference_image');
    expect(html).toContain('任务取回接口');
  });

  it('defaults the online runner to test mode and offers an explicit real submission mode', () => {
    const html = renderDocs('imageEdit', { kind: 'images.edits', model: 'gpt-image-1', prompt: '移除背景' });

    expect(html).toContain('运行模式');
    expect(html).toContain('测试模式');
    expect(html).toContain('真实提交');
    expect(html).toContain('aria-pressed="true"');
    expect(html).toContain('&quot;runMode&quot;: &quot;simulation&quot;');
    expect(html).toContain('&quot;simulation&quot;: true');
  });

  it('documents async mode as a body-independent capability', () => {
    const html = renderDocs('asyncMode', { kind: 'chat.completions', model: 'gpt-4o-mini', prompt: '你好' });

    expect(html).toContain('X-Async');
    expect(html).toContain('原请求 Header');
    expect(html).toContain('同步与异步的区别');
    expect(html).toContain('异步受理响应');
    expect(html).not.toContain('/api/v1/videos/generations');
    expect(html).not.toContain('Body 参数');
    expect(html).not.toContain('视频模型 ID');
  });

  it.each(['chat', 'responses', 'embeddings', 'reranks', 'imageGeneration', 'imageEdit', 'videoGeneration'] as const)(
    'shows the shared X-Async switch on the %s task API',
    (section) => {
      const html = renderDocs(section, { kind: 'chat.completions', model: 'gpt-4o-mini', prompt: '你好' });

      expect(html).toContain('X-Async');
    },
  );

  it('renders nested objects and object arrays recursively', () => {
    const html = renderDocs('videoGeneration', { kind: 'videos.generations', model: '豆包Seedance-2.0', prompt: '雪山日出' });

    expect(html).toContain('array&lt;object&gt;');
    expect(html).toContain('data-depth="1"');
    expect(html).toContain('data-depth="4"');
    expect(html).toContain('inline_element');
    expect(html).toContain('refer_images');
    expect(html).toContain('slot_key');
  });

  it('renders task retrieval as GET with a path parameter instead of a request body', () => {
    const html = renderDocs('taskRetrieve', { kind: 'tasks.retrieve', model: 'task', prompt: '', taskId: 'task-123' });

    expect(html).toContain('GET');
    expect(html).toContain('/api/v1/tasks/task-123');
    expect(html).toContain('Path 参数');
    expect(html).toContain('响应 Body');
    expect(html).toContain('result');
    expect(html).toContain('billingSummary');
    expect(html).toContain('attempts');
    expect(html).toContain('成功响应示例');
    expect(html).toContain('Task ID');
    expect(html).not.toContain('请求 Body');
  });
});

function renderDocs(activeDocSection: ApiDocSection, taskForm: TaskForm) {
  return renderToStaticMarkup(
    <ApiDocsPage
      activeDocSection={activeDocSection}
      apiKeySecretsById={{}}
      apiKeys={[]}
      canRun
      coreMessage=""
      coreState="idle"
      selectedApiKeyId=""
      taskForm={taskForm}
      taskResult={null}
      onApiKeyChange={vi.fn()}
      onCreateApiKey={vi.fn()}
      onDocSectionChange={vi.fn()}
      onLogin={vi.fn()}
      onSubmitTask={vi.fn()}
      onTaskFormChange={vi.fn()}
    />,
  );
}
