import {
  DERIVATIVES_TRADING_USDS_FUTURES_REST_API_PROD_URL,
  DerivativesTradingUsdsFutures,
  DerivativesTradingUsdsFuturesRestAPI,
} from '@binance/derivatives-trading-usds-futures'

export class FutureConnector {
  client: DerivativesTradingUsdsFutures
  constructor(apiKey: string, apiSecret: string) {
    const configurationRestAPI = {
      apiKey: apiKey,
      apiSecret: apiSecret,
      basePath: DERIVATIVES_TRADING_USDS_FUTURES_REST_API_PROD_URL,
    }
    this.client = new DerivativesTradingUsdsFutures({ configurationRestAPI })
  }

  async getAssetsInfo() {
    try {
      const response = await this.client.restAPI.accountInformationV3()
      const data = await response.data()
      return data.assets.filter((asset: any) => Number(asset.walletBalance) > 0)
    } catch (error) {
      console.error('accountInformation() error:', error)
      return []
    }
  }

  async getPositonInfo() {
    try {
      const response = await this.client.restAPI.accountInformationV3()
      const data = await response.data()
      return data.positions.filter((position: any) => Number(position.positionAmt) > 0)
    } catch (error) {
      console.error('futuresPositionInformation() error:', error)
      return []
    }
  }

  async getPositionBalanceBySymbol(symbol: string) {
    try {
      const response = await this.client.restAPI.accountInformationV3()
      const data = await response.data()
      const position = data.positions.find((pos: any) => pos.symbol === symbol)
      if (position) {
        return position
      } else {
        return null
      }
    } catch (error) {
      console.error('getPositionBalanceBySymbol() error:', error)
      return null
    }
  }

  async openModifyPosition(
    symbol: string,
    side: DerivativesTradingUsdsFuturesRestAPI.ModifyOrderSideEnum,
    quantity: number,
    price: number,
  ) {
    try {
      const response = await this.client.restAPI.modifyOrder({
        symbol: symbol,
        side: side,
        quantity: quantity,
        price: price,
      })
      return await response.data()
    } catch (error) {
      console.error('openPosition() error:', error)
      return null
    }
  }

  async getCurrentAllOpenPosition() {
    try {
      const response = await this.client.restAPI.currentAllOpenOrders()
      const data = await response.data()
      console.log('当前所有开仓订单响应:', data)
    } catch (error) {
      console.error('currentAllOpenOrders() error:', error)
    }
  }

  async openPosition(
    symbol: string,
    side: DerivativesTradingUsdsFuturesRestAPI.NewOrderSideEnum,
    quantity: number,
    price: number,
    options?: any,
  ) {
    try {
      const orderParams: any = {
        symbol: symbol,
        side: side,
        type: options?.type || 'LIMIT',
        timeInForce: options?.timeInForce || DerivativesTradingUsdsFuturesRestAPI.NewOrderTimeInForceEnum.GTC,
        quantity: quantity,
        price: price,
      }
      if (options?.positionSide) {
        orderParams.positionSide = options.positionSide
      }
      if (options?.reduceOnly) {
        orderParams.reduceOnly = options.reduceOnly
      }
      if (options?.closePosition) {
        orderParams.closePosition = options.closePosition
      }
      if (options?.activationPrice) {
        orderParams.activationPrice = options.activationPrice
      }
      if (options?.callbackRate) {
        orderParams.callbackRate = options.callbackRate
      }
      if (options?.workingType) {
        orderParams.workingType = options.workingType
      }
      if (options?.priceProtect) {
        orderParams.priceProtect = options.priceProtect
      }
      if (options?.newOrderRespType) {
        orderParams.newOrderRespType = options.newOrderRespType
      }
      if (options?.newClientOrderId) {
        orderParams.newClientOrderId = options.newClientOrderId
      }
      if (options?.stopPrice) {
        orderParams.stopPrice = options.stopPrice
      }
      if (options?.icebergQty) {
        orderParams.icebergQty = options.icebergQty
      }
      if (options?.orderTag) {
        orderParams.orderTag = options.orderTag
      }
      console.log('下单参数:', orderParams)
      const response = await this.client.restAPI.newOrder(orderParams)
      const result = await response.data()
      console.log('下单成功:', result)
      return result
    } catch (error) {
      console.error('openPosition() 错误:', error)
      return null
    }
  }

