import { RhoSDKNetwork } from '../../sdk-typings'
import axios from 'axios'

const DataServiceUrlMap: Record<string, string> = {
  'mainnet': 'https://ds.rhoservice.com',
  'testnet': 'https://ds-testnet.rhoservice.com',
}

interface DataServiceConfig {
  network: RhoSDKNetwork
  url?: string
}

export interface GetRequestBase {
  userAddress?: string
  marketId?: string
  futureId?: string
  before?: number
  count?: number
}

export type GetMarginUpdatesRequest = Omit<GetRequestBase, 'futureId'>
export type GetPositionOwnershipTransferParams = Omit<GetRequestBase, 'before' | 'count'> & { limit?: number; skip?: number }
export type GetPositionLiquidationsParams = GetPositionOwnershipTransferParams

export interface Trade {
  txHash: string
  ownerAddress: string
  timestamp: number
  marketId: string
  marketAddress: string
  futureId: string
  futureAddress: string
  notionalAmount: string
  feeAmount: string
  rate: string
  direction: 0 | 1
  ownerIsMaker: boolean
  market: string
  maturity: number
  marketRateBefore: string
  marketRateAfter: string
}

export interface GetTradesResponse {
  cached: boolean
  trades: Trade[]
}

export interface Provision {
  txHash: string
  ownerAddress: string
  timestamp: number
  marketId: string
  marketAddress: string
  futureId: string
  futureAddress: string
  notionalAmount: string
  lowerBoundRate: string
  upperBoundRate: string
  market: string
  maturity: number
}

export interface GetProvisionsResponse {
  cached: boolean
  provisions: Provision[]
}

export interface MarginUpdate {
  txHash: string
  ownerAddress: string
  timestamp: number
  marketId: string
  marketAddress: string
  marginDelta: string
  market: string
}

export interface GetMarginUpdatesResponse {
  cached: boolean
  marginUpdates: MarginUpdate[]
}

export interface PositionOwnershipTransferFuture {
  futureId: string
  fixedTokenAmount: string
  floatTokenAmount: string
  floatTradeValue: string
  notional: string
  marketRate: string
}

export interface PositionOwnershipTransfer {
  transactionHash: string
  marketId: string
  from: string
  to: string
  deposit: string
  marginTransfer: string
  positionsMtmPayment: string
  reward: string
  floatIndex: string
  blockNumber: number
  timestamp: number
  futures: PositionOwnershipTransferFuture[]
}

export interface PositionLiquidation {
  marketId: string
  futureIds: string[]
  positionsPercentages: string[]
  owner: string
  liquidator: string
  reward: string
  blockNumber: number
  timestamp: number
  transactionHash: string
}

export class DataServiceAPI {
  private readonly config: DataServiceConfig

  constructor(config: DataServiceConfig) {
    this.config = config
  }

  public getUrl() {
    const defaultUrl = DataServiceUrlMap[this.config.network]
    return this.config.url || defaultUrl
  }

  async getTrades(params: GetRequestBase = {}) {
    const { data } = await axios.get<GetTradesResponse>(
      `${this.getUrl()}/api/v1/trades`
      , {
      params
    })

    return data.trades
  }

  async getProvision(params: GetRequestBase = {}) {
    const { data } = await axios.get<GetProvisionsResponse>(
      `${this.getUrl()}/api/v1/provisions`
      , {
        params
      })

    return data.provisions
  }

  async getMarginUpdates(params: GetMarginUpdatesRequest = {}) {
    const { data } = await axios.get<GetMarginUpdatesResponse>(
      `${this.getUrl()}/api/v1/margin-updates`
      , {
        params
      })

    return data.marginUpdates
  }

  async getPositionOwnershipTransfers(params: GetPositionOwnershipTransferParams = {}) {
    const { data } = await axios.get<{ cached: boolean; data: PositionOwnershipTransfer[] }>(
      `${this.getUrl()}/api/v1/position-ownership-transfers`
      , {
        params
      })

    return data.data
  }

  async getPositionLiqudations(params: GetPositionLiquidationsParams = {}) {
    const { data } = await axios.get<{ cached: boolean; data: PositionLiquidation[] }>(
      `${this.getUrl()}/api/v1/position-liquidations`
      , {
        params
      })

    return data.data
  }
}
