package option

import (
	"context"
	"encoding/json"
	"github.com/redis/go-redis/v9"
	"github.com/shopspring/decimal"
	"matchmaking-system/internal/biz/structure"
	"matchmaking-system/internal/data/memory"
	"matchmaking-system/internal/pkg/flags"
	"matchmaking-system/internal/pkg/logging/applogger"
	"matchmaking-system/internal/pkg/logging/common"
	"matchmaking-system/internal/pkg/setting"
	"matchmaking-system/internal/pkg/utils"
	"time"
)

/*
处理印度期权股下单交易(订单状态:0-挂单(委托),1-持仓订单,2-已撤单,3-完成订单)
1>写入挂单缓存列表
2>监控挂单缓存列表
3>监控持仓缓存列表
4>处理完成订单
5>清理缓存列表
*/

// OptionInrTallyCache
// @Description:
type OptionInrTallyCache struct {
	UserId       int64                // 用户ID
	OrderId      string               // 订单ID
	Symbol       string               // 交易对
	Status       string               // 订单状态
	OpenPrice    string               // 开仓价格
	ClosingPrice string               // 平仓价格
	ClosingTime  time.Time            // 平仓时间
	Order        structure.ShareOrder // 下单信息
}

// OptionInrCacheDeal
//
//	@Description:
//	@param ctx
//	@param userId
//	@param orderId
//	@param subKey
//	@param order
//	@param chg
//	@param priceNew
//	@param closingTime
//	@return string
//	@return *OptionInrTallyCache
//	@return error
func OptionInrCacheDeal(ctx context.Context, userId int64, orderId string, order structure.ShareOrder) (string, *OptionInrTallyCache, error) {
	var marketStatus string
	tallyCache := OptionInrTallyCache{
		UserId:  userId,        // 股票期权下单用户Id
		OrderId: orderId,       // 股票期权下单订单Id
		Symbol:  order.StockId, // 股票期权下单交易对
		Status:  flags.Entrust, // 股票期权下单挂单状态
		Order:   order,         // 股票期权完整下单信息
	}

	// 股票期权到期时间
	closingTime, err := utils.TimeStopTime(order.StopTime)
	if err == nil {
		tallyCache.ClosingTime = closingTime
	}

	// 股票期权缓存状态
	marketStatus = setting.MarketOptionInrEntrust

	return marketStatus, &tallyCache, nil
}

// GetOptionOrderInrByChg
//
//	@Description: 处理涨跌幅
//	@param priceNew
//	@param tallyCache
//	@param chg
//	@return string
//	@return OptionInrTallyCache
func GetOptionOrderInrByChg(priceNew string, tallyCache OptionInrTallyCache, chg string) (string, OptionInrTallyCache) {
	var marketStatus string
	switch chg {
	case flags.UpLimit: // 涨停
		switch tallyCache.Order.TradeType {
		case flags.TradeTypeBuy: // 买涨:涨停-下单不到持仓,可以平仓
			if !flags.CheckSetting {
				applogger.Debug("下单股票买涨涨停,只能挂单......")
			}
			marketStatus = setting.MarketOptionInrEntrust
		case flags.TradeTypeSell: // 买跌:涨停-下单到持仓,不能平仓
			marketStatus, tallyCache = GetOptionOrderInrMarketPrice(priceNew, tallyCache)
		default:
			marketStatus = setting.MarketOptionInrEntrust
		}
	case flags.DownLimit: // 跌停
		switch tallyCache.Order.TradeType {
		case flags.TradeTypeBuy: // 买涨:跌停-下单到持仓,不能平仓
			marketStatus, tallyCache = GetOptionOrderInrMarketPrice(priceNew, tallyCache)
		case flags.TradeTypeSell: // 买跌:跌停-下单不到持仓,可以平仓
			if !flags.CheckSetting {
				applogger.Debug("下单股票买跌跌停,只能挂单......")
			}
			marketStatus = setting.MarketOptionInrEntrust
		default:
			marketStatus = setting.MarketOptionInrEntrust
		}
	default:
		marketStatus, tallyCache = GetOptionOrderInrMarketPrice(priceNew, tallyCache)
	}

	return marketStatus, tallyCache
}

// CheckOptionInrOrderByChg
//
//	@Description: 股票期权判定涨跌幅业务逻辑
//	@param orderMarket
//	@param tallyCache
//	@param chg
//	@return bool
func CheckOptionInrOrderByChg(orderMarket string, tallyCache OptionInrTallyCache, chg string) bool {
	var checkBool bool
	switch chg {
	case flags.UpLimit: // 涨停
		switch tallyCache.Order.TradeType {
		case flags.TradeTypeBuy: // 买涨:涨停-下单不到持仓,持仓可以平仓
			checkBool = CheckOptionOrderInrBuyMarket(orderMarket)
		case flags.TradeTypeSell: // 买跌:涨停-下单到持仓,持仓不能平仓
			checkBool = CheckOptionOrderInrSellMarket(orderMarket)
		}
	case flags.DownLimit: // 跌停
		switch tallyCache.Order.TradeType {
		case flags.TradeTypeBuy: // 买涨:跌停-下单到持仓,持仓不能平仓
			checkBool = CheckOptionOrderInrSellMarket(orderMarket)
		case flags.TradeTypeSell: // 买跌:跌停-下单不到持仓,持仓可以平仓
			checkBool = CheckOptionOrderInrBuyMarket(orderMarket)
		}
	default:
		checkBool = false
	}

	return checkBool
}

