import { Codex } from '@codex-data/sdk';
import {
  getEVMWalletBalance,
  getSolanaTokenBalances,
  getPortfolioTokens,
  getTokenUSDPrice,
  isValidSolanaOrEvMaddreess,
  searchToken,
  searchTokenByAddress,
  Token,
  TokenBalanceResults,
  TokenPrice,
  getTokenInfo,
} from '@shogun-sdk/money-legos';
import { Balance } from '../lib/codex.js';

/**
 * Client for interacting with Shogun balances API
 */
export class ShogunBalancesApiClient {
  public readonly sdk: Codex;

  constructor(apiKey: string) {
    this.sdk = new Codex(apiKey);
  }

  /**
   * Get EVM wallet balances across multiple chains
   * @param address - Wallet address to check balances for
   */
  public async getEvmWalletBalance(address: string) {
    return getEVMWalletBalance(this.sdk, address);
  }

  /**
   * Get token balances with additional info like prices
   * @param data - Balance data from getEvmWalletBalance
   * @param walletAddress - Wallet address
   * @param fallbackTokens - Optional fallback tokens to include
   */
  public async getPortfolioTokens(
    data: Balance[],
    walletAddress: string,
    fallbackTokens?: {
      tokenIn?: Token | null;
      tokenOut?: Token | null;
    },
  ): Promise<TokenBalanceResults[]> {
    return getPortfolioTokens(this.sdk, data, walletAddress, fallbackTokens);
  }

  /**
   * Search for a token by symbol or address
   * @param symbolOrAddress - Symbol or address to search for
   */
  public async searchToken(symbolOrAddress: string) {
    return searchToken(this.sdk, symbolOrAddress);
  }

  /**
   * Get Solana token balances for a wallet
   * @param walletAddress - Solana wallet address
   */
  public async getSolanaTokenBalances(walletAddress: string): Promise<TokenBalanceResults[]> {
    return getSolanaTokenBalances(this.sdk, walletAddress);
  }

  /**
   * Get USD price for a token
   * @param tokenAddress - Token address
   * @param chainId - Chain ID the token is on
   */
  public async getTokenUSDPrice(tokenAddress: string, chainId: number): Promise<TokenPrice | null> {
    return getTokenUSDPrice(this.sdk, tokenAddress, chainId);
  }

  /**
   * Validate if an address is a valid Solana or EVM address
   * @param address - Address to validate
   */
  public isValidAddress(address: string): boolean {
    return isValidSolanaOrEvMaddreess(address);
  }

  /**
   * Search for a token by address
   * @param options - Options for the search
   */
  public async searchTokenByAddress(options: { addresses: string[]; network?: number[] }) {
    return searchTokenByAddress(this.sdk, options);
  }

  public async getTokenInfo(tokenAddress: string, chainId: number) {
    return getTokenInfo(this.sdk, tokenAddress, chainId);
  }
}
