/**
 * EIP-6963 Multi-Provider Discovery
 *
 * Discovers all injected browser wallets (MetaMask, Rainbow, etc.)
 * via the standardized EIP-6963 event protocol. Zero dependencies.
 *
 * @see https://eips.ethereum.org/EIPS/eip-6963
 */

// ============================================================================
// TYPES
// ============================================================================

export interface EIP6963ProviderInfo {
  uuid: string;
  name: string;
  icon: string;
  rdns: string;
}

export interface EIP1193Provider {
  request(args: { method: string; params?: any[] }): Promise<any>;
  on?(event: string, handler: (...args: any[]) => void): void;
  removeListener?(event: string, handler: (...args: any[]) => void): void;
}

export interface EIP6963ProviderDetail {
  info: EIP6963ProviderInfo;
  provider: EIP1193Provider;
}

interface EIP6963AnnounceProviderEvent extends Event {
  detail: EIP6963ProviderDetail;
}

// ============================================================================
// WALLET PROVIDER DISCOVERY
// ============================================================================

export class WalletProviderDiscovery {
  private providers = new Map<string, EIP6963ProviderDetail>();
  private listeners = new Set<(providers: EIP6963ProviderDetail[]) => void>();
  private listening = false;
  private handler: ((e: Event) => void) | null = null;

  start(): void {
    if (this.listening) return;
    this.listening = true;

    this.handler = (e: Event) => {
      const detail = (e as EIP6963AnnounceProviderEvent).detail;
      if (!detail?.info?.uuid || !detail?.provider) return;
      this.providers.set(detail.info.uuid, detail);
      this.notify();
    };

    window.addEventListener('eip6963:announceProvider', this.handler);
    window.dispatchEvent(new Event('eip6963:requestProvider'));
  }

  stop(): void {
    if (!this.listening || !this.handler) return;
    window.removeEventListener('eip6963:announceProvider', this.handler);
    this.handler = null;
    this.listening = false;
  }

  getProviders(): EIP6963ProviderDetail[] {
    return [...this.providers.values()];
  }

  getProvider(uuid: string): EIP6963ProviderDetail | undefined {
    return this.providers.get(uuid);
  }

  getProviderByRdns(rdns: string): EIP6963ProviderDetail | undefined {
    for (const detail of this.providers.values()) {
      if (detail.info.rdns === rdns) return detail;
    }
    return undefined;
  }

  onProvidersChanged(cb: (providers: EIP6963ProviderDetail[]) => void): () => void {
    this.listeners.add(cb);
    return () => this.listeners.delete(cb);
  }

  private notify(): void {
    const list = this.getProviders();
    for (const cb of this.listeners) {
      try { cb(list); } catch {}
    }
  }
}