  async openLimitOrder(
    symbol: string,
    side: 'long' | 'short',
    quantity: number,
    price: number,
    timeInForce: 'GTC' | 'IOC' | 'FOK' | 'GTX' | 'GTD' = 'GTC',
  ) {
    return this.openPosition(
      symbol,
      side === 'long'
        ? DerivativesTradingUsdsFuturesRestAPI.NewOrderSideEnum.BUY
        : DerivativesTradingUsdsFuturesRestAPI.NewOrderSideEnum.SELL,
      quantity,
      price,
      {
        type: 'LIMIT',
        timeInForce,
        positionSide:
          side === 'long'
            ? DerivativesTradingUsdsFuturesRestAPI.NewOrderPositionSideEnum.LONG
            : DerivativesTradingUsdsFuturesRestAPI.NewOrderPositionSideEnum.SHORT,
      },
    )
  }

  async openMarketOrder(symbol: string, side: 'long' | 'short', quantity: number) {
    return this.openPosition(
      symbol,
      side === 'long'
        ? DerivativesTradingUsdsFuturesRestAPI.NewOrderSideEnum.BUY
        : DerivativesTradingUsdsFuturesRestAPI.NewOrderSideEnum.SELL,
      quantity,
      0,
      {
        type: 'MARKET',
        positionSide:
          side === 'long'
            ? DerivativesTradingUsdsFuturesRestAPI.NewOrderPositionSideEnum.LONG
            : DerivativesTradingUsdsFuturesRestAPI.NewOrderPositionSideEnum.SHORT,
      },
    )
  }

  async openStopOrder(
    symbol: string,
    side: 'long' | 'short',
    quantity: number,
    stopPrice: number,
    type: 'STOP' | 'STOP_MARKET' = 'STOP_MARKET',
    price?: number,
    timeInForce: 'GTC' | 'IOC' | 'FOK' | 'GTX' | 'GTD' = 'GTC',
  ) {
    const orderParams: any = {
      type,
      stopPrice,
      reduceOnly: 'true',
      positionSide:
        side === 'long'
          ? DerivativesTradingUsdsFuturesRestAPI.NewOrderPositionSideEnum.LONG
          : DerivativesTradingUsdsFuturesRestAPI.NewOrderPositionSideEnum.SHORT,
    }
    if (type === 'STOP') {
      orderParams.timeInForce = timeInForce
    }
    return this.openPosition(
      symbol,
      side === 'long'
        ? DerivativesTradingUsdsFuturesRestAPI.NewOrderSideEnum.BUY
        : DerivativesTradingUsdsFuturesRestAPI.NewOrderSideEnum.SELL,
      quantity,
      price || 0,
      orderParams,
    )
  }

  async openTakeProfitOrder(
    symbol: string,
    side: 'long' | 'short',
    quantity: number,
    stopPrice: number,
    type: 'TAKE_PROFIT' | 'TAKE_PROFIT_MARKET' = 'TAKE_PROFIT_MARKET',
    price?: number,
    timeInForce: 'GTC' | 'IOC' | 'FOK' | 'GTX' | 'GTD' = 'GTC',
  ) {
    const orderParams: any = {
      type,
      stopPrice,
      reduceOnly: 'true',
      positionSide:
        side === 'long'
          ? DerivativesTradingUsdsFuturesRestAPI.NewOrderPositionSideEnum.LONG
          : DerivativesTradingUsdsFuturesRestAPI.NewOrderPositionSideEnum.SHORT,
    }
    if (type === 'TAKE_PROFIT') {
      orderParams.timeInForce = timeInForce
    }
    return this.openPosition(
      symbol,
      side === 'long'
        ? DerivativesTradingUsdsFuturesRestAPI.NewOrderSideEnum.BUY
        : DerivativesTradingUsdsFuturesRestAPI.NewOrderSideEnum.SELL,
      quantity,
      price || 0,
      orderParams,
    )
  }

  async openTrailingStopOrder(
    symbol: string,
    side: 'long' | 'short',
    quantity: number,
    activationPrice: number,
    callbackRate: number,
  ) {
    return this.openPosition(
      symbol,
      side === 'long'
        ? DerivativesTradingUsdsFuturesRestAPI.NewOrderSideEnum.BUY
        : DerivativesTradingUsdsFuturesRestAPI.NewOrderSideEnum.SELL,
      quantity,
      0,
      {
        type: 'TRAILING_STOP_MARKET',
        activationPrice,
        callbackRate,
        reduceOnly: 'true',
        positionSide:
          side === 'long'
            ? DerivativesTradingUsdsFuturesRestAPI.NewOrderPositionSideEnum.LONG
            : DerivativesTradingUsdsFuturesRestAPI.NewOrderPositionSideEnum.SHORT,
      },
    )
  }

