package bitgetservice

import (
	"errors"
	"fmt"
	"go-admin/common/global"
	"go-admin/common/helper"
	"go-admin/common/interfaces"
	"go-admin/models"
	"go-admin/pkg/utility"
	"strconv"
	"strings"

	"github.com/bytedance/sonic"
)

// BitgetClient Bitget交易所客户端实现
type BitgetClient struct {
	httpClient   *helper.BitgetClient
	marketClient *BitgetMarketClient // 公开行情客户端
}

// NewBitgetClient 创建新的Bitget客户端实例
func NewBitgetClient(apiKey, apiSecret, passphrase, proxyUrl string) (*BitgetClient, error) {
	httpClient, err := helper.NewBitgetClient(apiKey, apiSecret, passphrase, proxyUrl)
	if err != nil {
		return nil, err
	}

	client := &BitgetClient{
		httpClient: httpClient,
	}

	// 初始化公开行情客户端
	marketConfig := DefaultMarketConfig()
	client.marketClient = NewBitgetMarketClient(marketConfig)

	return client, nil
}

// GetExchangeName 获取交易所名称
func (c *BitgetClient) GetExchangeName() string {
	return global.EXCHANGE_BITGET
}

// GetExchangeInfo 获取交易所信息
func (c *BitgetClient) GetExchangeInfo() (interfaces.ExchangeInfoResponse, error) {
	restApi := NewBitgetRestApi()

	datas, err := restApi.GetSpotSymbols()

	if err != nil {
		return interfaces.ExchangeInfoResponse{}, err
	}

	symbols := make([]interfaces.SymbolInfo, 0, len(datas))
	for _, item := range datas {
		symbols = append(symbols, interfaces.SymbolInfo{
			Symbol:     item.Symbol,
			BaseAsset:  item.BaseCoin,
			QuoteAsset: item.QuoteCoin,
			Status:     item.Status,
			MinQty:     item.MinQty,
			MaxQty:     item.MaxQty,
			StepSize:   strconv.Itoa(item.QuantityDigit),
			TickSize:   strconv.Itoa(item.PriceDigit),
		})
	}

	return interfaces.ExchangeInfoResponse{Symbols: symbols}, nil
}

// GetSpotTickers 获取所有现货行情
func (c *BitgetClient) GetSpotTickers() ([]models.TradeSet, error) {
	params := map[string]interface{}{}
	resp, _, err := c.httpClient.SendSpotRequestAuth("/api/v2/spot/market/tickers", "GET", params)
	if err != nil {
		return nil, fmt.Errorf("获取Bitget现货行情列表失败: %v", err)
	}

	var response struct {
		Code string `json:"code"`
		Msg  string `json:"msg"`
		Data []struct {
			Symbol    string `json:"symbol"`
			High24h   string `json:"high24h"`
			Low24h    string `json:"low24h"`
			Close     string `json:"close"`
			Open      string `json:"open"`
			Volume24h string `json:"volume24h"`
			QuoteVol  string `json:"quoteVol"`
			Change24h string `json:"change24h"`
			Change    string `json:"change"`
		} `json:"data"`
	}

	if err := sonic.Unmarshal(resp, &response); err != nil {
		return nil, fmt.Errorf("解析Bitget行情列表失败: %v", err)
	}

	if response.Code != "00000" {
		return nil, fmt.Errorf("bitget API错误: %s", response.Msg)
	}

	tradeSets := make([]models.TradeSet, 0, len(response.Data))
	for _, item := range response.Data {
		// 解析交易对，获取基础币种和计价币种
		var coin, currency string
		if strings.HasSuffix(item.Symbol, "USDT") {
			coin = strings.TrimSuffix(item.Symbol, "USDT")
			currency = "USDT"
		} else if strings.HasSuffix(item.Symbol, "BTC") {
			coin = strings.TrimSuffix(item.Symbol, "BTC")
			currency = "BTC"
		} else if strings.HasSuffix(item.Symbol, "ETH") {
			coin = strings.TrimSuffix(item.Symbol, "ETH")
			currency = "ETH"
		} else {
			continue // 跳过不支持的交易对
		}

		tradeSet := models.TradeSet{
			Coin:        coin,
			Currency:    currency,
			LastPrice:   item.Close,
			HighPrice:   item.High24h,
			LowPrice:    item.Low24h,
			Volume:      item.Volume24h,
			QuoteVolume: item.QuoteVol,
			OpenPrice:   utility.StringAsFloat(item.Open),
			PriceChange: utility.StringAsFloat(item.Change),
		}

		tradeSets = append(tradeSets, tradeSet)
	}

	return tradeSets, nil
}

