/* ═══════════════════════════════════════════════════════════════════════════
   WCAHT Wallet – Injected Provider (window.wcaht)
   ═══════════════════════════════════════════════════════════════════════════
   This script is injected into web pages to provide a `window.wcaht` object.
   Universal WCAHT wallets expose a base58 publicKey plus a paired EVM 0x
   evmAddress when the account is backed by a secp256k1 key.
*/

(() => {
  if (window.wcaht) return; // already injected

  class WcahtProvider {
    constructor() {
      this.isWcaht = true;
      this.isConnected = false;
      this.publicKey = null;
      this.address = null;
      this.addressType = 'native-ed25519';
      this.evmAddress = null;
      this._listeners = {};
      this._requestId = 0;
      this._pending = {};
    }

    // ── Event Emitter ─────────────────────────────────────────────────────
    on(event, fn) {
      if (!this._listeners[event]) this._listeners[event] = [];
      this._listeners[event].push(fn);
      return this;
    }

    off(event, fn) {
      if (!this._listeners[event]) return;
      this._listeners[event] = this._listeners[event].filter(f => f !== fn);
    }

    _emit(event, ...args) {
      (this._listeners[event] || []).forEach(fn => fn(...args));
    }

    // ── RPC to extension via postMessage ─────────────────────────────────
    _request(method, params) {
      return new Promise((resolve, reject) => {
        const id = ++this._requestId;
        this._pending[id] = { resolve, reject };

        window.postMessage({
          source: 'wcaht-dapp',
          id,
          method,
          params,
        }, '*');

        // Timeout after 60s
        setTimeout(() => {
          if (this._pending[id]) {
            delete this._pending[id];
            reject(new Error('Request timed out'));
          }
        }, 60000);
      });
    }

    // ── Public API ───────────────────────────────────────────────────────
    async connect() {
      const resp = await this._request('connect', {});
      if (resp.error) throw new Error(resp.error);
      this.publicKey = resp.publicKey;
      this.addressType = resp.addressType || 'native-ed25519';
      this.evmAddress = resp.evmAddress || null;
      this.address = this.evmAddress || this.publicKey;
      this.isConnected = true;
      this._emit('connect', { address: this.address, publicKey: this.publicKey, addressType: this.addressType, evmAddress: this.evmAddress });
      return { address: this.address, publicKey: this.publicKey, addressType: this.addressType, evmAddress: this.evmAddress };
    }

    async disconnect() {
      await this._request('disconnect', {});
      this.publicKey = null;
      this.address = null;
      this.addressType = 'native-ed25519';
      this.evmAddress = null;
      this.isConnected = false;
      this._emit('disconnect');
    }

    async getBalance(address) {
      const resp = await this._request('getBalance', { address });
      if (resp.error) throw new Error(resp.error);
      return resp.balance;
    }

    async sendTransaction(to, amountWcaht) {
      const amountKak = Math.round(amountWcaht * 1_000_000_000);
      const resp = await this._request('sendTransaction', { to, amount: amountKak });
      if (resp.error) throw new Error(resp.error);
      return {
        txHash: resp.txHash,
        signature: resp.signature,
      };
    }

    async getNodeStatus() {
      const resp = await this._request('getNodeStatus', {});
      if (resp.error) throw new Error(resp.error);
      return resp;
    }
  }

  const provider = new WcahtProvider();

  // Listen for responses from content script
  window.addEventListener('message', (event) => {
    if (event.source !== window) return;
    if (!event.data || event.data.source !== 'wcaht-extension') return;

    const { id, result } = event.data;
    const pending = provider._pending[id];
    if (pending) {
      delete provider._pending[id];
      pending.resolve(result);
    }
  });

  // Expose provider
  window.wcaht = provider;

  // Announce availability
  window.dispatchEvent(new Event('wcaht#initialized'));
})();
