package erms3

import (
	"mtp2_if/global/app"
	"mtp2_if/global/e"
	"mtp2_if/logger"
	"mtp2_if/models"
	"mtp2_if/pb"
	"mtp2_if/rediscli"
	"net/http"
	"strconv"
	"strings"

	"github.com/gin-gonic/gin"
	"github.com/golang/protobuf/proto"
)

// QueryBusinessInfoReq 查询业务请求.
type QueryBusinessInfoReq struct {
	Accountids string `form:"accountids" binding:"required"` // 资金账号ID列表,逗号分隔.
	Status     int32  `form:"status"`                        // 合同状态,0-未结束 1-已结束.
}

// QueryBusinessInfoRsp 查询业务响应.
type QueryBusinessInfoRsp struct {
	BusinessID      int64   `json:"businessid"`      // 业务ID.
	Type            int32   `json:"type"`            // 业务类型,1-期现套利,2-仓单回购,3-现货贸易.
	GoodsID         string  `json:"goodsid"`         // 商品名称/商品代码.
	Buyqty          string  `json:"buyqty"`          // 采购量.
	BuyAmount       float64 `json:"buyamount"`       // 采购额.
	Sellqty         string  `json:"sellqty"`         // 销售量.
	SellAmount      float64 `json:"sellamount"`      // 销售额.
	Spotqty         string  `json:"spotqty"`         // 现货量.
	SpotMarketValue float64 `json:"spotmarketvalue"` // 现货市值.
	Hedgingqty      string  `json:"hedgingqty"`      // 套保量.
	Spotpl          float64 `json:"spotpl"`          // 浮动权益.
	Futureqty       string  `json:"futureqty"`       // 期货敞口.
	Futurepl        float64 `json:"futurepl"`        // 期货盈亏.
	Totalqty        string  `json:"totalqty"`        // 总敞口.
	Totalpl         float64 `json:"totalpl"`         // 总盈亏.
	Status          int32   `json:"statu"`           // 状态,0-未结束 1-已结束.
}

