import { describe, it, expect } from 'vitest';
import { deduplicateResults } from '../../src/registry/dedup.js';
import type { RegistryServer } from '../../src/registry/types.js';

function makeServer(overrides: Partial<RegistryServer> = {}): RegistryServer {
  return {
    name: 'test-server',
    description: 'A test server',
    packages: {},
    envTemplate: [],
    transport: 'stdio',
    popularityScore: 0,
    verified: false,
    sourceRegistry: 'official',
    ...overrides,
  };
}

describe('deduplicateResults', () => {
  it('keeps unique servers', () => {
    const servers = [
      makeServer({ name: 'server-a', packages: { npm: 'pkg-a' } }),
      makeServer({ name: 'server-b', packages: { npm: 'pkg-b' } }),
    ];
    expect(deduplicateResults(servers)).toHaveLength(2);
  });

  it('deduplicates by npm package name, keeps higher popularity', () => {
    const servers = [
      makeServer({ name: 'low', packages: { npm: '@test/slack' }, popularityScore: 10, sourceRegistry: 'official' }),
      makeServer({ name: 'high', packages: { npm: '@test/slack' }, popularityScore: 100, sourceRegistry: 'smithery' }),
    ];
    const result = deduplicateResults(servers);
    expect(result).toHaveLength(1);
    expect(result[0]?.name).toBe('high');
    expect(result[0]?.popularityScore).toBe(100);
  });

  it('deduplicates by GitHub URL with different formats', () => {
    const servers = [
      makeServer({ name: 'a', repositoryUrl: 'https://github.com/org/repo', popularityScore: 5 }),
      makeServer({ name: 'b', repositoryUrl: 'git@github.com:org/repo.git', popularityScore: 50 }),
    ];
    const result = deduplicateResults(servers);
    expect(result).toHaveLength(1);
    expect(result[0]?.name).toBe('b');
  });

  it('merges envTemplate from both sources', () => {
    const servers = [
      makeServer({
        name: 'a',
        packages: { npm: 'pkg' },
        envTemplate: [{ name: 'TOKEN', description: 'API token', isSecret: true }],
        popularityScore: 10,
      }),
      makeServer({
        name: 'b',
        packages: { npm: 'pkg' },
        envTemplate: [{ name: 'URL', description: 'Base URL', isSecret: false }],
        popularityScore: 5,
      }),
    ];
    const result = deduplicateResults(servers);
    expect(result).toHaveLength(1);
    expect(result[0]?.envTemplate).toHaveLength(2);
    expect(result[0]?.envTemplate.map((e) => e.name)).toContain('TOKEN');
    expect(result[0]?.envTemplate.map((e) => e.name)).toContain('URL');
  });

  it('deduplicates envTemplate by var name', () => {
    const servers = [
      makeServer({
        packages: { npm: 'pkg' },
        envTemplate: [{ name: 'TOKEN', description: 'from a', isSecret: true }],
        popularityScore: 10,
      }),
      makeServer({
        packages: { npm: 'pkg' },
        envTemplate: [{ name: 'TOKEN', description: 'from b', isSecret: true }],
        popularityScore: 5,
      }),
    ];
    const result = deduplicateResults(servers);
    expect(result[0]?.envTemplate).toHaveLength(1);
  });

  it('merges verified status (OR)', () => {
    const servers = [
      makeServer({ packages: { npm: 'pkg' }, verified: true, popularityScore: 10 }),
      makeServer({ packages: { npm: 'pkg' }, verified: false, popularityScore: 5 }),
    ];
    const result = deduplicateResults(servers);
    expect(result[0]?.verified).toBe(true);
  });

  it('handles servers with no npm or repo', () => {
    const servers = [
      makeServer({ name: 'a' }),
      makeServer({ name: 'b' }),
    ];
    // No matching key → no dedup
    expect(deduplicateResults(servers)).toHaveLength(2);
  });
});
