import { RegistrySource } from '../base.js';
import {
  SmitheryRegistryResponseSchema,
  sanitizeString,
  type SmitheryServerEntry,
  type RegistryServer,
} from '../types.js';
import { withRetry } from '../retry.js';

const BASE_URL = 'https://registry.smithery.ai/servers';

export class SmitheryRegistrySource extends RegistrySource {
  readonly name = 'smithery' as const;

  async search(query: string, limit: number): Promise<RegistryServer[]> {
    const results: RegistryServer[] = [];
    let page = 1;

    while (results.length < limit) {
      const url = new URL(BASE_URL);
      url.searchParams.set('q', query);
      url.searchParams.set('pageSize', String(Math.min(limit - results.length, 50)));
      url.searchParams.set('page', String(page));

      const response = await withRetry(() => fetch(url.toString()));
      if (!response.ok) {
        throw new Error(`Smithery registry returned ${String(response.status)}`);
      }

      const raw: unknown = await response.json();
      const parsed = SmitheryRegistryResponseSchema.parse(raw);

      for (const entry of parsed.servers) {
        results.push(this.normalizeResult(entry));
      }

      if (page >= parsed.pagination.totalPages || parsed.servers.length === 0) break;
      page++;
    }

    return results.slice(0, limit);
  }

  protected normalizeResult(raw: unknown): RegistryServer {
    const entry = raw as SmitheryServerEntry;

    const result: RegistryServer = {
      name: sanitizeString(entry.displayName !== '' ? entry.displayName : entry.qualifiedName),
      description: sanitizeString(entry.description),
      packages: {},
      envTemplate: [], // Smithery doesn't include env vars in list view
      transport: entry.remote ? 'sse' : 'stdio',
      popularityScore: entry.useCount,
      verified: entry.verified,
      sourceRegistry: 'smithery',
    };
    if (entry.createdAt !== undefined) {
      result.lastUpdated = new Date(entry.createdAt);
    }
    return result;
  }
}
