/* ==========================================================================
   PrimeBridge Entropy Tracker Module
   ==========================================================================
   Prevents repetitive patterns in generated notifications by tracking
   recently used names, countries, amounts, and payment methods.
   Improves realism by ensuring natural-looking diversity.
   ========================================================================== */

(function () {
  'use strict';

  /* ------------------------------------------------------------------ */
  /*  CONFIGURATION                                                       */
  /* ------------------------------------------------------------------ */

  var DEFAULTS = {
    nameWindow:    12,  // track last 12 user names
    countryWindow: 8,   // track last 8 countries
    amountWindow:  6,   // track last 6 amounts
    methodWindow:  5    // track last 5 payment methods
  };

  /* ------------------------------------------------------------------ */
  /*  INTERNAL STATE                                                      */
  /* ------------------------------------------------------------------ */

  var _history = {
    name:    [],
    country: [],
    amount:  [],
    method:  []
  };

  var _windows = {
    name:    DEFAULTS.nameWindow,
    country: DEFAULTS.countryWindow,
    amount:  DEFAULTS.amountWindow,
    method:  DEFAULTS.methodWindow
  };

  var _eventCount = 0;

  /* ------------------------------------------------------------------ */
  /*  HELPERS                                                             */
  /* ------------------------------------------------------------------ */

  /** Return the last `count` items from an array. */
  function _last(arr, count) {
    return arr.slice(-count);
  }

  /** Check if a value appears in an array (case-insensitive for strings). */
  function _contains(arr, value) {
    for (var i = 0; i < arr.length; i++) {
      var a = typeof arr[i] === 'string' ? arr[i].toLowerCase() : arr[i];
      var b = typeof value === 'string' ? value.toLowerCase() : value;
      if (a === b) return true;
    }
    return false;
  }

  /** Pick a random element from an array. */
  function _pickRandom(arr) {
    return arr[Math.floor(Math.random() * arr.length)];
  }

  /**
   * Check if an amount string looks "natural" — i.e., not too round.
   * Round amounts like "$5,000" or "$10,000" look generated.
   * @param {string} amountStr - e.g. "$5,234"
   * @returns {boolean} True if the amount passes entropy checks
   */
  function _validateAmount(amountStr) {
    if (!amountStr) return false;
    // Strip currency symbols and commas
    var num = parseFloat(amountStr.replace(/[^0-9.]/g, ''));
    if (isNaN(num)) return true;

    // Reject amounts ending in "00" (too round)
    if (num >= 100 && num % 100 === 0) return false;

    // Reject amounts ending in "000" (very round)
    if (num >= 1000 && num % 1000 === 0) return false;

    // Reject amounts ending in "50" or "500" (suspicious)
    if (num >= 100 && (num % 100 === 50 || num % 1000 === 500)) {
      // But allow them occasionally (30% chance — keeps realism)
      return Math.random() > 0.3;
    }

    return true;
  }

  /* ------------------------------------------------------------------ */
  /*  API                                                                */
  /* ------------------------------------------------------------------ */

  window.PrimeBridge = window.PrimeBridge || {};
  PrimeBridge.entropy = {

    /**
     * Record a value so the tracker knows not to repeat it soon.
     * @param {string} category - 'name', 'country', 'amount', or 'method'
     * @param {*} value - The value to record
     */
    record: function (category, value) {
      if (!_history[category]) return;
      _history[category].push(value);
      // Keep only the last N entries
      var limit = _windows[category] || 20;
      if (_history[category].length > limit) {
        _history[category].shift();
      }
    },

    /**
     * Record an entire event's data in one call.
     * @param {Object} event - { user, country, amount, method }
     */
    recordEvent: function (event) {
      _eventCount++;
      if (event.user)        this.record('name', event.user);
      if (event.country)     this.record('country', event.country);
      if (event.amount)      this.record('amount', event.amount);
      if (event.method)      this.record('method', event.method);
    },

    /**
     * Check if a value would be a "safe" choice — not recently seen.
     * @param {string} category
     * @param {*} value
     * @returns {boolean}
     */
    check: function (category, value) {
      if (!_history[category]) return true;
      return !_contains(_history[category], value);
    },

    /**
     * From a list of candidates, pick one that passes the entropy check.
     * If none passes, picks the least-recently-used one.
     * @param {string} category
     * @param {Array} candidates - Array of possible values
     * @returns {*} The chosen value, or null if candidates is empty
     */
    pick: function (category, candidates) {
      if (!candidates || candidates.length === 0) return null;

      // First pass — find values not recently used
      var fresh = [];
      for (var i = 0; i < candidates.length; i++) {
        if (this.check(category, candidates[i])) {
          fresh.push(candidates[i]);
        }
      }

      // If we have fresh choices, pick randomly
      if (fresh.length > 0) return _pickRandom(fresh);

      // Otherwise return a random candidate (we'll record it and move on)
      return _pickRandom(candidates);
    },

    /**
     * Validate and "de-round" an amount string.
     * If the amount is too round (e.g., "$5,000"), adds random variation.
     * @param {string} amountStr - e.g. "$5,000"
     * @returns {string} A more natural-looking amount
     */
    naturalizeAmount: function (amountStr) {
      if (!amountStr) return amountStr;
      if (_validateAmount(amountStr)) return amountStr;

      // Deround: add random offset ($13-$87)
      var num = parseFloat(amountStr.replace(/[^0-9.]/g, ''));
      if (isNaN(num)) return amountStr;

      var offset = Math.floor(13 + Math.random() * 75);
      // Randomly add or subtract
      if (Math.random() > 0.5 && num > offset + 100) {
        num -= offset;
      } else {
        num += offset;
      }

      // Format back: "$X,XXX"
      var formatted = '$' + num.toLocaleString('en-US', {
        minimumFractionDigits: 0,
        maximumFractionDigits: 0
      });
      return formatted;
    },

    /**
     * Get a weighted country distribution to avoid repeating the same
     * country too frequently. Countries with fewer recent appearances
     * get higher weight.
     * @param {Array} countries - Array of country objects with .name field
     * @returns {Object} The chosen country
     */
    pickWeightedCountry: function (countries) {
      if (!countries || countries.length === 0) return null;

      // Score each country: lower score = better pick
      var scored = [];
      var recent = _last(_history.country, _windows.country);

      for (var i = 0; i < countries.length; i++) {
        var c = countries[i];
        var recencyPenalty = 0;

        // Count how many of the last N notifications used this country
        for (var j = 0; j < recent.length; j++) {
          if (typeof recent[j] === 'string' &&
              recent[j].toLowerCase() === (c.name || c).toLowerCase()) {
            // Recent appearances get heavier penalty
            recencyPenalty += (recent.length - j) * 2;
          }
        }

        scored.push({
          country: c,
          score: recencyPenalty
        });
      }

      // Sort by score ascending (lowest penalty = best choice)
      scored.sort(function (a, b) { return a.score - b.score; });

      // Pick from the top 40% (randomized within them)
      var topN = Math.max(1, Math.ceil(scored.length * 0.4));
      var choice = Math.floor(Math.random() * topN);
      return scored[choice].country;
    },

    /**
     * Get the total number of events generated.
     * @returns {number}
     */
    getEventCount: function () {
      return _eventCount;
    },

    /**
     * Get the current state (for debugging via console).
     * @returns {Object}
     */
    getState: function () {
      return {
        history: {
          name:    _history.name.slice(),
          country: _history.country.slice(),
          amount:  _history.amount.slice(),
          method:  _history.method.slice()
        },
        windows: { name: _windows.name, country: _windows.country, amount: _windows.amount, method: _windows.method },
        eventCount: _eventCount
      };
    },

    /**
     * Reset all tracked state (useful for testing).
     */
    reset: function () {
      _history = { name: [], country: [], amount: [], method: [] };
      _eventCount = 0;
    }
  };
})();
