import { OpenAPI, OpenAPIV3_1 } from 'openapi-types';
import { describe, it, expect } from 'vitest';

import { DEFAULT_API_GROUP_NAME, DEFAULT_WEBHOOK_GROUP_NAME } from '../src/openapi/common.js';
import { generateOpenApiPagesForDocsConfig } from '../src/openapi/generateOpenApiPagesForDocsConfig.js';
import {
  emptyDoc,
  simpleDoc,
  docWithTags,
  complexDoc,
  webhooksDoc,
  pathsAndWebhooksDoc,
} from './fixtures/openapi.js';

describe('generateOpenApiPagesForDocsConfig', () => {
  it('should throw error for empty paths', async () => {
    await expect(generateOpenApiPagesForDocsConfig(emptyDoc as OpenAPI.Document)).rejects.toThrow(
      'No paths defined.'
    );
  });

  it('should generate navigation structure for simple API', async () => {
    const result = await generateOpenApiPagesForDocsConfig(simpleDoc as OpenAPI.Document);

    // Check nav structure
    expect(result.nav).toHaveLength(1);
    expect(result.nav[0]).toHaveProperty('group', DEFAULT_API_GROUP_NAME);
    expect(result.nav[0]).toHaveProperty('pages');

    // Check decorated nav structure
    expect(result.decoratedNav).toHaveLength(1);
    expect(result.decoratedNav[0]).toHaveProperty('group', DEFAULT_API_GROUP_NAME);
    expect(result.decoratedNav[0]).toHaveProperty('pages');
  });

  it('should handle custom group names', async () => {
    const result = await generateOpenApiPagesForDocsConfig(docWithTags as OpenAPI.Document);

    // Check that the group name matches the tag
    expect(result.nav).toHaveLength(1);
    expect(result.nav[0]).toHaveProperty('group', 'Users');
  });

  it('should handle multiple paths and methods', async () => {
    const result = await generateOpenApiPagesForDocsConfig(complexDoc as OpenAPI.Document);

    // Should have two groups (Users and Products)
    expect(result.nav).toHaveLength(2);

    // Check that pages were generated for all operations
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const allPages = result.nav.flatMap((group) => (group as any).pages);
    expect(allPages).toHaveLength(3); // getUsers, createUser, getProducts
  });

  it('should handle URL input', async () => {
    const validUrl = new URL('https://api.example.com/openapi.json');

    // Mock fetch implementation would be needed for this test
    // This is just to show the structure
    await expect(generateOpenApiPagesForDocsConfig(validUrl)).rejects.toThrow();
  });

  it('should handle creating pages for webhooks', async () => {
    const result = await generateOpenApiPagesForDocsConfig(webhooksDoc as OpenAPIV3_1.Document);

    expect(result.nav).toHaveLength(1);
    expect(result.nav[0]).toHaveProperty('group', DEFAULT_WEBHOOK_GROUP_NAME);
    expect(result.nav[0]).toHaveProperty('pages');
    expect((result.nav[0] as { pages: string[] }).pages[0]).toMatch(/webhooks(?:\/|\\)newpet/);
  });

  it('should handle creating pages for paths and webhooks', async () => {
    const result = await generateOpenApiPagesForDocsConfig(
      pathsAndWebhooksDoc as OpenAPIV3_1.Document
    );

    expect(result.nav).toHaveLength(2);
    expect(result.nav[0]).toHaveProperty('group', DEFAULT_API_GROUP_NAME);
    expect(result.nav[0]).toHaveProperty('pages');
    expect(result.nav[1]).toHaveProperty('group', DEFAULT_WEBHOOK_GROUP_NAME);
    expect(result.nav[1]).toHaveProperty('pages');
    expect((result.nav[0] as { pages: string[] }).pages[0]).toBe('get-plants');
    expect((result.nav[0] as { pages: string[] }).pages[1]).toBe('post-plants');
    expect((result.nav[0] as { pages: string[] }).pages[2]).toBe('delete-plants');
    expect((result.nav[1] as { pages: string[] }).pages[0]).toMatch(/webhooks(?:\/|\\)newplant/);
  });
});