// QueryBusinessInfo 查询业务数据
// @Summary 查询业务表单数据
// @Produce json
// @Security ApiKeyAuth
// @Param accountids query string true "资金账号ID列表,用逗号分隔"
// @Param status query int true "状态,0为未结束 1为已结束"
// @Success 200 {array} QueryBusinessInfoRsp
// @Failure 500 {object} app.Response
// @Router /Erms3/QueryBusinessInfo [get]
// @Tags 风险管理v3
func QueryBusinessInfo(c *gin.Context) {
	appG := app.Gin{C: c}

	// 获取请求参数
	var req QueryBusinessInfoReq
	err := appG.C.ShouldBindQuery(&req)
	if err != nil {
		logger.GetLogger().Errorf("QueryBusinessInfo failed: %s", err.Error())
		appG.Response(http.StatusBadRequest, e.INVALID_PARAMS, nil)

		return
	}

	// 获取商品信息.
	goods, err := models.GetDeliverGoods()
	if err != nil {
		logger.GetLogger().Errorf("query deliverygoods failed: %s", err.Error())
		appG.Response(http.StatusBadRequest, e.ERROR_GET_GOODS_FAILED, nil)

		return
	}

	// 转换格式.
	id2goods := make(map[int32]models.Deliverygoods, len(goods))
	for i := range goods {
		id2goods[goods[i].Deliverygoodsid] = goods[i]
	}

	// 获取枚举信息.
	enuminfo, err := models.GetEnumDicItem("goodsunit", 0)
	if err != nil {
		logger.GetLogger().Errorf("query enumifno failed: %s", err.Error())
		appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)

		return
	}

	// 转换格式.
	id2enum := make(map[int64]models.Enumdicitem)
	for i := range enuminfo {
		id2enum[enuminfo[i].Enumitemname] = enuminfo[i]
	}

	// 查询期现套利业务.
	var asa models.Erms2Arbitragestrategy
	asainfo, err := asa.GetByAccountIDSAndStatus(req.Accountids, req.Status)
	if err != nil {
		logger.GetLogger().Errorf("query asainfo failed: %s", err.Error())
		appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)

		return
	}

	redisClient := rediscli.GetRedisClient()
	preKey := "Erms2_ArbitrageStrategy:"
	rsp := make([]QueryBusinessInfoRsp, 0, len(asainfo))
	for i := range asainfo {
		key := preKey + asainfo[i].Asapplyid
		redisMsg := pb.Erms2ArbitrageStrategy{}
		redisRsp, err := redisClient.Get(key).Result()
		if err != nil {
			logger.GetLogger().Errorf("redis query arbitragestrategy failed: %s, key: %s", err.Error(), key)
		} else {
			err = proto.Unmarshal([]byte(redisRsp), &redisMsg)
			if err != nil {
				logger.GetLogger().Errorf("unmarshal arbitragestrategy failed: %s, key: %s", err.Error(), key)
			}
		}

		goodsinfo := id2goods[int32(asainfo[i].Deliverygoodsid)]
		goodsunit := id2enum[int64(goodsinfo.Goodsunitid)]
		businessid, err := strconv.ParseInt(asainfo[i].Asapplyid, 10, 64)
		if err != nil {
			logger.GetLogger().Errorf("parse string[%s] to int failed: %s", asainfo[i].Asapplyid, err.Error())
			appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)

			return
		}

		business := QueryBusinessInfoRsp{
			BusinessID:      businessid,
			Type:            1,
			GoodsID:         strings.Join([]string{goodsinfo.Deliverygoodsname, goodsinfo.Deliverygoodscode}, "/"),
			Buyqty:          strconv.FormatFloat(asainfo[i].Buyqty, 'f', 2, 64) + goodsunit.Enumdicname,
			BuyAmount:       asainfo[i].Buyamount,
			Sellqty:         strconv.FormatFloat(asainfo[i].Sellqty, 'f', 2, 64) + goodsunit.Enumdicname,
			SellAmount:      asainfo[i].Sellamount,
			Spotqty:         strconv.FormatFloat(asainfo[i].Pricedspotqty, 'f', 2, 64) + goodsunit.Enumdicname,
			SpotMarketValue: 0.0,
			Hedgingqty:      strconv.FormatFloat(asainfo[i].Futureqty, 'f', 2, 64) + goodsunit.Enumdicname,
			Spotpl:          redisMsg.GetSpotPL(),
			Futureqty:       strconv.FormatFloat(asainfo[i].Futureqty, 'f', 2, 64) + goodsunit.Enumdicname,
			Futurepl:        redisMsg.GetFuturePL(),
			Totalqty:        strconv.FormatFloat(asainfo[i].Pricedspotqty-asainfo[i].Futureqty, 'f', 2, 64) + goodsunit.Enumdicname,
			Totalpl:         redisMsg.GetTotalPL(),
			Status:          asainfo[i].Strategystatus,
		}

		rsp = append(rsp, business)
	}

	// 查询仓单回购业务.
	var wr models.Erms2Wrrcontract
	wrrcontracts, err := wr.GetByAccountIDSAndStatus(req.Accountids, req.Status)
	if err != nil {
		logger.GetLogger().Errorf("query wrrcontract failed: %s", err.Error())
		appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)

		return
	}

	for i := range wrrcontracts {
		goodsinfo := id2goods[int32(wrrcontracts[i].Deliverygoodsid)]
		goodsunit := id2enum[int64(goodsinfo.Goodsunitid)]
		businessid, err := strconv.ParseInt(wrrcontracts[i].Wrrcontractid, 10, 64)
		if err != nil {
			logger.GetLogger().Errorf("parse string[%s] to int failed: %s", asainfo[i].Asapplyid, err.Error())
			appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)

			return
		}

		business := QueryBusinessInfoRsp{
			BusinessID:      businessid,
			Type:            2,
			GoodsID:         strings.Join([]string{goodsinfo.Deliverygoodsname, goodsinfo.Deliverygoodscode}, "/"),
			Buyqty:          strconv.FormatFloat(wrrcontracts[i].Buyqty, 'f', 2, 64) + goodsunit.Enumdicname,
			BuyAmount:       wrrcontracts[i].Buyamount,
			Sellqty:         strconv.FormatFloat(wrrcontracts[i].Sellqty, 'f', 2, 64) + goodsunit.Enumdicname,
			SellAmount:      wrrcontracts[i].Sellamount,
			Spotqty:         strconv.FormatFloat(wrrcontracts[i].Contractqty, 'f', 2, 64) + goodsunit.Enumdicname,
			SpotMarketValue: 0,
			Hedgingqty:      "-",
			Spotpl:          0,
			Futureqty:       "-",
			Futurepl:        0,
			Totalqty:        "-",
			Totalpl:         0,
			Status:          wrrcontracts[i].Contractstatus,
		}

		rsp = append(rsp, business)
	}

	// 查询现货贸易业务.
	var sbt models.Erms2Spottradebiz
	spotTradeBiz, err := sbt.GetByAccountIDSAndStatus(req.Accountids, req.Status)
	if err != nil {
		logger.GetLogger().Errorf("query spottradebiz failed: %s", err.Error())
		appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)

		return
	}

	for i := range spotTradeBiz {
		goodsinfo := id2goods[int32(spotTradeBiz[i].Deliverygoodsid)]
		goodsunit := id2enum[int64(goodsinfo.Goodsunitid)]
		businessid, err := strconv.ParseInt(spotTradeBiz[i].Spottradeid, 10, 64)
		if err != nil {
			logger.GetLogger().Errorf("parse string[%s] to int failed: %s", asainfo[i].Asapplyid, err.Error())
			appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)

			return
		}

		business := QueryBusinessInfoRsp{
			BusinessID:      businessid,
			Type:            3,
			GoodsID:         strings.Join([]string{goodsinfo.Deliverygoodsname, goodsinfo.Deliverygoodscode}, "/"),
			Buyqty:          strconv.FormatFloat(spotTradeBiz[i].TradeBuyqty, 'f', 2, 64) + goodsunit.Enumdicname,
			BuyAmount:       spotTradeBiz[i].TradeBuyamount,
			Sellqty:         strconv.FormatFloat(spotTradeBiz[i].TradeSellqty, 'f', 2, 64) + goodsunit.Enumdicname,
			SellAmount:      spotTradeBiz[i].TradeSellamount,
			Spotqty:         strconv.FormatFloat(spotTradeBiz[i].Buyqty+spotTradeBiz[i].Sellqty, 'f', 2, 64) + goodsunit.Enumdicname,
			SpotMarketValue: 0,
			Hedgingqty:      "-",
			Spotpl:          0,
			Futureqty:       "-",
			Futurepl:        0,
			Totalqty:        "-",
			Totalpl:         0,
			Status:          spotTradeBiz[i].Closestatus,
		}

		rsp = append(rsp, business)
	}

	// 查询成功
	logger.GetLogger().Debugf("QuerySpotContractDetail successed: %v", rsp)
	appG.Response(http.StatusOK, e.SUCCESS, rsp)
}

