const { AML } = require('elliptic-sdk')
const _ = require('lodash/fp')

const NAME = 'Elliptic'

const HOLLISTIC_COINS = {
  BTC: 'BTC',
  ETH: 'ETH',
  USDT: 'USDT',
  USDT_TRON: 'USDT',
  LTC: 'LTC',
  TRX: 'TRX',
}

const SINGLE_ASSET_COINS = {
  ZEC: {
    asset: 'ZEC',
    blockchain: 'zcash',
  },
  BCH: {
    asset: 'BCH',
    blockchain: 'bitcoin_cash',
  },
}

const TYPE = {
  TRANSACTION: 'transaction',
  ADDRESS: 'address',
}

const SUPPORTED_COINS = { ...HOLLISTIC_COINS, ...SINGLE_ASSET_COINS }

function rate(account, objectType, cryptoCode, objectId) {
  return isWalletScoringEnabled(account, cryptoCode).then(isEnabled => {
    if (!isEnabled) return Promise.resolve(null)

    const aml = new AML({
      key: account.apiKey,
      secret: account.apiSecret,
    })

    const isHolistic = Object.keys(HOLLISTIC_COINS).includes(cryptoCode)

    const requestBody = {
      subject: {
        asset: isHolistic ? 'holistic' : SINGLE_ASSET_COINS[cryptoCode].asset,
        blockchain: isHolistic
          ? 'holistic'
          : SINGLE_ASSET_COINS[cryptoCode].blockchain,
        type: objectType,
        hash: objectId,
      },
      type: objectType === TYPE.ADDRESS ? 'wallet_exposure' : 'source_of_funds',
    }

    const threshold = account.scoreThreshold
    const endpoint =
      objectType === TYPE.ADDRESS
        ? '/v2/wallet/synchronous'
        : '/v2/analysis/synchronous'

    return aml.client.post(endpoint, requestBody).then(res => {
      const resScore = res.data?.risk_score

      // elliptic returns 0-1 score, but we're accepting 0-100 config
      // normalize score to 0-10 where 0 is the lowest risk
      // elliptic score can be null and contains decimals
      return {
        score: (resScore || 0) * 10,
        isValid: (resScore || 0) * 100 < threshold,
      }
    })
  })
}

function rateTransaction(account, cryptoCode, transactionId) {
  return rate(account, TYPE.TRANSACTION, cryptoCode, transactionId)
}

function rateAddress(account, cryptoCode, address) {
  return rate(account, TYPE.ADDRESS, cryptoCode, address)
}

function isWalletScoringEnabled(account, cryptoCode) {
  const isAccountEnabled = !_.isNil(account) && account.enabled

  if (!isAccountEnabled) return Promise.resolve(false)

  if (!Object.keys(SUPPORTED_COINS).includes(cryptoCode)) {
    return Promise.reject(new Error('Unsupported crypto: ' + cryptoCode))
  }

  return Promise.resolve(true)
}

module.exports = {
  NAME,
  rateAddress,
  rateTransaction,
  isWalletScoringEnabled,
}