// GetSpotTicker24h 获取现货24小时行情
func (c *BitgetClient) GetSpotTicker24h(symbol string) (models.Ticker24, error) {
	params := map[string]interface{}{
		"symbol": symbol,
	}

	resp, _, err := c.httpClient.SendSpotRequestAuth("/api/v2/spot/market/ticker", "GET", params)
	if err != nil {
		return models.Ticker24{}, fmt.Errorf("获取Bitget现货24h行情失败: %v", err)
	}

	var response struct {
		Code string `json:"code"`
		Msg  string `json:"msg"`
		Data struct {
			Symbol    string `json:"symbol"`
			High24h   string `json:"high24h"`
			Low24h    string `json:"low24h"`
			Close     string `json:"close"`
			Open      string `json:"open"`
			Volume24h string `json:"volume24h"`
			QuoteVol  string `json:"quoteVol"`
			Change24h string `json:"change24h"`
			Change    string `json:"change"`
		} `json:"data"`
	}

	if err := sonic.Unmarshal(resp, &response); err != nil {
		return models.Ticker24{}, fmt.Errorf("解析Bitget 24h行情失败: %v", err)
	}

	if response.Code != "00000" {
		return models.Ticker24{}, fmt.Errorf("Bitget API错误: %s", response.Msg)
	}

	ticker := models.Ticker24{
		HighPrice:     response.Data.High24h,
		LowPrice:      response.Data.Low24h,
		LastPrice:     response.Data.Close,
		OpenPrice:     response.Data.Open,
		Volume:        response.Data.Volume24h,
		QuoteVolume:   response.Data.QuoteVol,
		ChangePercent: response.Data.Change,
	}

	return ticker, nil
}

// PlaceSpotOrder 下现货订单
func (c *BitgetClient) PlaceSpotOrder(params interfaces.SpotOrderParams) (interfaces.SpotOrderResponse, error) {
	orderParams := map[string]interface{}{
		"symbol":    params.Symbol,
		"side":      strings.ToLower(params.Side),
		"orderType": strings.ToLower(params.Type),
		"quantity":  params.Quantity.String(),
	}

	if params.Type == "LIMIT" {
		orderParams["price"] = params.Price.String()
	}

	if params.TimeInForce != "" {
		orderParams["timeInForce"] = params.TimeInForce
	}

	if params.NewClientOrderId != "" {
		orderParams["clientOrderId"] = params.NewClientOrderId
	}

	resp, _, err := c.httpClient.SendSpotRequestAuth("/api/v2/spot/trade/orders", "POST", orderParams)
	if err != nil {
		return interfaces.SpotOrderResponse{}, fmt.Errorf("Bitget现货下单失败: %v", err)
	}

	var response struct {
		Code string `json:"code"`
		Msg  string `json:"msg"`
		Data struct {
			OrderId       string `json:"orderId"`
			ClientOrderId string `json:"clientOrderId"`
		} `json:"data"`
	}

	if err := sonic.Unmarshal(resp, &response); err != nil {
		return interfaces.SpotOrderResponse{}, fmt.Errorf("解析Bitget下单响应失败: %v", err)
	}

	if response.Code != "00000" {
		return interfaces.SpotOrderResponse{}, fmt.Errorf("Bitget下单API错误: %s", response.Msg)
	}

	orderId, _ := strconv.ParseInt(response.Data.OrderId, 10, 64)

	return interfaces.SpotOrderResponse{
		Symbol:        params.Symbol,
		OrderId:       orderId,
		ClientOrderId: response.Data.ClientOrderId,
		Price:         params.Price.String(),
		OrigQty:       params.Quantity.String(),
		Side:          params.Side,
		Type:          params.Type,
		Status:        "NEW",
	}, nil
}

