import {
  CancelOrderRequest,
  CancelOrderResponse, Candle,
  CreateOrderRequest,
  CreateOrderResponse, FloatingRateCandle,
  Market,
  Order,
  OrderBookCandle,
  OrderBookCandleInterval,
  RhoV2Config,
  SymbolStats,
  UserPortfolio
} from '../typings'
import axios, { Axios } from 'axios'

interface GetMarketsResponse {
  data: {
    marketInfos: Market[]
  }
}

export class RhoV2API {
  private client: Axios

  constructor(config: RhoV2Config) {
    this.client = axios.create({
      baseURL: `${config.gatewayUrl}/api/v1`
    })
  }

  async getMarkets() {
    const { data } = await this.client.get<GetMarketsResponse>('/markets')

    return data.data.marketInfos
  }

  async postOrder(requestData: CreateOrderRequest) {
    const { data } = await this.client.post<{
      data: CreateOrderResponse
      message: string
    }>('/orders', requestData, {
      headers: { 'Content-Type': 'application/json' }
    })
    return data.data
  }

  async cancelOrder(requestData: CancelOrderRequest) {
    const { data } = await this.client.post<{
      data: CancelOrderResponse
      message: string
    }>('/orders/cancel', requestData, {
      headers: {
        'Content-Type': 'application/json'
      }
    })
    return data.data
  }

  async getPortfolios(userId: string) {
    const { data } = await this.client.get<{
      data: {
        userPortfolios: UserPortfolio[]
      }
    }>(`/users/${userId}/portfolios`)
    return data.data.userPortfolios
  }

  async getPortfolioCandles(params: {
    userId: string
    portfolioId: string,
    interval?: string,
    from?: string,
    to?: string,
  }) {
    const { userId, portfolioId, interval = '1h' } = params
    const { data } = await this.client.get<{
      data: Candle[]
    }>(`/users/${userId}/portfolios/${portfolioId}/candles`, {
      params: {
        ...params,
        interval
      }
    })
    return data.data
  }

  async getOrderBook(symbol: string, depth = 20) {
    const { data } = await this.client.get<{
      data: {
        symbol: string
        asks: Order[]
        bids: Order[]
      }
    }>(`/markets/symbols/${symbol}/order-book`, {
      params: {
        depth
      }
    })

    return data.data
  }

  async getSymbolStats(symbols: string[]): Promise<SymbolStats[]> {
    const symbolsList = symbols
      .map((symbol, index) => `${index === 0 ? '?' : '&'}symbols=${symbol}`)
      .join('')
    const { data } = await this.client.get<{
      data: SymbolStats[]
    }>(`markets/symbols/stats${symbolsList}`)
    return data.data
  }

  async getCandles(params: {
    symbol: string
    interval: OrderBookCandleInterval
    from?: string
    to?: string
  }): Promise<OrderBookCandle[]> {
    const { symbol, interval, from, to } = params
    const { data } = await this.client.get<{
      data: OrderBookCandle[]
    }>(`/markets/symbols/${symbol}/candles`, {
      params: {
        interval,
        from,
        to
      }
    })
    return data.data
  }

  async getFloatingRateCandles(params: {
    marketId: string
    interval: OrderBookCandleInterval
    from?: string
    to?: string
  }): Promise<FloatingRateCandle[]> {
    const { marketId, interval, from, to } = params
    const { data } = await this.client.get<{
      data: FloatingRateCandle[]
    }>(`/markets/${marketId}/floating-rate-candles`, {
      params: {
        interval,
        from,
        to
      }
    })
    return data.data
  }
}