// AddErms2ASApplyReq 新增期现套利业务申请请求参数
type AddErms2ASApplyReq struct {
	models.Erms2asapply
}

// AddErms2ASApply 新增期现套利业务申请
// @Summary 新增期现套利业务申请
// @Produce json
// @Security ApiKeyAuth
// @Param jsonBody body AddErms2ASApplyReq true "申请参数"
// @Success 200 {object} app.Response
// @Failure 500 {object} app.Response
// @Router /Erms3/AddErms2ASApply [post]
// @Tags 风险管理v3
func AddErms2ASApply(c *gin.Context) {
	appG := app.Gin{C: c}

	// 获取请求参数
	var req AddErms2ASApplyReq
	err := appG.C.ShouldBindJSON(&req)
	if err != nil {
		logger.GetLogger().Errorf("AddErms2ASApply failed: %s", err.Error())
		appG.Response(http.StatusBadRequest, e.INVALID_PARAMS, nil)
		return
	}

	// 插入数据
	if err := models.InsertErms2AsApply(req.Erms2asapply); err != nil {
		logger.GetLogger().Errorf("AddErms2ASApply failed: %s", err.Error())
		appG.Response(http.StatusBadRequest, e.ERROR_OPERATION_FAILED, nil)
		return
	}

	// 执行成功
	logger.GetLogger().Debugf("AddErms2ASApply successed: ok")
	appG.Response(http.StatusOK, e.SUCCESS, "ok")
}

// AddErms2SpotTradeApplyReq 新增期现套利业务申请请求参数
type AddErms2SpotTradeApplyReq struct {
	models.Erms2spottradeapply
}

// AddErms2SpotTradeApply 新增现货贸易业务申请
// @Summary 新增现货贸易业务申请
// @Produce json
// @Security ApiKeyAuth
// @Param jsonBody body AddErms2SpotTradeApplyReq true "申请参数"
// @Success 200 {object} app.Response
// @Failure 500 {object} app.Response
// @Router /Erms3/AddErms2SpotTradeApply [post]
// @Tags 风险管理v3
func AddErms2SpotTradeApply(c *gin.Context) {
	appG := app.Gin{C: c}

	// 获取请求参数
	var req AddErms2SpotTradeApplyReq
	err := appG.C.ShouldBindJSON(&req)
	if err != nil {
		logger.GetLogger().Errorf("AddErms2SpotTradeApply failed: %s", err.Error())
		appG.Response(http.StatusBadRequest, e.INVALID_PARAMS, nil)
		return
	}

	// 插入数据
	if err := models.InsertErms2SpotTradeApply(req.Erms2spottradeapply); err != nil {
		logger.GetLogger().Errorf("AddErms2SpotTradeApply failed: %s", err.Error())
		appG.Response(http.StatusBadRequest, e.ERROR_OPERATION_FAILED, nil)
		return
	}

	// 执行成功
	logger.GetLogger().Debugf("AddErms2SpotTradeApply successed: ok")
	appG.Response(http.StatusOK, e.SUCCESS, "ok")
}
