/**
 * Openfort Provider
 *
 * Creates embedded smart wallets for on-ramp users
 * using Openfort's account abstraction SDK.
 *
 * Docs: https://www.openfort.io/docs
 */

import Openfort from '@openfort/openfort-node';

export interface OpenfortConfig {
  apiKey: string;
  publishableKey: string;
  chainId: number;
}

export interface WalletInfo {
  playerId: string;
  accountId: string;
  address: string;
  chainId: number;
}

export class OpenfortProvider {
  private client: Openfort;
  private config: OpenfortConfig;

  constructor(config: OpenfortConfig) {
    this.config = config;
    this.client = new Openfort(config.apiKey);
  }

  /**
   * Find an existing wallet by player name, or create a new one.
   * Ensures one wallet per label (e.g. "user-alice@example.com").
   */
  async findOrCreateWallet(label: string, metadata?: Record<string, string>): Promise<WalletInfo> {
    try {
      // Search for existing player by name
      const existing = await this.client.players.list({ name: label, limit: 1 });
      if (existing.data.length > 0) {
        const player = existing.data[0];
        const accounts = await this.client.accounts.v1.list({
          player: player.id,
          chainId: this.config.chainId,
        });
        if (accounts.data.length > 0) {
          const account = accounts.data[0];
          console.log(`[openfort] Found existing wallet: player=${player.id} address=${account.address} label=${label}`);
          return {
            playerId: player.id,
            accountId: account.id,
            address: account.address,
            chainId: this.config.chainId,
          };
        }
        // Player exists but no account on this chain — create one
        const account = await this.client.accounts.v1.create({
          player: player.id,
          chainId: this.config.chainId,
        });
        console.log(`[openfort] Created account for existing player: player=${player.id} address=${account.address}`);
        return {
          playerId: player.id,
          accountId: account.id,
          address: account.address,
          chainId: this.config.chainId,
        };
      }

      // No existing player — create new
      const player = await this.client.players.create({
        name: label,
        metadata: metadata ?? {},
      });

      const account = await this.client.accounts.v1.create({
        player: player.id,
        chainId: this.config.chainId,
      });

      console.log(`[openfort] Created new wallet: player=${player.id} address=${account.address} label=${label}`);

      return {
        playerId: player.id,
        accountId: account.id,
        address: account.address,
        chainId: this.config.chainId,
      };
    } catch (error) {
      console.error(`[openfort] Failed to find/create wallet for "${label}":`, error);
      throw error;
    }
  }

  /**
   * @deprecated Use findOrCreateWallet instead
   */
  async createWallet(label: string, metadata?: Record<string, string>): Promise<WalletInfo> {
    return this.findOrCreateWallet(label, metadata);
  }
}
