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

const BASE_URL = 'https://glama.ai/api/mcp/v1/servers';

export class GlamaRegistrySource extends RegistrySource {
  readonly name = 'glama' as const;

  async search(query: string, limit: number): Promise<RegistryServer[]> {
    const results: RegistryServer[] = [];
    let cursor: string | null | undefined;

    while (results.length < limit) {
      const url = new URL(BASE_URL);
      url.searchParams.set('query', query);
      if (cursor !== undefined && cursor !== null) {
        url.searchParams.set('after', cursor);
      }

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

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

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

      if (!parsed.pageInfo.hasNextPage || parsed.servers.length === 0) break;
      cursor = parsed.pageInfo.endCursor;
    }

    return results.slice(0, limit);
  }

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

    // Extract env vars from JSON Schema
    const props = entry.environmentVariablesJsonSchema?.properties ?? {};
    const envTemplate = Object.entries(props).map(([name, schemaProp]) => {
      const envVar: import('../types.js').EnvVar = {
        name,
        description: sanitizeString(schemaProp.description ?? ''),
        isSecret: name.toLowerCase().includes('token') ||
          name.toLowerCase().includes('secret') ||
          name.toLowerCase().includes('password') ||
          name.toLowerCase().includes('key'),
      };
      if (schemaProp.default !== undefined) {
        envVar.defaultValue = schemaProp.default;
      }
      return envVar;
    });

    // Determine transport from attributes
    const attrs = entry.attributes;
    let transport: RegistryServer['transport'] = 'stdio';
    if (attrs.includes('hosting:remote-capable') || attrs.includes('hosting:hybrid')) {
      transport = 'sse';
    }

    const packages: RegistryServer['packages'] = {};
    if (entry.slug !== '') {
      packages.npm = entry.slug;
    }

    const result: RegistryServer = {
      name: sanitizeString(entry.name),
      description: sanitizeString(entry.description),
      packages,
      envTemplate,
      transport,
      popularityScore: 0, // Glama has no popularity metrics in list
      verified: attrs.includes('author:official'),
      sourceRegistry: 'glama',
    };
    if (entry.repository?.url !== undefined) {
      result.repositoryUrl = entry.repository.url;
    }
    return result;
  }
}
