import { JsonRpcProvider, Contract } from 'ethers';
import { CouponDetail, CouponHolding } from '../types';
import { COUPON_ABI, COUPON_FACTORY_ABI, COUPON_ADDRESS, COUPON_FACTORY_ADDRESS } from '../contracts/abis';

export class CouponModule {
  private coupon: Contract;
  private factory: Contract;

  constructor(provider: JsonRpcProvider) {
    this.coupon = new Contract(COUPON_ADDRESS, COUPON_ABI, provider);
    this.factory = new Contract(COUPON_FACTORY_ADDRESS, COUPON_FACTORY_ABI, provider);
  }

  async getDetail(tokenId: bigint): Promise<CouponDetail> {
    const [config, resaleCount, owner, redeemed] = await Promise.all([
      this.coupon.getConfig(tokenId),
      this.coupon.getResaleCount(tokenId),
      this.coupon.ownerOf(tokenId),
      this.coupon.isRedeemed(tokenId),
    ]);

    return {
      tokenId: tokenId.toString(),
      faceValue: config.faceValue.toString(),
      couponType: Number(config.couponType) === 0 ? 'utility' : 'security',
      expiryDate: new Date(Number(config.expiryDate) * 1000).toISOString(),
      resaleCount: Number(resaleCount),
      maxResaleCount: Number(config.maxResaleCount),
      transferable: config.transferable,
      issuer: config.issuer,
      redeemed,
    };
  }

  async getHoldings(address: string): Promise<CouponHolding[]> {
    const balance = Number(await this.coupon.balanceOf(address));
    const holdings: CouponHolding[] = [];

    for (let i = 0; i < balance && i < 100; i++) {
      const tokenId = await this.coupon.tokenOfOwnerByIndex(address, i);
      const detail = await this.getDetail(tokenId);
      holdings.push({ tokenId: tokenId.toString(), batchId: '0', detail });
    }

    return holdings;
  }

  async getResaleCount(tokenId: bigint): Promise<number> {
    return Number(await this.coupon.getResaleCount(tokenId));
  }

  async isExpired(tokenId: bigint): Promise<boolean> {
    const config = await this.coupon.getConfig(tokenId);
    return Date.now() / 1000 > Number(config.expiryDate);
  }
}
