import { spot_game, formatted_spot_players } from './spot_data';
import { range_game, formatted_range_players } from './range_data';
import {
  computeRangePlayerVariance,
  computeSpotPlayerVariance,
  calculateRangePotDistribution,
  calculateSpotPotDistribution,
  computeRangeWinnings,
  computeSpotWinnings,
} from '../src/computation';

import * as index from '../src/index';
import * as computation from '../src/computation';
import * as types from '../src/types';

describe('Metafide Surge Computation Tests', () => {
  /**
   * Tests spot game pot distribution calculation
   */
  it('should correctly calculate Spot pot distribution', () => {
    const expected_spot_distribution = {
      total_pot: 7632879,
      metafide_rake: 151703.47,
      streak_pot_5: 108768.53,
      streak_pot_10: 72512.35,
      streak_pot_25: 18128.09,
      daily_reward_pot: 26715.08,
      monthly_reward_pot: 11449.32,
      burn: 190821.98,
      winning_pot: 6938287,
      range_rake: 114493.18,
    };
    const spot_distribution = calculateSpotPotDistribution(
      formatted_spot_players
    );
    expect(spot_distribution).toEqual(expected_spot_distribution);
  });

  /**
   * Tests range game pot distribution calculation
   */
  it('should correctly calculate Range pot distribution', () => {
    const expected_range_distribution = {
      total_pot: 2237403,
      metafide_rake: 44468.38,
      streak_pot_5: 31882.99,
      streak_pot_10: 21255.33,
      streak_pot_25: 5313.83,
      daily_reward_pot: 7830.91,
      monthly_reward_pot: 3356.1,
      burn: 55935.08,
      winning_pot: 2067360.38,
    };

    const range_distribution = calculateRangePotDistribution(
      formatted_range_players
    );
    expect(range_distribution).toEqual(expected_range_distribution);
  });

  /**
   * Tests spot game pot distribution calculation for one player
   */
  it('should correctly calculate Spot pot distribution for one player', () => {
    const spot_player = [formatted_spot_players[0]];
    const expected_spot_distribution = {
      total_pot: 17324,
      metafide_rake: 0,
      range_rake: 0,
      streak_pot_5: 0,
      streak_pot_10: 0,
      streak_pot_25: 0,
      daily_reward_pot: 0,
      monthly_reward_pot: 0,
      burn: 0,
      winning_pot: 17324,
    };
    const spot_distribution = calculateSpotPotDistribution(spot_player);
    expect(spot_distribution).toEqual(expected_spot_distribution);
  });

  /**
   * Tests range game pot distribution calculation for one player
   */
  it('should correctly calculate Range pot distribution for one player', () => {
    const range_player = [formatted_range_players[0]];
    const expected_range_distribution = {
      total_pot: 12275,
      metafide_rake: 0,
      streak_pot_5: 0,
      streak_pot_10: 0,
      streak_pot_25: 0,
      daily_reward_pot: 0,
      monthly_reward_pot: 0,
      burn: 0,
      winning_pot: 12275,
    };

    const range_distribution = calculateRangePotDistribution(range_player);
    expect(range_distribution).toEqual(expected_range_distribution);
  });

  /**
   * Tests variance calculation for Range players
   */
  it('should correctly calculate Range player variance', () => {
    const expected_variance_player_1 = {
      gid: 3758,
      c: 'Mantle',
      a: 'BTC_USDT',
      id: 'b82caf9c-a42b-47d1-ae2d-c419fbd1b976',
      f: 12275,
      hp: 97249,
      lp: 96062,
      cm: false,
      cmt: null,
      t: '2025-03-20 10:23:34',
      w: 11132.389706803686,
      r: -9.308434160458766,
      p: -9.308434248195336,
      ex: true,
      ex_ha: 9713500000000,
      ex_la: 9619100000000,
      ex_t: 1697030400,
      pw: '0xd252aca57e7cbe5360f2486d2a0298a35350a29f',
      win: true,
      varianceInput: {
        high_actual: 97135,
        low_actual: 96191,
        total_variance: 3787.9951161531344,
        sum_total_variance: 30756.695759,
      },
    };
    const range_variance = computeRangePlayerVariance(
      formatted_range_players,
      range_game
    );
    expect(range_variance[0]).toEqual(expected_variance_player_1);
  });

  /**
   * Tests variance calculation for Spot players
   */
  it('should correctly calculate Spot player variance', () => {
    const expected_variance_player_1 = {
      gid: 18775,
      c: 'Mantle',
      a: 'BTC_USDT',
      id: 157,
      f: 17324,
      sp: 96738,
      cm: true,
      cmt: 1744926040446,
      t: '1742469259000',
      w: 6330.224433585335,
      r: -63.45979892873854,
      pw: '0x7a9df597be5e0533b144c28ec47311aecb5d91ad',
      win: false,
      varianceInput: {
        actual_price: 96488,
        abs_spot_var: 250,
        token_milliseconds: 4477746850.247011,
        share_tkm_to_var: 0.7771971399842026,
        sum_share_tkm_to_var: 851.8523913194913,
      },
    };

    const spot_variance = computeSpotPlayerVariance(
      formatted_spot_players,
      spot_game
    );
    expect(spot_variance[0]).toEqual(expected_variance_player_1);
  });

  /**
   * Tests winnings calculation for Range players
   */
  it('should correctly calculate Range player winnings', () => {
    const expected_player_1 = {
      gid: 3758,
      c: 'Mantle',
      a: 'BTC_USDT',
      id: 'b82caf9c-a42b-47d1-ae2d-c419fbd1b976',
      f: 12275,
      hp: 97249,
      lp: 96062,
      cm: false,
      cmt: null,
      t: '2025-03-20 10:23:34',
      w: 11132.389749882348,
      r: -9.30843380951244,
      p: -9.308434248195336,
      ex: true,
      ex_ha: 9713500000000,
      ex_la: 9619100000000,
      ex_t: 1697030400,
      pw: '0xd252aca57e7cbe5360f2486d2a0298a35350a29f',
      win: true,
    };
    const expected_player_2 = {
      gid: 3758,
      c: 'Mantle',
      a: 'BTC_USDT',
      id: '21a46dc1-25af-4149-9cd7-1ff8b061bc77',
      f: 44572,
      hp: 97206,
      lp: 96084,
      cm: false,
      cmt: null,
      t: '2025-03-20 10:23:34',
      w: 64477.53572445048,
      r: 44.659283237123034,
      p: 44.65928253739369,
      ex: true,
      ex_ha: 9713500000000,
      ex_la: 9619100000000,
      ex_t: 1697030400,
      pw: '0x719921a08bb5d1fdabe2232ff08c82c87ce52ac5',
      win: true,
    };
    const range_distribution = calculateRangePotDistribution(
      formatted_range_players
    );
    const range_winnings = computeRangeWinnings(
      formatted_range_players,
      range_game,
      range_distribution
    );
    expect(range_winnings.players[0]).toEqual(expected_player_1);
    expect(range_winnings.players[range_winnings.players.length - 1]).toEqual(
      expected_player_2
    );
  });

  /**
   * Tests winnings calculation for Spot players
   */
  it('should correctly calculate Spot player winnings', () => {
    const expected_player_1 = {
      gid: 18775,
      c: 'Mantle',
      a: 'BTC_USDT',
      id: 157,
      f: 17324,
      cm: true,
      cmt: 1744926040446,
      t: '1742469259000',
      w: 6330.224423549364,
      r: -63.45979898666957,
      sp: 96738,
      pw: '0x7a9df597be5e0533b144c28ec47311aecb5d91ad',
      win: false,
      tx: undefined,
      txid: undefined,
    };
    const expected_player_2 = {
      gid: 18775,
      c: 'Mantle',
      a: 'BTC_USDT',
      id: 231,
      f: 12649,
      cm: true,
      cmt: 1744926040446,
      t: '1742454569000',
      w: 2410.0275032078353,
      r: -80.94689300966215,
      sp: 96164,
      pw: '0xa626b3ba0ae8b56a82e797a2d54e2b7af6d8bebb',
      win: false,
      tx: undefined,
      txid: undefined,
    };

    const spot_distribution = calculateSpotPotDistribution(
      formatted_spot_players
    );
    const spot_winnings = computeSpotWinnings(
      formatted_spot_players,
      spot_game,
      spot_distribution
    );
    expect(spot_winnings.players[0]).toEqual(expected_player_1);
    expect(spot_winnings.players[spot_winnings.players.length - 1]).toEqual(
      expected_player_2
    );
  });

  /**
   * Tests winnings calculation for one Range player
   */
  it('should correctly calculate one Range player winning', () => {
    const range_player = [formatted_range_players[0]];
    const expected_player_1 = {
      gid: 3758,
      c: 'Mantle',
      a: 'BTC_USDT',
      id: 'b82caf9c-a42b-47d1-ae2d-c419fbd1b976',
      f: 12275,
      hp: 97249,
      lp: 96062,
      cm: false,
      cmt: null,
      t: '2025-03-20 10:23:34',
      w: 12275,
      r: 1,
      p: -9.308434248195336,
      ex: true,
      ex_ha: 9713500000000,
      ex_la: 9619100000000,
      ex_t: 1697030400,
      pw: '0xd252aca57e7cbe5360f2486d2a0298a35350a29f',
      win: true,
    };
    const range_distribution = calculateRangePotDistribution(range_player);
    const range_winnings = computeRangeWinnings(
      range_player,
      range_game,
      range_distribution
    );
    expect(range_winnings.players[0]).toEqual(expected_player_1);
    expect(range_winnings.streak.winnings).toEqual([]);
    expect(range_winnings.streak.returns).toEqual([]);
  });

  /**
   * Tests winnings calculation for One Spot player
   */
  it('should correctly calculate one Spot player winning', () => {
    const spot_player = [formatted_spot_players[0]];
    const expected_player_1 = {
      gid: 18775,
      c: 'Mantle',
      a: 'BTC_USDT',
      id: 157,
      f: 17324,
      cm: true,
      cmt: 1744926040446,
      t: '1742469259000',
      w: 17324,
      r: 1,
      sp: 96738,
      pw: '0x7a9df597be5e0533b144c28ec47311aecb5d91ad',
      win: false,
      tx: undefined,
      txid: undefined,
    };
    const spot_distribution = calculateSpotPotDistribution(spot_player);
    const spot_winnings = computeSpotWinnings(
      spot_player,
      spot_game,
      spot_distribution
    );
    expect(spot_winnings.players[0]).toEqual(expected_player_1);
    expect(spot_winnings.streak.winnings).toEqual([]);
    expect(spot_winnings.streak.returns).toEqual([]);
  });

  // Tests index entry point
  it('should export computation functions correctly', () => {
    expect(index.calculateSpotPotDistribution).toBe(
      computation.calculateSpotPotDistribution
    );
    expect(index.calculateRangePotDistribution).toBe(
      computation.calculateRangePotDistribution
    );
    expect(index.computeRangeWinnings).toBe(computation.computeRangeWinnings);
    expect(index.computeSpotWinnings).toBe(computation.computeSpotWinnings);
  });

  it('should export types correctly', () => {
    expect(index).toBeDefined();
  });
});
