/**
 * PaymentManager.js
 * Simplified payment manager for monetization-lite.
 * Only 3 products: Ad-Free (¥18), Gold Pack (¥6=1000g), Newcomer Pack (¥1=500g).
 * Handles WeChat payment, order recovery, and newcomer pack 24h timer.
 */

/** Product definitions. */
const PRODUCTS = {
  AD_FREE: {
    id: 'ad_free',
    price: 18,       // ¥18
    name: 'Remove Ads (Permanent)',
    type: 'permanent',
  },
  GOLD_PACK: {
    id: 'gold_pack',
    price: 6,        // ¥6
    goldAmount: 1000,
    name: 'Gold Pack',
    type: 'consumable',
  },
  NEWCOMER_PACK: {
    id: 'newcomer_pack',
    price: 1,        // ¥1
    goldAmount: 500,
    name: 'Newcomer Pack',
    type: 'one_time',
  },
};

/** Newcomer pack availability window in milliseconds (24 hours). */
const NEWCOMER_WINDOW_MS = 24 * 60 * 60 * 1000;

class PaymentManager {
  constructor() {
    this._adFreePurchased = false;
    this._newcomerPackPurchased = false;
    this._newcomerPackStartTime = 0; // timestamp when user first entered game
    this._pendingOrders = [];

    this._load();
  }

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

  /**
   * Load payment state from StorageManager.
   * @private
   */
  _load() {
    try {
      if (GameGlobal && GameGlobal.storageManager) {
        const data = GameGlobal.storageManager.get('payment', null);
        if (data) {
          this._adFreePurchased = data.adFreePurchased || false;
          this._newcomerPackPurchased = data.newcomerPackPurchased || false;
          this._newcomerPackStartTime = data.newcomerPackStartTime || 0;
          this._pendingOrders = data.pendingOrders || [];
        }

        // Initialize newcomer pack timer on first load
        if (this._newcomerPackStartTime === 0) {
          this._newcomerPackStartTime = Date.now();
          this._save();
        }
      }
    } catch (e) {
      console.warn('[PaymentManager] Failed to load payment data:', e);
    }

    // Try to recover any pending orders
    this._recoverPendingOrders();
  }

  /**
   * Save payment state to StorageManager.
   * @private
   */
  _save() {
    try {
      if (GameGlobal && GameGlobal.storageManager) {
        GameGlobal.storageManager.set('payment', {
          adFreePurchased: this._adFreePurchased,
          newcomerPackPurchased: this._newcomerPackPurchased,
          newcomerPackStartTime: this._newcomerPackStartTime,
          pendingOrders: this._pendingOrders,
        });
      }
    } catch (e) {
      console.warn('[PaymentManager] Failed to save payment data:', e);
    }
  }

  // ============================================================
  // Purchase API
  // ============================================================

  /**
   * Purchase the ad-free privilege (¥18, permanent).
   * @param {Function} callback - Called with { success: boolean, error?: string }.
   */
  purchaseAdFree(callback) {
    if (this._adFreePurchased) {
      if (callback) callback({ success: false, error: 'Already purchased' });
      return;
    }

    this._requestPayment(PRODUCTS.AD_FREE, (result) => {
      if (result.success) {
        this._adFreePurchased = true;
        this._save();

        // Enable ad-free in AdManager
        if (GameGlobal.adManager) {
          GameGlobal.adManager.enableAdFree();
        }

        // Emit event
        this._emitPurchaseEvent('ad_free');
      }
      if (callback) callback(result);
    });
  }

  /**
   * Purchase a gold pack (¥6 = 1000 gold).
   * @param {Function} callback - Called with { success: boolean, error?: string }.
   */
  purchaseGoldPack(callback) {
    this._requestPayment(PRODUCTS.GOLD_PACK, (result) => {
      if (result.success) {
        // Award gold
        if (GameGlobal.currencyManager) {
          GameGlobal.currencyManager.addGold(PRODUCTS.GOLD_PACK.goldAmount);
        }
        this._emitPurchaseEvent('gold_pack');
      }
      if (callback) callback(result);
    });
  }

  /**
   * Purchase the newcomer pack (¥1 = 500 gold, one-time only).
   * @param {Function} callback - Called with { success: boolean, error?: string }.
   */
  purchaseNewcomerPack(callback) {
    if (this._newcomerPackPurchased) {
      if (callback) callback({ success: false, error: 'Already purchased' });
      return;
    }

    if (!this.isNewcomerPackAvailable()) {
      if (callback) callback({ success: false, error: 'Newcomer pack expired' });
      return;
    }

    this._requestPayment(PRODUCTS.NEWCOMER_PACK, (result) => {
      if (result.success) {
        this._newcomerPackPurchased = true;
        this._save();

        // Award gold
        if (GameGlobal.currencyManager) {
          GameGlobal.currencyManager.addGold(PRODUCTS.NEWCOMER_PACK.goldAmount);
        }
        this._emitPurchaseEvent('newcomer_pack');
      }
      if (callback) callback(result);
    });
  }