  async openIcebergOrder(
    symbol: string,
    side: 'long' | 'short',
    quantity: number,
    price: number,
    icebergQty: number,
    timeInForce: 'GTC' | 'IOC' | 'FOK' | 'GTX' | 'GTD' = 'GTC',
  ) {
    return this.openPosition(
      symbol,
      side === 'long'
        ? DerivativesTradingUsdsFuturesRestAPI.NewOrderSideEnum.BUY
        : DerivativesTradingUsdsFuturesRestAPI.NewOrderSideEnum.SELL,
      quantity,
      price,
      {
        type: 'LIMIT',
        timeInForce,
        icebergQty,
        positionSide:
          side === 'long'
            ? DerivativesTradingUsdsFuturesRestAPI.NewOrderPositionSideEnum.LONG
            : DerivativesTradingUsdsFuturesRestAPI.NewOrderPositionSideEnum.SHORT,
      },
    )
  }

  async closeLongPosition(symbol: string, quantity: number) {
    return this.openPosition(symbol, DerivativesTradingUsdsFuturesRestAPI.NewOrderSideEnum.SELL, quantity, 0, {
      type: 'MARKET',
      reduceOnly: 'true',
      positionSide: DerivativesTradingUsdsFuturesRestAPI.NewOrderPositionSideEnum.LONG,
    })
  }

  async closeShortPosition(symbol: string, quantity: number) {
    return this.openPosition(symbol, DerivativesTradingUsdsFuturesRestAPI.NewOrderSideEnum.BUY, quantity, 0, {
      type: 'MARKET',
      reduceOnly: 'true',
      positionSide: DerivativesTradingUsdsFuturesRestAPI.NewOrderPositionSideEnum.SHORT,
    })
  }

  async closeAllPositions() {
    const positions = await this.getAllPositions()
    const results: any[] = []
    for (const pos of positions as any[]) {
      const amt = Number((pos as any).positionAmt)
      if (amt > 0) {
        results.push(await this.closeLongPosition((pos as any).symbol, Math.abs(amt)))
      } else if (amt < 0) {
        results.push(await this.closeShortPosition((pos as any).symbol, Math.abs(amt)))
      }
    }
    return results
  }

  async cancelOrder(symbol: string, orderId?: number, origClientOrderId?: string) {
    return this.client.restAPI.cancelOrder({ symbol, orderId, origClientOrderId })
  }

  async cancelAllOrders(symbol: string) {
    return this.client.restAPI.cancelAllOpenOrders({ symbol })
  }

  async getOrderHistory(symbol: string, startTime?: number, endTime?: number, limit: number = 100) {
    const response = await this.client.restAPI.allOrders({ symbol, startTime, endTime, limit })
    return response.data()
  }

  async getTradeHistory(symbol: string, startTime?: number, endTime?: number, limit: number = 100) {
    const response = await this.client.restAPI.accountTradeList({ symbol, startTime, endTime, limit })
    return response.data()
  }

  async setLeverage(symbol: string, leverage: number) {
    return this.client.restAPI.changeInitialLeverage({ symbol, leverage })
  }

  async setMarginType(symbol: string, marginType: DerivativesTradingUsdsFuturesRestAPI.ChangeMarginTypeMarginTypeEnum) {
    return this.client.restAPI.changeMarginType({ symbol, marginType })
  }

  async getAllPositions() {
    const response = await this.client.restAPI.accountInformationV3()
    const data = await response.data()
    return data.positions || []
  }

  async getExchangeInfo() {
    try {
      const response = await this.client.restAPI.exchangeInformation()
      return response.data()
    } catch (error) {
      console.error('getExchangeInfo() error:', error)
      return null
    }
  }

  async getSymbols(): Promise<string[]> {
    try {
      const exchangeInfo = await this.getExchangeInfo()
      if (!exchangeInfo?.symbols) return []
      return exchangeInfo.symbols.filter((s: any) => s.status === 'TRADING').map((s: any) => s.symbol)
    } catch (error) {
      console.error('getSymbols() error:', error)
      return []
    }
  }

  async getDepth(symbol: string, limit = 100) {
    try {
      const response = await this.client.restAPI.orderBook({ symbol, limit })
      return response.data()
    } catch (error) {
      console.error('getDepth() error:', error)
      return { bids: [], asks: [], lastUpdateId: 0 }
    }
  }

  async getCurrentAllOpenOrders(symbol?: string) {
    try {
      const response = await this.client.restAPI.currentAllOpenOrders({ symbol })
      return response.data()
    } catch (error) {
      console.error('getCurrentAllOpenOrders() error:', error)
      return []
    }
  }
}

// 移除重复导出，统一以本文件类为准
