import { db, ResellerWallet, ResellerLedgerEntry } from '../../database/db';

export class WalletService {
  /**
   * Top up a reseller's pre-paid wholesale wallet with atomic Row-Locking
   */
  public static async topupWallet(
    resellerId: string,
    amount: number,
    referenceId: string,
    description = 'Pre-Paid Wallet Credit'
  ): Promise<{ wallet: ResellerWallet; ledger: ResellerLedgerEntry }> {
    if (amount <= 0) {
      throw new Error('Top-up amount must be greater than zero');
    }

    return await db.withRowLock(`reseller_wallets:${resellerId}`, async () => {
      let wallet = db.reseller_wallets.find(w => w.reseller_id === resellerId);
      if (!wallet) {
        wallet = {
          id: `wallet_${Date.now()}_${Math.random().toString(36).substring(2, 6)}`,
          reseller_id: resellerId,
          balance: 0.0,
          currency: 'BDT',
          updated_at: new Date().toISOString()
        };
        db.reseller_wallets.push(wallet);
      }

      const balanceBefore = wallet.balance;
      const balanceAfter = Number((balanceBefore + amount).toFixed(2));
      wallet.balance = balanceAfter;
      wallet.updated_at = new Date().toISOString();

      const ledgerEntry: ResellerLedgerEntry = {
        id: `led_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`,
        reseller_id: resellerId,
        type: 'TOPUP',
        amount: Number(amount.toFixed(2)),
        balance_before: balanceBefore,
        balance_after: balanceAfter,
        reference_id: referenceId,
        description,
        created_at: new Date().toISOString()
      };

      db.reseller_ledger.unshift(ledgerEntry);
      db.logAudit('RESELLER', resellerId, 'WALLET_TOPUP_SUCCESS', {
        amount,
        balanceBefore,
        balanceAfter,
        referenceId
      });

      db.persist();
      return { wallet, ledger: ledgerEntry };
    });
  }

  /**
   * Atomic deduction of wholesale fee from reseller wallet during subscriber renewal
   * Strict Row-Level Locking (SELECT ... FOR UPDATE) ensures no negative balances under race conditions.
   */
  public static async deductWholesale(
    resellerId: string,
    amount: number,
    subscriberUsername: string,
    packageName: string
  ): Promise<{ success: boolean; balanceBefore: number; balanceAfter: number; ledgerId: string }> {
    return await db.withRowLock(`reseller_wallets:${resellerId}`, async () => {
      const wallet = db.reseller_wallets.find(w => w.reseller_id === resellerId);
      if (!wallet) {
        throw new Error(`Reseller wallet for '${resellerId}' not found.`);
      }

      if (wallet.balance < amount) {
        throw new Error(
          `Insufficient reseller pre-paid balance. Required: ৳${amount.toFixed(2)}, Available: ৳${wallet.balance.toFixed(2)}. Please recharge reseller wallet.`
        );
      }

      const balanceBefore = wallet.balance;
      const balanceAfter = Number((balanceBefore - amount).toFixed(2));
      wallet.balance = balanceAfter;
      wallet.updated_at = new Date().toISOString();

      const ledgerEntry: ResellerLedgerEntry = {
        id: `led_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`,
        reseller_id: resellerId,
        type: 'WHOLESALE_DEDUCTION',
        amount: Number(amount.toFixed(2)),
        balance_before: balanceBefore,
        balance_after: balanceAfter,
        reference_id: `SUB_RENEW_${subscriberUsername}`,
        description: `Wholesale Package Cost for Subscriber ${subscriberUsername} (${packageName})`,
        created_at: new Date().toISOString()
      };

      db.reseller_ledger.unshift(ledgerEntry);
      db.logAudit('SYSTEM', resellerId, 'WALLET_WHOLESALE_DEDUCTED', {
        subscriberUsername,
        packageName,
        amount,
        balanceAfter
      });

      db.persist();
      return {
        success: true,
        balanceBefore,
        balanceAfter,
        ledgerId: ledgerEntry.id
      };
    });
  }

  /**
   * Returns wallet details, ledger statements, and profit margins for a reseller
   */
  public static getWalletSummary(resellerId: string) {
    const wallet = db.reseller_wallets.find(w => w.reseller_id === resellerId);
    const ledger = db.reseller_ledger.filter(l => l.reseller_id === resellerId);
    const reseller = db.resellers.find(r => r.id === resellerId);
    const subscribers = db.subscribers.filter(s => s.reseller_id === resellerId);

    return {
      reseller,
      wallet: wallet || { balance: 0, currency: 'BDT' },
      ledger,
      totalSubscribers: subscribers.length,
      activeSubscribers: subscribers.filter(s => s.status === 'active').length,
      expiredSubscribers: subscribers.filter(s => s.status === 'expired').length
    };
  }
}
