/* ==========================================================================
   PrimeBridge Payment Methods Module
   ==========================================================================
   Strict schema enforcement for payment methods on PrimeBridge.
   Every method defines exactly what fields it can produce — no mixing.

   **PAYMENT METHOD FIELD RULES (IMMUTABLE):**
     NOWPayments (crypto)  → wallet address (masked) ONLY
     PayPal                → masked email ONLY
     Paystack (deposit)    → card number (masked) ONLY
     Paystack (withdrawal) → bank name, account name, masked acct number
     Razorpay (deposit)    → card number (masked) ONLY
     Razorpay (withdrawal) → bank name, account name, masked acct number
   ========================================================================== */

(function () {
  'use strict';

  /* ------------------------------------------------------------------ */
  /*  HELPER: mask a string                                              */
  /* ------------------------------------------------------------------ */
  function _mask(str, keepStart, keepEnd) {
    keepEnd = keepEnd || 0;
    if (!str || str.length <= keepStart + keepEnd + 1) return str;
    var visibleStart = str.slice(0, keepStart);
    var visibleEnd = keepEnd > 0 ? str.slice(-keepEnd) : '';
    return visibleStart + str.slice(keepStart, keepStart + (str.length - keepStart - keepEnd)).replace(/./g, '*') + visibleEnd;
  }

  /* ------------------------------------------------------------------ */
  /*  GENERATORS                                                         */
  /* ------------------------------------------------------------------ */

  /** Generate a fake PayPal email — masked local part, full domain */
  function _genPaypalEmail(identity) {
    if (identity && identity.email) {
      var atIndex = identity.email.indexOf('@');
      return _mask(identity.email.slice(0, atIndex), 4, 0) + identity.email.slice(atIndex);
    }
    var firstNames = ['james', 'helen', 'maria', 'john', 'sarah', 'david', 'emma', 'michael',
                      'linda', 'robert', 'alex', 'amina', 'wei', 'carlos', 'fatima', 'peter',
                      'grace', 'daniel', 'sophia', 'victor'];
    var domains = ['gmail.com', 'outlook.com', 'yahoo.com', 'proton.me', 'icloud.com', 'hotmail.com'];
    var name = firstNames[Math.floor(Math.random() * firstNames.length)];
    var domain = domains[Math.floor(Math.random() * domains.length)];
    var rawEmail = name + Math.floor(Math.random() * 9999) + '@' + domain;
    var atIndex = rawEmail.indexOf('@');
    return _mask(rawEmail.slice(0, atIndex), 4, 0) + rawEmail.slice(atIndex);
  }

  /** Generate a masked card number */
  function _genCardNumber() {
    var last4 = String(Math.floor(1000 + Math.random() * 9000));
    return '**** **** **** ' + last4;
  }

  /** Generate bank account details for card-method withdrawals */
  function _genBankAccount(identity) {
    var banks = ['GTBank', 'Access Bank', 'Zenith Bank', 'First Bank', 'UBA', 'Fidelity Bank',
                 'Stanbic IBTC', 'Polaris Bank', 'Union Bank', 'Ecobank', 'FCMB', 'Wema Bank'];
    var names = ['Michael Okafor', 'Sarah Obi', 'Chidera Eze', 'Fatima Bello', 'Emeka Nwosu',
                 'Grace Okonkwo', 'David Adeleke', 'Amina Suleiman', 'Peter Ogunlade', 'Chioma Nnamdi'];
    var accountNumber = String(Math.floor(1000000000 + Math.random() * 9000000000));
    return {
      bankName: banks[Math.floor(Math.random() * banks.length)],
      accountName: (identity && identity.fullName) ? identity.fullName : names[Math.floor(Math.random() * names.length)],
      accountNumber: _mask(accountNumber, 0, 4) // "******4827"
    };
  }

  /** Generate a masked crypto wallet address */
  function _genWallet() {
    var types = [
      function () {
        var raw = 'bc1q' + Math.random().toString(36).substring(2, 14) + Math.random().toString(36).substring(2, 6);
        return _mask(raw, 5, 4);
      },
      function () {
        var raw = '0x' + Math.random().toString(16).substring(2, 14) + Math.random().toString(16).substring(2, 6);
        return _mask(raw, 4, 4);
      },
      function () {
        var raw = 'T' + Math.random().toString(36).substring(2, 16).toUpperCase();
        return _mask(raw, 4, 4);
      }
    ];
    return types[Math.floor(Math.random() * types.length)]();
  }

  /* ------------------------------------------------------------------ */
  /*  REGION MAPPING                                                      */
  /* ------------------------------------------------------------------ */
  // Country → continent/region for payment method selection
  var REGIONS = {
    africa: ['NG', 'GH', 'KE', 'ZA', 'UG', 'TZ'],
    europe: ['GB', 'DE', 'FR', 'IT', 'ES', 'NL', 'CH', 'SE', 'NO', 'DK', 'FI', 'BE', 'AT', 'IE', 'PT', 'PL'],
    asia:   ['JP', 'CN', 'KR', 'SG', 'MY', 'TH', 'VN', 'PH', 'ID', 'IN', 'PK', 'BD', 'LK', 'NP'],
    americas: ['US', 'CA', 'MX', 'BR', 'AR', 'CL', 'CO', 'PE']
  };

  function _continent(countryCode) {
    for (var c in REGIONS) {
      if (REGIONS[c].indexOf(countryCode) !== -1) return c;
    }
    return 'europe'; // default
  }

  // Region → allowed payment methods (method IDs)
  var REGION_METHODS = {
    africa:   ['paystack', 'stripe', 'paypal', 'nowpayments'],
    europe:   ['stripe', 'paypal', 'nowpayments'],
    asia:     ['stripe', 'paypal', 'nowpayments', 'razorpay'],
    americas: ['stripe', 'paypal', 'nowpayments']
  };

  /* ------------------------------------------------------------------ */
  /*  STRICT METHOD SCHEMAS                                              */
  //
  //
  // Each method defines:
  //   - name              — Display name
  //   - allowedDeposit    — { key: label } pairs for deposit modals
  //   - allowedWithdrawal — { key: label } pairs for withdrawal modals
  //   - generate(eventType) — Produce the correct fields for the given event type
  //

  var METHODS = {};

  METHODS.paypal = {
    id: 'paypal',
    name: 'PayPal',
    allowedDeposit: { email: 'EMAIL' },
    allowedWithdrawal: { email: 'EMAIL' },
    generate: function (eventType, identity) {
      return { email: _genPaypalEmail(identity) };
    }
  };

  METHODS.paystack = {
    id: 'paystack',
    name: 'Paystack',
    allowedDeposit: { card: 'CARD' },
    allowedWithdrawal: { bankName: 'BANK', accountName: 'ACCOUNT NAME', accountNumber: 'ACCOUNT NO' },
    generate: function (eventType, identity) {
      if (eventType === 'withdrawal') {
        var bank = _genBankAccount(identity);
        return { bankName: bank.bankName, accountName: bank.accountName, accountNumber: bank.accountNumber };
      }
      return { card: _genCardNumber() };
    }
  };

  METHODS.nowpayments = {
    id: 'nowpayments',
    name: 'NOWPayments',
    allowedDeposit: { network: 'NETWORK', wallet: 'WALLET ADDRESS' },
    allowedWithdrawal: { network: 'NETWORK', wallet: 'WALLET ADDRESS' },
    generate: function (eventType, identity) {
      var networks = ['BTC', 'ETH', 'TRX', 'BNB', 'SOL'];
      var wallets = {
        BTC: function () { return _mask('bc1q' + Math.random().toString(36).substring(2, 18), 6, 4); },
        ETH: function () { return _mask('0x' + Math.random().toString(16).substring(2, 18), 4, 4); },
        TRX: function () { return _mask('T' + Math.random().toString(36).substring(2, 18).toUpperCase(), 4, 4); },
        BNB: function () { return _mask('bnb1' + Math.random().toString(36).substring(2, 18), 6, 4); },
        SOL: function () { return _mask('' + Math.random().toString(36).substring(2, 14) + Math.random().toString(36).substring(2, 10), 4, 4); }
      };
      var net = networks[Math.floor(Math.random() * networks.length)];
      return { network: net, wallet: wallets[net]() };
    }
  };

  METHODS.razorpay = {
    id: 'razorpay',
    name: 'Razorpay',
    allowedDeposit: { card: 'CARD' },
    allowedWithdrawal: { bankName: 'BANK', accountName: 'ACCOUNT NAME', accountNumber: 'ACCOUNT NO' },
    generate: function (eventType, identity) {
      if (eventType === 'withdrawal') {
        var bank = _genBankAccount(identity);
        return { bankName: bank.bankName, accountName: bank.accountName, accountNumber: bank.accountNumber };
      }
      return { card: _genCardNumber() };
    }
  };

  METHODS.stripe = {
    id: 'stripe',
    name: 'Stripe',
    allowedDeposit: { card: 'CARD', cardType: 'CARD TYPE' },
    allowedWithdrawal: { bankName: 'BANK', accountName: 'ACCOUNT NAME', accountNumber: 'ACCOUNT NO' },
    generate: function (eventType, identity) {
      if (eventType === 'withdrawal') {
        var bank = _genBankAccount(identity);
        return { bankName: bank.bankName, accountName: bank.accountName, accountNumber: bank.accountNumber };
      }
      var cardTypes = ['Visa', 'Mastercard', 'Amex', 'Discover'];
      return { card: _genCardNumber(), cardType: cardTypes[Math.floor(Math.random() * cardTypes.length)] };
    }
  };

  /* ------------------------------------------------------------------ */
  /*  VALIDATOR                                                          */
  /* ------------------------------------------------------------------ */
  //
  // Checks that a generated data object only contains fields that the
  // method's schema allows.  If it finds a disallowed field → returns
  // an error array.  If pass → returns [].
  //
  function validate(methodId, eventType, data) {
    var m = METHODS[methodId];
    if (!m) return ['Unknown method: ' + methodId];

    var schema = (eventType === 'withdrawal') ? m.allowedWithdrawal : m.allowedDeposit;
    var allowedKeys = Object.keys(schema);
    var errors = [];

    for (var key in data) {
      if (data.hasOwnProperty && key === 'hasOwnProperty') continue;
      if (allowedKeys.indexOf(key) === -1 && data[key] !== undefined) {
        errors.push('Field "' + key + '" not allowed for ' + m.name + ' (' + eventType + ')');
      }
    }

    return errors;
  }

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

  var api = {

    /** @returns {Array} All available methods */
    getAll: function () {
      var keys = Object.keys(METHODS);
      return keys.map(function (k) { return METHODS[k]; });
    },

    /** @returns {string[]} All method IDs */
    getIds: function () {
      return Object.keys(METHODS);
    },

    /** @returns {Object|null} Method definition by id */
    getById: function (id) {
      return METHODS[id] || null;
    },

    /**
     * Pick a random payment method.
     * @returns {{ id: string, name: string }}
     */
    pickRandom: function () {
      var keys = Object.keys(METHODS);
      var m = METHODS[keys[Math.floor(Math.random() * keys.length)]];
      return { id: m.id, name: m.name };
    },

    /**
     * Pick a payment method suitable for a given country & event type.
     * Country → region → available methods.
     * @param {string} countryCode — ISO 3166-1 alpha-2 (e.g. 'NG', 'US')
     * @param {string} [eventType] — 'deposit' | 'withdrawal'
     * @returns {{ id: string, name: string }}
     */
    pickForCountry: function (countryCode, eventType) {
      var continent = _continent(countryCode);
      var allowedIds = REGION_METHODS[continent] || REGION_METHODS.europe;
      // Only Razorpay if country is India (IN)
      var filtered = allowedIds.filter(function (id) {
        if (id === 'razorpay' && countryCode !== 'IN') return false;
        return true;
      });
      var id = filtered[Math.floor(Math.random() * filtered.length)];
      var m = METHODS[id];
      return m ? { id: m.id, name: m.name } : this.pickRandom();
    },

    /**
     * Generate identifier data for a method, given the event type.
     * @param {string} methodId
     * @param {string} eventType — 'deposit' or 'withdrawal'
     * @param {Object} [identity] — User identity { fullName, email } for consistent naming
     * @returns {Object} Fields object (e.g. { card: '**** 4827' } or { bankName: 'GTBank', ... })
     */
    generateFields: function (methodId, eventType, identity) {
      var m = METHODS[methodId];
      if (!m) return {};
      return m.generate(eventType, identity);
    },

    /**
     * Build modal display rows for a payment method.
     * @param {string} methodId
     * @param {string} eventType
     * @param {Object} fields — Result from generateFields()
     * @returns {Array} e.g. [['METHOD', 'PayPal'], ['EMAIL', 'james****@gmail.com']]
     */
    getModalRows: function (methodId, eventType, fields) {
      var m = METHODS[methodId];
      if (!m) return [['METHOD', methodId]];

      var schema = (eventType === 'withdrawal') ? m.allowedWithdrawal : m.allowedDeposit;
      var rows = [['METHOD', m.name]];

      for (var key in schema) {
        if (!schema.hasOwnProperty || schema.hasOwnProperty(key)) {
          var label = schema[key];
          var value = (fields && fields[key]) || '';
          if (value) rows.push([label, value]);
        }
      }

      return rows;
    },

    /**
     * Validate generated data against the method's strict schema.
     * @returns {string[]} Array of error messages (empty = valid)
     */
    validate: function (methodId, eventType, data) {
      return validate(methodId, eventType, data);
    }
  };

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

})();