// CheckOptionOrderInrBuyMarket
//
//	@Description: 买涨-涨跌幅
//	@param orderMarket
//	@return bool
func CheckOptionOrderInrBuyMarket(orderMarket string) bool {
	var checkBool bool
	switch orderMarket {
	case setting.MarketOptionInrEntrust: // 挂单缓存状态--不到持仓
		checkBool = true
	case setting.MarketOptionInrPosition: // 持仓缓存状态--可以平仓
		checkBool = false
	}

	return checkBool
}

// CheckOptionOrderInrSellMarket
//
//	@Description: 买跌-涨跌幅
//	@param orderMarket
//	@return bool
func CheckOptionOrderInrSellMarket(orderMarket string) bool {
	var checkBool bool
	switch orderMarket {
	case setting.MarketOptionInrEntrust: // 挂单缓存状态-- 到持仓
		checkBool = false
	case setting.MarketOptionInrPosition: // 持仓缓存状态-- 不能平仓
		checkBool = true
	}

	return checkBool
}

// GetOptionOrderInrMarketPrice
//
//	@Description: 市价下单开仓信息
//	@param priceNew
//	@param tallyCache
//	@return string
//	@return OptionInrTallyCache
func GetOptionOrderInrMarketPrice(priceNew string, tallyCache OptionInrTallyCache) (string, OptionInrTallyCache) {
	var marketStatus string
	tallyCache.OpenPrice = decimal.RequireFromString(priceNew).String() // 股票期权市价下单开盘价格(price)
	tallyCache.Status = flags.Position                                  // 股票期权市价下单持仓状态(status)
	marketStatus = setting.MarketOptionInrPosition                      // 股票期权下单状态(挂单|持仓)缓存列表

	return marketStatus, tallyCache
}

// OptionInrSubMarketPrice
//
//	@Description: 下单订阅行情数据
//	@param subKey
//	@return string
//	@return error
func OptionInrSubMarketPrice(subKey string) (string, error) {
	price, err := memory.GetOptionInrCache(subKey)
	if err != nil {
		return flags.SetNull, err
	}

	return string(price), nil
}

// OptionInrHashUserOrder
//
//	@Description: 下单录入订阅缓存列表(用户订阅|管理员订阅|挂单|持仓)
//	@param red
//	@param cacheKey
//	@param order
//	@return error
func OptionInrHashUserOrder(red *redis.Client, cacheKey string, order *OptionInrTallyCache) error {
	orderStr, err := json.Marshal(order)
	if err != nil {
		applogger.Error("%v OptionInrHashUserOrder.Marshal:%v", common.ErrOptionInr, err)
		return err
	}

	if err = red.HSet(context.Background(), cacheKey, order.OrderId, string(orderStr)).Err(); err != nil {
		applogger.Error("%v OptionInrHashUserOrder.HSet:%v", common.ErrOptionInr, err)
		return err
	}

	return nil
}

// UpdateOptionInrHashByOrderId
//
//	@Description: 更新缓存列表
//	@param reds
//	@param orderId
//	@param updateKey
//	@param status
//	@return error
func UpdateOptionInrHashByOrderId(reds *redis.Client, orderId, updateKey, status string) error {
	order, err := reds.HGet(context.Background(), updateKey, orderId).Result()
	if err != nil {
		return err
	}

	var orderModel OptionInrTallyCache
	if err = json.Unmarshal([]byte(order), &orderModel); err != nil {
		return err
	}

	orderModel.Status = status
	orderStr, err := json.Marshal(&orderModel)
	if err != nil {
		return err
	}

	err = reds.HSet(context.Background(), updateKey, orderId, string(orderStr)).Err()
	if err != nil {
		return err
	}
	return nil
}

// UpdateOptionInrStopByOrderId
//
//	@Description: 更新止盈止损设置
//	@param reds
//	@param order
//	@param updateKey
//	@param status
//	@return error
func UpdateOptionInrStopByOrderId(reds *redis.Client, order structure.StopOrder, updateKey, status string) error {
	orderHash, err := reds.HGet(context.Background(), updateKey, order.OrderId).Result()
	if err != nil {
		return err
	}

	var orderModel OptionInrTallyCache
	if err = json.Unmarshal([]byte(orderHash), &orderModel); err != nil {
		return err
	}

	orderModel.Status = status
	orderModel.Order.StopType = order.StopType
	orderModel.Order.StopLossPrice = order.StopLossPrice
	orderModel.Order.StopWinPrice = order.StopWinPrice

	orderStr, err := json.Marshal(&orderModel)
	if err != nil {
		return err
	}

	err = reds.HSet(context.Background(), updateKey, order.OrderId, string(orderStr)).Err()
	if err != nil {
		return err
	}
	return nil
}