  // ============================================================
  // Status Queries
  // ============================================================

  /**
   * Whether ad-free has been purchased.
   * @returns {boolean}
   */
  isAdFreePurchased() {
    return this._adFreePurchased;
  }

  /**
   * Whether the newcomer pack is still available (within 24h and not purchased).
   * @returns {boolean}
   */
  isNewcomerPackAvailable() {
    if (this._newcomerPackPurchased) return false;
    const elapsed = Date.now() - this._newcomerPackStartTime;
    return elapsed < NEWCOMER_WINDOW_MS;
  }

  /**
   * Get remaining time for newcomer pack in milliseconds.
   * @returns {number} Remaining ms, or 0 if expired.
   */
  getNewcomerPackRemainingMs() {
    if (this._newcomerPackPurchased) return 0;
    const remaining = NEWCOMER_WINDOW_MS - (Date.now() - this._newcomerPackStartTime);
    return Math.max(0, remaining);
  }

  /**
   * Get product definitions.
   * @returns {object}
   */
  getProducts() {
    return PRODUCTS;
  }

  // ============================================================
  // WeChat Payment
  // ============================================================

  /**
   * Request payment via WeChat Midas payment.
   * @param {object} product - Product definition.
   * @param {Function} callback - Called with { success: boolean, error?: string }.
   * @private
   */
  _requestPayment(product, callback) {
    // Add to pending orders for recovery
    const orderId = `${product.id}_${Date.now()}`;
    this._pendingOrders.push({ orderId, productId: product.id, timestamp: Date.now() });
    this._save();

    try {
      if (typeof wx === 'undefined' || typeof wx.requestMidasPayment !== 'function') {
        // Dev environment: simulate success
        console.log(`[PaymentManager] Dev mode: simulating purchase of ${product.id}`);
        this._removePendingOrder(orderId);
        if (callback) callback({ success: true });
        return;
      }

      wx.requestMidasPayment({
        mode: 'game',
        env: 0, // 0 = production, 1 = sandbox
        offerId: '', // Replace with actual offer ID
        currencyType: 'CNY',
        buyQuantity: product.price * 10, // Midas uses 1/10 yuan units
        success: () => {
          console.log(`[PaymentManager] Purchase successful: ${product.id}`);
          this._removePendingOrder(orderId);
          if (callback) callback({ success: true });
        },
        fail: (err) => {
          console.warn(`[PaymentManager] Purchase failed: ${product.id}`, err);
          this._removePendingOrder(orderId);
          if (callback) callback({ success: false, error: err.errMsg || 'Payment failed' });
        },
      });
    } catch (e) {
      console.warn('[PaymentManager] Payment request error:', e);
      this._removePendingOrder(orderId);
      if (callback) callback({ success: false, error: e.message });
    }
  }

  /**
   * Remove a pending order after completion.
   * @param {string} orderId
   * @private
   */
  _removePendingOrder(orderId) {
    this._pendingOrders = this._pendingOrders.filter(o => o.orderId !== orderId);
    this._save();
  }

  /**
   * Attempt to recover pending orders (e.g., after network interruption).
   * @private
   */
  _recoverPendingOrders() {
    if (this._pendingOrders.length === 0) return;

    // Remove orders older than 1 hour (stale)
    const oneHourAgo = Date.now() - 60 * 60 * 1000;
    this._pendingOrders = this._pendingOrders.filter(o => o.timestamp > oneHourAgo);
    this._save();

    // In production, query server for order status and deliver items
    // For now, just log
    if (this._pendingOrders.length > 0) {
      console.log(`[PaymentManager] ${this._pendingOrders.length} pending orders to recover`);
    }
  }

  /**
   * Emit a purchase completed event.
   * @param {string} productId
   * @private
   */
  _emitPurchaseEvent(productId) {
    try {
      if (GameGlobal && GameGlobal.eventBus) {
        GameGlobal.eventBus.emit('purchase:completed', { productId });
      }
    } catch (e) {}
  }

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

  /**
   * Get payment data for cloud sync.
   * @returns {object}
   */
  getCloudSyncData() {
    return {
      adFreePurchased: this._adFreePurchased,
      newcomerPackPurchased: this._newcomerPackPurchased,
      newcomerPackStartTime: this._newcomerPackStartTime,
    };
  }

  /**
   * Restore payment data from cloud.
   * @param {object} cloudData
   */
  restoreFromCloud(cloudData) {
    if (!cloudData) return;
    let changed = false;

    // Ad-free is permanent — if cloud says purchased, trust it
    if (cloudData.adFreePurchased && !this._adFreePurchased) {
      this._adFreePurchased = true;
      if (GameGlobal.adManager) {
        GameGlobal.adManager.enableAdFree();
      }
      changed = true;
    }

    if (cloudData.newcomerPackPurchased && !this._newcomerPackPurchased) {
      this._newcomerPackPurchased = true;
      changed = true;
    }

    if (changed) {
      this._save();
    }
  }
}

PaymentManager.PRODUCTS = PRODUCTS;

module.exports = PaymentManager;
