/**
 * PrimeBridge Event Data Handler
 *
 * Loads and parses event data from a JSON file, providing a data layer
 * for the notification engine. Events are template-based with
 * placeholder substitution for generating realistic notifications.
 *
 * @namespace PrimeBridge.events
 * @version 1.0.0
 */

(function () {
  'use strict';

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

  /**
   * @type {Object}
   * @property {Array|null} _cache - Cached event templates loaded from JSON
   * @property {Function} loadEvents - Fetch and cache event data
   * @property {Function} getEventsByType - Filter cached events by type
   * @property {Function} getRandomEvent - Generate a random concrete event
   * @property {Function} getAllTypes - List all event types in cache
   * @property {Function} getEventCount - Count total cached templates
   * @property {Function} isLoaded - Check if data has been fetched
   */
  PrimeBridge.events = {
    /** @private */
    _cache: null,

    /**
     * Format a number as a currency string (e.g., "$1,234.00").
     * Drops decimals for whole amounts.
     *
     * @param {number} value - The numeric amount
     * @returns {string} Formatted currency string
     */
    _formatAmount: function (value) {
      if (Number.isInteger(value)) {
        return '$' + value.toLocaleString('en-US');
      }
      return '$' + value.toLocaleString('en-US', {
        minimumFractionDigits: 2,
        maximumFractionDigits: 2
      });
    },

    /**
     * Pick a random element from an array.
     *
     * @param {Array} arr - Source array
     * @returns {*} Random element, or null if array is empty
     */
    _pickRandom: function (arr) {
      if (!arr || arr.length === 0) {
        return null;
      }
      return arr[Math.floor(Math.random() * arr.length)];
    },

    /**
     * Generate a random integer between min and max (inclusive).
     *
     * @param {number} min - Minimum value
     * @param {number} max - Maximum value
     * @returns {number} Random integer in range
     */
    _randomInRange: function (min, max) {
      return Math.floor(Math.random() * (max - min + 1)) + min;
    },

    /**
     * Generate a random amount for display, using round numbers
     * that are multiples of common increments for realism.
     *
     * @param {number} min - Minimum amount
     * @param {number} max - Maximum amount
     * @returns {number} Realistic random amount
     */
    _generateAmount: function (min, max) {
      var raw = this._randomInRange(min, max);
      // Round to nice display values
      if (raw >= 1000) {
        raw = Math.round(raw / 100) * 100;
      } else if (raw >= 100) {
        raw = Math.round(raw / 10) * 10;
      }
      return Math.max(min, Math.min(max, raw));
    },

    /**
     * Substitute placeholders in a message template.
     *
     * Supported placeholders:
     *   {user}    — Random user name
     *   {amount}  — Random formatted amount
     *   {method}  — Random payment/trade method
     *   {country} — Random country
     *   {pair}    — Random trading pair (trading events)
     *   {profit}  — Random profit string (trading events)
     *   {position} — LONG or SHORT
     *   {leverage} — Leverage multiplier
     *
     * @param {string} template - Message template with placeholders
     * @param {Object} fields - Field values to substitute
     * @returns {string} Resolved message
     */
    _resolveTemplate: function (template, fields) {
      return template.replace(/\{(\w+)\}/g, function (match, key) {
        return fields[key] !== undefined ? fields[key] : match;
      });
    },

    /**
     * Generate a concrete, resolved event object from an event template.
     *
     * @param {Object} template - Event template definition
     * @returns {Object} Resolved event with substituted values
     */
    _generateEvent: function (template) {
      var user = this._pickRandom(template.users) || 'Anonymous Trader';
      var amount = this._generateAmount(template.amount.min, template.amount.max);
      var country = this._pickRandom(template.countries) || '';
      var method = this._pickRandom(template.methods) || '';

      /** @type {Object} */
      var fields = {
        user: user,
        amount: this._formatAmount(amount),
        country: country,
        method: method
      };

      // Trading-specific fields
      if (template.pairs) {
        fields.pair = this._pickRandom(template.pairs) || 'BTC/USDT';
      }
      if (template.profits) {
        fields.profit = this._pickRandom(template.profits) || '+10%';
      }
      if (template.positions) {
        fields.position = this._pickRandom(template.positions) || 'LONG';
      }
      if (template.leverages) {
        fields.leverage = this._pickRandom(template.leverages) || 1;
      }

      // Managed Portfolio fields
      if (template.packages) {
        fields.package = this._pickRandom(template.packages) || 'Balanced Growth';
      }

      // Sector Investment fields
      if (template.sectors) {
        fields.sector = this._pickRandom(template.sectors) || 'Technology';
      }

      // Capital Instruments fields
      if (template.instruments) {
        fields.instrument = this._pickRandom(template.instruments) || 'Corporate Bond';
      }

      return {
        type: template.type,
        title: this._resolveTemplate(template.title, fields) || template.title,
        message: this._resolveTemplate(template.message, fields),
        user: user,
        amount: this._formatAmount(amount),
        method: method,
        country: country,
        txnId: 'PB-' + 
          Math.random().toString(36).substring(2, 10).toUpperCase() + '-' +
          String(Date.now()).slice(-6)
      };
    },

    /**
     * Fetch and cache event data from a JSON URL.
     *
     * Fetches the events JSON file, parses it, and stores the resulting
     * template array in the internal cache. Supports a default path
     * relative to the site root.
     *
     * @param {string} [url='assets/data/live-events.json'] - URL to JSON file
     * @returns {Promise<Array>} Promise resolving to the cached event templates
     * @throws {Error} If fetch fails or response is not valid JSON
     *
     * @example
     * PrimeBridge.events.loadEvents()
     *   .then(function (events) { console.log(events.length); });
     *
     * @example
     * PrimeBridge.events.loadEvents('/custom/path/events.json')
     *   .then(function (events) { /* ... *\/ });
     */
    loadEvents: function (url) {
      url = url || 'assets/data/live-events.json';

      var self = this;

      return fetch(url)
        .then(function (response) {
          if (!response.ok) {
            throw new Error(
              'Failed to load events: ' + response.status + ' ' + response.statusText
            );
          }
          return response.json();
        })
        .then(function (data) {
          if (!Array.isArray(data)) {
            throw new Error('Events data must be an array of event templates');
          }
          self._cache = data;
          return self._cache;
        })
        .catch(function (err) {
          self._cache = null;
          console.error('[PrimeBridge.events] Error loading events:', err);
          throw err;
        });
    },

    /**
     * Return cached event templates, optionally filtered by type.
     *
     * @param {string} [type] - Event type to filter by
     * @returns {Array} Array of event templates (empty if not loaded or no match)
     *
     * @example
     * var deposits = PrimeBridge.events.getEventsByType('deposit');
     * var allEvents = PrimeBridge.events.getEventsByType();
     */
    getEventsByType: function (type) {
      if (!this._cache) {
        return [];
      }
      if (!type) {
        return this._cache;
      }
      return this._cache.filter(function (event) {
        return event.type === type;
      });
    },

    /**
     * Return a single randomly-generated event, optionally filtered by type.
     *
     * Selects a random event template from the cache (optionally filtered
     * by type) and generates a concrete event by substituting random
     * values for all template placeholders.
     *
     * @param {string} [type] - Event type filter
     * @returns {Object|null} A resolved event object with title, message,
     *                        user, amount, method, country; or null if
     *                        no templates are available
     *
     * @example
     * var event = PrimeBridge.events.getRandomEvent('trading');
     * // => { type: 'trading', title: 'Trade Closed',
     * //      message: 'Ethan Cole closed a BTC/USDT position with +18.4% profit',
     * //      user: 'Ethan Cole', amount: '$12,300', ... }
     */
    getRandomEvent: function (type) {
      var pool = type
        ? this.getEventsByType(type)
        : this._cache;

      if (!pool || pool.length === 0) {
        return null;
      }

      var template = this._pickRandom(pool);
      return this._generateEvent(template);
    },

    /**
     * Return an array of unique event type strings from the cached data.
     *
     * @returns {string[]} Sorted array of event types (empty if not loaded)
     *
     * @example
     * var types = PrimeBridge.events.getAllTypes();
     * // => ['bonus', 'deposit', 'registration', 'trading', 'withdrawal']
     */
    getAllTypes: function () {
      if (!this._cache) {
        return [];
      }

      var types = {};
      this._cache.forEach(function (event) {
        types[event.type] = true;
      });

      return Object.keys(types).sort();
    },

    /**
     * Return the total number of cached event templates.
     *
     * @returns {number} Template count (0 if not loaded)
     *
     * @example
     * var count = PrimeBridge.events.getEventCount();
     * // => 12
     */
    getEventCount: function () {
      if (!this._cache) {
        return 0;
      }
      return this._cache.length;
    },

    /**
     * Check whether event data has been fetched and cached.
     *
     * @returns {boolean} True if events data is available in memory
     *
     * @example
     * if (PrimeBridge.events.isLoaded()) {
     *   // ...
     * }
     */
    isLoaded: function () {
      return this._cache !== null;
    }
  };
})();