// CancelSpotOrder 取消现货订单
func (c *BitgetClient) CancelSpotOrder(symbol, orderID string) error {
	params := map[string]interface{}{
		"symbol":  symbol,
		"orderId": orderID,
	}

	resp, _, err := c.httpClient.SendSpotRequestAuth("/api/v2/spot/trade/cancel-order", "POST", params)
	if err != nil {
		return fmt.Errorf("Bitget取消现货订单失败: %v", err)
	}

	var response struct {
		Code string `json:"code"`
		Msg  string `json:"msg"`
	}

	if err := sonic.Unmarshal(resp, &response); err != nil {
		return fmt.Errorf("解析Bitget取消订单响应失败: %v", err)
	}

	if response.Code != "00000" {
		return fmt.Errorf("Bitget取消订单API错误: %s", response.Msg)
	}

	return nil
}

// GetSpotOrder 获取现货订单详情
func (c *BitgetClient) GetSpotOrder(symbol, orderID string) (interfaces.SpotOrderResponse, error) {
	// 实现订单查询逻辑
	return interfaces.SpotOrderResponse{}, fmt.Errorf("GetSpotOrder not implemented yet")
}

// GetSpotOrders 获取现货订单列表
func (c *BitgetClient) GetSpotOrders(symbol string) ([]interfaces.SpotOrderResponse, error) {
	params := map[string]interface{}{
		"symbol": symbol,
	}

	_, _, err := c.httpClient.SendSpotRequestAuth("/api/v2/spot/trade/open-orders", "GET", params)
	if err != nil {
		return nil, fmt.Errorf("获取Bitget现货订单列表失败: %v", err)
	}

	// 这里需要根据实际的Bitget API响应格式来解析
	return []interfaces.SpotOrderResponse{}, nil
}

// 合约相关接口实现（暂时返回错误）
func (c *BitgetClient) GetFuturesTicker24h(symbol string) (models.Ticker24, error) {
	return models.Ticker24{}, fmt.Errorf("futures not implemented yet")
}

func (c *BitgetClient) GetFuturesTickers() ([]models.TradeSet, error) {
	return nil, fmt.Errorf("futures not implemented yet")
}

func (c *BitgetClient) PlaceFuturesOrder(params interfaces.FuturesOrderParams) (interfaces.FuturesOrderResponse, error) {
	return interfaces.FuturesOrderResponse{}, fmt.Errorf("futures not implemented yet")
}

func (c *BitgetClient) CancelFuturesOrder(symbol, orderID string) error {
	return fmt.Errorf("futures not implemented yet")
}

func (c *BitgetClient) GetFuturesOrder(symbol, orderID string) (interfaces.FuturesOrderResponse, error) {
	return interfaces.FuturesOrderResponse{}, fmt.Errorf("futures not implemented yet")
}

// WebSocket相关接口实现（已重构为使用公开行情客户端）
// 注意：这些方法已被重构，现在使用新的公开行情客户端
// 如需私有数据订阅（如订单、持仓），请使用 BitgetWebSocketManager

// 旧的订阅方法（保留兼容性，但建议使用新方法）
func (c *BitgetClient) SubscribeSpotTickerLegacy(symbols []string, callback func(models.Ticker24, string, string)) error {
	return fmt.Errorf("已废弃，请使用 SubscribeSpotTicker(symbol, listener) 方法")
}

func (c *BitgetClient) SubscribeFuturesTickerLegacy(symbols []string, callback func(models.Ticker24, string, string)) error {
	return fmt.Errorf("已废弃，请使用 SubscribeFuturesTicker(symbol, listener) 方法")
}

func (c *BitgetClient) SubscribeSpotDepthLegacy(symbols []string, callback func(models.DepthBin, string, string)) error {
	return fmt.Errorf("已废弃，请使用 SubscribeSpotDepth(symbol, listener) 方法")
}

func (c *BitgetClient) SubscribeSpotTradesLegacy(symbols []string, callback func(models.NewDealPush, string, string)) error {
	return fmt.Errorf("已废弃，请使用 SubscribeSpotTrades(symbol, listener) 方法")
}

