import { ethers } from "ethers";
import { EventEmitter } from "events";
import { VENICE_TOKEN_ABI, VENICE_TOKEN_ADDRESS } from "./constants";

export interface TokenOperationResult {
  success: boolean;
  transactionHash?: string;
  error?: string;
  data?: any;
}

export class VeniceToken extends EventEmitter {
  private contract: ethers.Contract | null = null;
  private provider: ethers.Provider | null = null;
  private signer: ethers.Signer | null = null;
  private address: string;

  constructor(tokenAddress?: string) {
    super();
    this.address = tokenAddress || VENICE_TOKEN_ADDRESS;
  }

  /**
   * Initialize the token contract with provider and signer
   */
  public async initialize(provider: ethers.Provider, signer?: ethers.Signer): Promise<void> {
    this.provider = provider;
    
    if (signer) {
      this.signer = signer;
      this.contract = new ethers.Contract(
        this.address,
        VENICE_TOKEN_ABI,
        this.signer
      );
    } else {
      this.contract = new ethers.Contract(
        this.address,
        VENICE_TOKEN_ABI,
        this.provider
      );
    }
  }

  /**
   * Cleanup resources
   */
  public async cleanup(): Promise<void> {
    this.contract = null;
    this.provider = null;
    this.signer = null;
  }

  /**
   * Get token balance for an address
   */
  public async getBalance(address: string): Promise<TokenOperationResult> {
    try {
      if (!this.contract) {
        throw new Error("Contract not initialized");
      }

      const balance = await this.contract.balanceOf(address);
      
      return {
        success: true,
        data: balance
      };
    } catch (error) {
      return {
        success: false,
        error: error instanceof Error ? error.message : String(error)
      };
    }
  }

  /**
   * Check allowance for spender
   */
  public async getAllowance(owner: string, spender: string): Promise<TokenOperationResult> {
    try {
      if (!this.contract) {
        throw new Error("Contract not initialized");
      }

      const allowance = await this.contract.allowance(owner, spender);
      
      return {
        success: true,
        data: allowance
      };
    } catch (error) {
      return {
        success: false,
        error: error instanceof Error ? error.message : String(error)
      };
    }
  }

  /**
   * Approve spender to use tokens
   */
  public async approve(spender: string, amount: bigint): Promise<TokenOperationResult> {
    try {
      if (!this.contract || !this.signer) {
        throw new Error("Contract not initialized with signer");
      }

      const tx = await this.contract.approve(spender, amount, {
        gasLimit: 100000
      });
      const receipt = await tx.wait();

      return {
        success: true,
        transactionHash: receipt.hash
      };
    } catch (error) {
      return {
        success: false,
        error: error instanceof Error ? error.message : String(error)
      };
    }
  }
} 