/**
 * CurrencyManager.js
 * Manages the single in-game currency: Gold.
 * Simplified from the original multi-currency system (monetization-lite).
 * Provides add/spend/get operations with EventBus notifications,
 * StorageManager persistence, and overflow protection.
 */

/** Maximum gold cap to prevent overflow. */
const MAX_GOLD = 999999;

class CurrencyManager {
  constructor() {
    this._gold = 0;
    this._load();
  }

  // ============================================================
  // Persistence
  // ============================================================

  /**
   * Load currency data from StorageManager.
   * @private
   */
  _load() {
    try {
      if (GameGlobal && GameGlobal.storageManager) {
        const data = GameGlobal.storageManager.get('currency', null);
        if (data) {
          this._gold = data.gold || 0;
        }
      }
    } catch (e) {
      console.warn('[CurrencyManager] Failed to load currency data:', e);
    }
  }

  /**
   * Save currency data to StorageManager.
   * @private
   */
  _save() {
    try {
      if (GameGlobal && GameGlobal.storageManager) {
        GameGlobal.storageManager.set('currency', {
          gold: this._gold,
        });
      }
    } catch (e) {
      console.warn('[CurrencyManager] Failed to save currency data:', e);
    }
  }

  /**
   * Emit a currency change event via EventBus.
   * @private
   */
  _emitGoldChanged() {
    try {
      if (GameGlobal && GameGlobal.eventBus) {
        GameGlobal.eventBus.emit('currency:gold:changed', this._gold);
      }
    } catch (e) {}
  }

  // ============================================================
  // Gold
  // ============================================================

  /**
   * Get current gold amount.
   * @returns {number}
   */
  getGold() {
    return this._gold;
  }

  /**
   * Add gold (capped at MAX_GOLD).
   * @param {number} amount - Must be positive.
   * @returns {number} Actual amount added (may be less if capped).
   */
  addGold(amount) {
    if (amount <= 0) return 0;
    const before = this._gold;
    this._gold = Math.min(this._gold + Math.floor(amount), MAX_GOLD);
    const added = this._gold - before;
    if (added > 0) {
      this._save();
      this._emitGoldChanged();
    }
    return added;
  }

  /**
   * Spend gold.
   * @param {number} amount - Must be positive.
   * @returns {boolean} True if successful, false if insufficient.
   */
  spendGold(amount) {
    if (amount <= 0) return true;
    if (this._gold < amount) {
      // Emit insufficient event for UI to handle
      try {
        if (GameGlobal && GameGlobal.eventBus) {
          GameGlobal.eventBus.emit('currency:gold:insufficient', { required: amount, current: this._gold });
        }
      } catch (e) {}
      return false;
    }
    this._gold -= Math.floor(amount);
    this._save();
    this._emitGoldChanged();
    return true;
  }

  /**
   * Check if player has enough gold.
   * @param {number} amount
   * @returns {boolean}
   */
  hasGold(amount) {
    return this._gold >= amount;
  }

  /**
   * Check if gold is at maximum cap.
   * @returns {boolean}
   */
  isGoldFull() {
    return this._gold >= MAX_GOLD;
  }

  /**
   * Get the maximum gold cap.
   * @returns {number}
   */
  getMaxGold() {
    return MAX_GOLD;
  }

  // ============================================================
  // Cloud Sync
  // ============================================================

  /**
   * Get currency data for cloud sync.
   * @returns {object}
   */
  getCloudSyncData() {
    return {
      gold: this._gold,
    };
  }

  /**
   * Restore currency data from cloud (merge: keep higher values).
   * @param {object} cloudData
   */
  restoreFromCloud(cloudData) {
    if (!cloudData) return;

    if (cloudData.gold !== undefined && cloudData.gold > this._gold) {
      this._gold = Math.min(cloudData.gold, MAX_GOLD);
      this._save();
      this._emitGoldChanged();
    }
  }
}

module.exports = CurrencyManager;