func (c *BitgetClient) SubscribeKlineLegacy(symbols []string, interval string, callback func(models.Kline, int, string, string)) error {
	return fmt.Errorf("已废弃，请使用 SubscribeKline(symbol, interval, listener) 方法")
}

func (c *BitgetClient) Close() error {
	// 关闭HTTP客户端等清理工作
	return nil
}

// SetMarketProxy 设置市场数据代理
func (c *BitgetClient) SetMarketProxy(proxyType, proxyAddress string) {
	if c.marketClient != nil {
		c.marketClient.SetProxy(proxyType, proxyAddress)
	}
}

// SetMarketListeners 设置市场数据监听器
func (c *BitgetClient) SetMarketListeners(msgListener, errorListener OnReceive) {
	if c.marketClient != nil {
		c.marketClient.SetListeners(msgListener, errorListener)
	}
}

// ConnectMarketData 连接市场数据WebSocket
func (c *BitgetClient) ConnectMarketData() error {
	if c.marketClient == nil {
		return errors.New("市场数据客户端未初始化")
	}
	return c.marketClient.Connect()
}

// SubscribeMarketData 订阅市场数据（公开行情）
func (c *BitgetClient) SubscribeMarketData(subscribeReqs []SubscribeReq, listener OnReceive) error {
	if c.marketClient == nil {
		return errors.New("市场数据客户端未初始化")
	}
	return c.marketClient.Subscribe(subscribeReqs, listener)
}

// UnsubscribeMarketData 取消订阅市场数据
func (c *BitgetClient) UnsubscribeMarketData(subscribeReqs []SubscribeReq) error {
	if c.marketClient == nil {
		return errors.New("市场数据客户端未初始化")
	}
	return c.marketClient.Unsubscribe(subscribeReqs)
}

// IsMarketDataConnected 检查市场数据连接状态
func (c *BitgetClient) IsMarketDataConnected() bool {
	if c.marketClient == nil {
		return false
	}
	return c.marketClient.IsConnected()
}

// CloseMarketData 关闭市场数据连接
func (c *BitgetClient) CloseMarketData() error {
	if c.marketClient == nil {
		return nil
	}
	return c.marketClient.Close()
}

// SubscribeSpotTicker 订阅现货行情（使用公开行情客户端）
func (c *BitgetClient) SubscribeSpotTicker(symbol string, listener OnReceive) error {
	subscribeReq := SubscribeReq{
		InstType: "SPOT",
		Channel:  "ticker",
		InstId:   symbol,
	}
	return c.SubscribeMarketData([]SubscribeReq{subscribeReq}, listener)
}

// SubscribeFuturesTicker 订阅合约行情（使用公开行情客户端）
func (c *BitgetClient) SubscribeFuturesTicker(symbol string, listener OnReceive) error {
	subscribeReq := SubscribeReq{
		InstType: "UMCBL",
		Channel:  "ticker",
		InstId:   symbol,
	}
	return c.SubscribeMarketData([]SubscribeReq{subscribeReq}, listener)
}

// SubscribeSpotDepth 订阅现货深度（使用公开行情客户端）
func (c *BitgetClient) SubscribeSpotDepth(symbol string, listener OnReceive) error {
	subscribeReq := SubscribeReq{
		InstType: "SPOT",
		Channel:  "books",
		InstId:   symbol,
	}
	return c.SubscribeMarketData([]SubscribeReq{subscribeReq}, listener)
}

// SubscribeSpotTrades 订阅现货成交（使用公开行情客户端）
func (c *BitgetClient) SubscribeSpotTrades(symbol string, listener OnReceive) error {
	subscribeReq := SubscribeReq{
		InstType: "SPOT",
		Channel:  "trade",
		InstId:   symbol,
	}
	return c.SubscribeMarketData([]SubscribeReq{subscribeReq}, listener)
}

// SubscribeKline 订阅K线数据（使用公开行情客户端）
func (c *BitgetClient) SubscribeKline(symbol, interval string, listener OnReceive) error {
	subscribeReq := SubscribeReq{
		InstType: "SPOT",
		Channel:  "candle" + interval,
		InstId:   symbol,
	}
	return c.SubscribeMarketData([]SubscribeReq{subscribeReq}, listener)
}
