package ermcp

import (
	"mtp2_if/global/app"
	"mtp2_if/global/e"
	"mtp2_if/logger"
	"mtp2_if/models"
	"mtp2_if/utils"
	"net/http"
	"strconv"

	"github.com/gin-gonic/gin"
)

// QueryErmcpTradePositionReq 获取企业风管期货持仓头寸信息请求参数
type QueryErmcpTradePositionReq struct {
	AccountID int `form:"accountID" binding:"required"`
	MarketID  int `form:"marketID"`
}

// QueryErmcpTradePositionRsp 获取企业风管期货持仓头寸信息返回模型
type QueryErmcpTradePositionRsp struct {
	Goodsname            string  `json:"goodsname"`            // 商品名称
	BuyOrSell            int64   `json:"buyorsell"`            // 方向 - 0:买 1:卖
	EnableQTY            int64   `json:"enableqty"`            // 可用（总仓可用）
	CurPositionQTY       int64   `json:"curpositionqty"`       // 持仓（总仓数量, 期末头寸）
	Last                 float64 `json:"last"`                 // 现价
	CurTDPosition        int64   `json:"curtdposition"`        // 今仓数量（期末今日头寸）
	CurTDPositionEnabled int64   `json:"curtdpositionenabled"` // 今仓可用
	PositionAveragePrice float64 `json:"positionaverageprice"` // 持仓均价【头寸变化更新】= 持仓成本 / 期末头寸 / 合约单位
	OpenAveragePrice     float64 `json:"openaverageprice" `    // 开仓均价【头寸变化更新】 = 开仓成本 / 期末头寸 / 合约单位
	PositionPL           float64 `json:"positionpl"`           // 盯市浮盈【实时行情更新】（MTP：浮动盈亏、持仓盈亏） 买方向 = (最新价 - 持仓均价) * 买期末头寸 * 合约单位；卖方向 = (持仓均价 - 最新价) * 卖期末头寸 * 合约单位
	OpenPL               float64 `json:"openpl"`               // 逐笔浮盈【实时行情更新】（MTP：开仓盈亏、平仓盈亏） 买方向 = (最新价 - 开仓均价) * 买期末头寸 * 合约单位；卖方向 = (开仓均价 - 最新价) * 卖期末头寸 * 合约单位
	PositionPLRate       float64 `json:"positionplrate"`       // 持仓盈亏比例【实时行情更新】 = 持仓盈亏 / 开仓成本
	UsedMargin           float64 `json:"usedmargin"`           // 占用保证金
	ExExehangeName       string  `json:"exexchangename"`       // 外部交易所名称
	OpenCost             float64 `json:"opencost"`             // 开仓成本
	PositionCost         float64 `json:"positioncost"`         // 持仓成本
	Goodsid              int64   `json:"goodsid"`              // 商品ID(自增ID SEQ_GOODS)
	Goodscode            string  `json:"goodscode"`            // 商品代码(内部)
	Outgoodscode         string  `json:"outgoodscode"`         // 商品代码(外部)
	Agreeunit            float64 `json:"agreeunit"`            // 合约单位
	Decimalplace         int64   `json:"decimalplace"`         // 报价小数位
	Marketid             int64   `json:"marketid"`             // 所属市场ID
}

// QueryErmcpTradePosition 获取企业风管期货持仓头寸信息
// @Summary 获取企业风管期货持仓头寸信息
// @Description 本接口只使用于通道交易相关头寸查询；子账户持仓头寸占用保证金为0；
// @Produce json
// @Security ApiKeyAuth
// @Param accountID query int true "资金账户ID"
// @Param marketID query int false "所属市场ID"
// @Success 200 {object} QueryErmcpTradePositionRsp
// @Failure 500 {object} app.Response
// @Router /Ermcp/QueryErmcpTradePosition [get]
// @Tags 企业风险管理(app)
func QueryErmcpTradePosition(c *gin.Context) {
	appG := app.Gin{C: c}

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

	rsp := make([]QueryErmcpTradePositionRsp, 0)

	// 获取资金账户信息
	taAccount, err := models.GetTaAccountByID(req.AccountID)
	if err != nil {
		logger.GetLogger().Errorf("QueryErmcpTradePosition failed: %s", err.Error())
		appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
		return
	}
	if taAccount == nil {
		logger.GetLogger().Errorf("QueryErmcpTradePosition failed")
		appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
		return
	}

	if taAccount.Ismain == 1 {
		// 母账户，从HEDGE_OUTTRADEPOSITION表查询持仓头寸（未生成内部头寸）
		hedgeOutTradePositions, err := models.GetHedgeOutTradePositions(req.AccountID, req.MarketID)
		if err != nil {
			// 查询失败
			logger.GetLogger().Errorf("QueryErmcpTradePosition failed: %s", err.Error())
			appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
			return
		}
		// 分解买卖方向的头寸
		for _, v := range hedgeOutTradePositions {
			// 分解买卖方向的头寸
			if v.Curbuyposition > 0 {
				// 买方向
				item := QueryErmcpTradePositionRsp{
					BuyOrSell:            0,
					EnableQTY:            v.Curbuyposition - v.Fretdbuyposition - v.Freydbuyposition, // 买可用 = 期末买头寸 - 冻结今日买头寸 - 冻结上日买头寸
					CurPositionQTY:       v.Curbuyposition,
					CurTDPosition:        v.Curtdbuyposition,
					CurTDPositionEnabled: v.Curtdbuyposition - v.Fretdbuyposition, // 今仓买可用 = 期末今日买头寸 - 冻结今日买头寸
					UsedMargin:           v.Buyusemargin,
					OpenCost:             v.Buyopencost,
					PositionCost:         v.Buypositioncost,
					Goodsid:              v.Hedgegoodsid,
					Marketid:             int64(v.Marketid),
				}
				// 获取对应商品信息
				goods, err := models.GetGoods(int(v.Hedgegoodsid))
				if err != nil {
					// 查询失败
					logger.GetLogger().Errorf("QueryErmcpTradePosition failed: %s", err.Error())
					appG.Response(http.StatusBadRequest, e.ERROR_GET_GOODS_FAILED, nil)
					return
				}
				if goods == nil {
					logger.GetLogger().Errorf("QueryErmcpTradePosition failed")
					appG.Response(http.StatusBadRequest, e.ERROR_GET_GOODS_FAILED, nil)
					return
				}
				item.Goodscode = goods.Goodscode
				item.Outgoodscode = goods.Outgoodscode
				item.Goodsname = goods.Goodsname
				item.Agreeunit = goods.Agreeunit
				item.Decimalplace = goods.Decimalplace
				// 获取对应外部交易所名称
				exchange, err := models.GetExternalexchangeByGoodsGroupID(int(goods.Goodsgroupid))
				if err != nil {
					// 查询失败
					logger.GetLogger().Errorf("QueryErmcpTradePosition failed: %s", err.Error())
					appG.Response(http.StatusBadRequest, e.ERROR_GET_EXEXCHANGE_FAILED, nil)
					return
				}
				if exchange == nil {
					logger.GetLogger().Errorf("QueryErmcpTradePosition failed")
					appG.Response(http.StatusBadRequest, e.ERROR_GET_EXEXCHANGE_FAILED, nil)
					return
				}
				item.ExExehangeName = exchange.Exchangefullname
				// 获取对应商品盘面信息
				quoteDays, err := models.GetQuoteDays("'" + goods.Outgoodscode + "'")
				if err != nil {
					logger.GetLogger().Errorf("QueryErmcpTradePosition failed: %s", err.Error())
					appG.Response(http.StatusBadRequest, e.ERROR_GET_QUOTE_FAILED, nil)
					return
				}
				if len(quoteDays) > 0 {
					if quoteDays[0].Last != 0 {
						item.Last = utils.IntToFloat64(int(quoteDays[0].Last), int(goods.Decimalplace))
					}
					// 没有现价则尝试用昨结
					if item.Last == 0 && quoteDays[0].Presettle != 0 {
						item.Last = utils.IntToFloat64(int(quoteDays[0].Presettle), int(goods.Decimalplace))
					}
				}
				// 计算价格与盈亏
				// 开仓均价 = 开仓成本 / 期末头寸 / 合约单位
				item.OpenAveragePrice = v.Buyopencost / float64(v.Curbuyposition) / goods.Agreeunit
				item.OpenAveragePrice, _ = strconv.ParseFloat(utils.FormatFloat(item.OpenAveragePrice, int(goods.Decimalplace)), 64)
				// 持仓均价 = 持仓成本 / 期末头寸 / 合约单位
				item.PositionAveragePrice = v.Buypositioncost / float64(v.Curbuyposition) / goods.Agreeunit
				item.PositionAveragePrice, _ = strconv.ParseFloat(utils.FormatFloat(item.PositionAveragePrice, int(goods.Decimalplace)), 64)
				// 盯市浮盈【实时行情更新】（MTP：浮动盈亏、持仓盈亏） 买方向 = (最新价 - 持仓均价) * 买期末头寸 * 合约单位；卖方向 = (持仓均价 - 最新价) * 卖期末头寸 * 合约单位
				if item.Last != 0 {
					item.PositionPL = (item.Last - item.PositionAveragePrice) * float64(v.Curbuyposition) * goods.Agreeunit
					item.PositionPL, _ = strconv.ParseFloat(utils.FormatFloat(item.PositionPL, 2), 64)
				}
				// 逐笔浮盈【实时行情更新】（MTP：开仓盈亏、平仓盈亏） 买方向 = (最新价 - 开仓均价) * 买期末头寸 * 合约单位；卖方向 = (开仓均价 - 最新价) * 卖期末头寸 * 合约单位
				if item.Last != 0 {
					item.OpenPL = (item.Last - item.OpenAveragePrice) * float64(v.Curbuyposition) * goods.Agreeunit
					item.OpenPL, _ = strconv.ParseFloat(utils.FormatFloat(item.OpenPL, 2), 64)
				}
				// 持仓盈亏比例 = 持仓盈亏 / 开仓成本
				if item.PositionPL != 0 && v.Buyopencost != 0 {
					item.PositionPLRate = item.PositionPL / v.Buyopencost
					item.PositionPLRate, _ = strconv.ParseFloat(utils.FormatFloat(item.PositionPLRate, 4), 64)
				}

				rsp = append(rsp, item)
			}
			if v.Cursellposition > 0 {
				// 卖方向
				item := QueryErmcpTradePositionRsp{
					BuyOrSell:            1,
					EnableQTY:            v.Cursellposition - v.Fretdsellposition - v.Freydsellposition,
					CurPositionQTY:       v.Cursellposition,
					CurTDPosition:        v.Curtdsellposition,
					CurTDPositionEnabled: v.Curtdsellposition - v.Fretdsellposition,
					UsedMargin:           v.Sellusemargin,
					OpenCost:             v.Sellopencost,
					PositionCost:         v.Sellpositioncost,
					Goodsid:              v.Hedgegoodsid,
					Marketid:             int64(v.Marketid),
				}
				// 获取对应商品信息
				goods, err := models.GetGoods(int(v.Hedgegoodsid))
				if err != nil {
					// 查询失败
					logger.GetLogger().Errorf("QueryErmcpTradePosition failed: %s", err.Error())
					appG.Response(http.StatusBadRequest, e.ERROR_GET_GOODS_FAILED, nil)
					return
				}
				if goods == nil {
					logger.GetLogger().Errorf("QueryErmcpTradePosition failed")
					appG.Response(http.StatusBadRequest, e.ERROR_GET_GOODS_FAILED, nil)
					return
				}
				item.Goodscode = goods.Goodscode
				item.Outgoodscode = goods.Outgoodscode
				item.Goodsname = goods.Goodsname
				item.Agreeunit = goods.Agreeunit
				item.Decimalplace = goods.Decimalplace
				// 获取对应外部交易所名称
				exchange, err := models.GetExternalexchangeByGoodsGroupID(int(goods.Goodsgroupid))
				if err != nil {
					// 查询失败
					logger.GetLogger().Errorf("QueryErmcpTradePosition failed: %s", err.Error())
					appG.Response(http.StatusBadRequest, e.ERROR_GET_EXEXCHANGE_FAILED, nil)
					return
				}
				if exchange == nil {
					logger.GetLogger().Errorf("QueryErmcpTradePosition failed")
					appG.Response(http.StatusBadRequest, e.ERROR_GET_EXEXCHANGE_FAILED, nil)
					return
				}
				item.ExExehangeName = exchange.Exchangefullname
				// 获取对应商品盘面信息
				quoteDays, err := models.GetQuoteDays("'" + goods.Outgoodscode + "'")
				if err != nil {
					logger.GetLogger().Errorf("QueryErmcpTradePosition failed: %s", err.Error())
					appG.Response(http.StatusBadRequest, e.ERROR_GET_QUOTE_FAILED, nil)
					return
				}
				if len(quoteDays) > 0 {
					if quoteDays[0].Last != 0 {
						item.Last = utils.IntToFloat64(int(quoteDays[0].Last), int(goods.Decimalplace))
					}
					// 没有现价则尝试用昨结
					if item.Last == 0 && quoteDays[0].Presettle != 0 {
						item.Last = utils.IntToFloat64(int(quoteDays[0].Presettle), int(goods.Decimalplace))
					}
				}
				// 计算价格与盈亏
				// 开仓均价 = 开仓成本 / 期末头寸 / 合约单位
				item.OpenAveragePrice = v.Sellopencost / float64(v.Cursellposition) / goods.Agreeunit
				item.OpenAveragePrice, _ = strconv.ParseFloat(utils.FormatFloat(item.OpenAveragePrice, int(goods.Decimalplace)), 64)
				// 持仓均价 = 持仓成本 / 期末头寸 / 合约单位
				item.PositionAveragePrice = v.Sellpositioncost / float64(v.Cursellposition) / goods.Agreeunit
				item.PositionAveragePrice, _ = strconv.ParseFloat(utils.FormatFloat(item.PositionAveragePrice, int(goods.Decimalplace)), 64)
				// 盯市浮盈【实时行情更新】（MTP：浮动盈亏、持仓盈亏） 买方向 = (最新价 - 持仓均价) * 买期末头寸 * 合约单位；卖方向 = (持仓均价 - 最新价) * 卖期末头寸 * 合约单位
				if item.Last != 0 {
					item.PositionPL = (item.PositionAveragePrice - item.Last) * float64(v.Cursellposition) * goods.Agreeunit
					item.PositionPL, _ = strconv.ParseFloat(utils.FormatFloat(item.PositionPL, 2), 64)
				}
				// 逐笔浮盈【实时行情更新】（MTP：开仓盈亏、平仓盈亏） 买方向 = (最新价 - 开仓均价) * 买期末头寸 * 合约单位；卖方向 = (开仓均价 - 最新价) * 卖期末头寸 * 合约单位
				if item.Last != 0 {
					item.OpenPL = (item.OpenAveragePrice - item.Last) * float64(v.Cursellposition) * goods.Agreeunit
					item.OpenPL, _ = strconv.ParseFloat(utils.FormatFloat(item.OpenPL, 2), 64)
				}
				// 持仓盈亏比例 = 持仓盈亏 / 开仓成本
				if item.PositionPL != 0 && v.Sellopencost != 0 {
					item.PositionPLRate = item.PositionPL / v.Sellopencost
					item.PositionPLRate, _ = strconv.ParseFloat(utils.FormatFloat(item.PositionPLRate, 4), 64)
				}

				rsp = append(rsp, item)
			}
		}
	} else {
		// 子账户
		tradePositions, err := models.GetTradePositions(req.AccountID, req.MarketID)
		if err != nil {
			// 查询失败
			logger.GetLogger().Errorf("QueryErmcpTradePosition failed: %s", err.Error())
			appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
			return
		}
		// 分解买卖方向的头寸
		for _, v := range tradePositions {
			if v.Buycurpositionqty > 0 {
				// 买方向
				item := QueryErmcpTradePositionRsp{
					BuyOrSell:            0,
					EnableQTY:            v.Buycurpositionqty - v.Buyfrozenqty, // 买可用 = 买当前持仓总数量 - 买持仓冻结数量
					CurPositionQTY:       v.Buycurpositionqty,
					CurTDPosition:        v.Buycurtdposition,
					CurTDPositionEnabled: v.Buycurtdposition - v.Buyfretdposition, // 今仓买可用 = 期末今日买头寸 - 冻结今日买头寸
					Goodsid:              int64(v.Goodsid),
				}
				// 获取对应市场信息
				market, err := models.GetMarketByGoodsID(int(v.Goodsid))
				if err != nil {
					// 查询失败
					logger.GetLogger().Errorf("QueryErmcpTradePosition failed: %s", err.Error())
					appG.Response(http.StatusBadRequest, e.ERROR_GET_MARKET_FAILED, nil)
					return
				}
				if market == nil {
					logger.GetLogger().Errorf("QueryErmcpTradePosition failed")
					appG.Response(http.StatusBadRequest, e.ERROR_GET_MARKET_FAILED, nil)
					return
				}
				item.Marketid = int64(market.Marketid)
				// 获取对应商品信息
				goods, err := models.GetGoods(int(v.Goodsid))
				if err != nil {
					// 查询失败
					logger.GetLogger().Errorf("QueryErmcpTradePosition failed: %s", err.Error())
					appG.Response(http.StatusBadRequest, e.ERROR_GET_GOODS_FAILED, nil)
					return
				}
				if goods == nil {
					logger.GetLogger().Errorf("QueryErmcpTradePosition failed")
					appG.Response(http.StatusBadRequest, e.ERROR_GET_GOODS_FAILED, nil)
					return
				}
				item.Goodscode = goods.Goodscode
				item.Outgoodscode = goods.Outgoodscode
				item.Goodsname = goods.Goodsname
				item.Agreeunit = goods.Agreeunit
				item.Decimalplace = goods.Decimalplace
				// 获取对应外部交易所名称
				exchange, err := models.GetExternalexchangeByGoodsGroupID(int(goods.Goodsgroupid))
				if err != nil {
					// 查询失败
					logger.GetLogger().Errorf("QueryErmcpTradePosition failed: %s", err.Error())
					appG.Response(http.StatusBadRequest, e.ERROR_GET_EXEXCHANGE_FAILED, nil)
					return
				}
				if exchange == nil {
					logger.GetLogger().Errorf("QueryErmcpTradePosition failed")
					appG.Response(http.StatusBadRequest, e.ERROR_GET_EXEXCHANGE_FAILED, nil)
					return
				}
				item.ExExehangeName = exchange.Exchangefullname
				// 获取对应商品盘面信息
				quoteDays, err := models.GetQuoteDays("'" + goods.Outgoodscode + "'")
				if err != nil {
					logger.GetLogger().Errorf("QueryErmcpTradePosition failed: %s", err.Error())
					appG.Response(http.StatusBadRequest, e.ERROR_GET_QUOTE_FAILED, nil)
					return
				}
				if len(quoteDays) > 0 {
					if quoteDays[0].Last != 0 {
						item.Last = utils.IntToFloat64(int(quoteDays[0].Last), int(goods.Decimalplace))
					}
					// 没有现价则尝试用昨结
					if item.Last == 0 && quoteDays[0].Presettle != 0 {
						item.Last = utils.IntToFloat64(int(quoteDays[0].Presettle), int(goods.Decimalplace))
					}
				}
				// 子账户需要从内部持仓明细（通道）表汇总计划开仓成本和开仓均价
				hedgeInnerHolderDetails, _ := models.GetHedgeInnerHolderDetails(req.AccountID, int(item.Goodsid), 0)
				for _, detail := range hedgeInnerHolderDetails {
					// 开仓成本 = 建仓价 * 持仓数量 * 合约单位
					item.OpenCost += detail.Openprice * float64(detail.Holderqty) * goods.Agreeunit
				}
				// 开仓均价 = 开仓成本 / 期末头寸 / 合约单位
				item.OpenAveragePrice = item.OpenCost / float64(item.CurPositionQTY) / goods.Agreeunit
				item.OpenAveragePrice, _ = strconv.ParseFloat(utils.FormatFloat(item.OpenAveragePrice, int(goods.Decimalplace)), 64)
				// 持仓成本
				item.PositionCost = v.Buycurholderamount
				// 持仓均价 = 持仓成本 / 期末头寸 / 合约单位
				item.PositionAveragePrice = v.Buycurholderamount / float64(v.Buycurpositionqty) / goods.Agreeunit
				item.PositionAveragePrice, _ = strconv.ParseFloat(utils.FormatFloat(item.PositionAveragePrice, int(goods.Decimalplace)), 64)
				// 盯市浮盈【实时行情更新】（MTP：浮动盈亏、持仓盈亏） 买方向 = (最新价 - 持仓均价) * 买期末头寸 * 合约单位；卖方向 = (持仓均价 - 最新价) * 卖期末头寸 * 合约单位
				if item.Last != 0 {
					item.PositionPL = (item.Last - item.PositionAveragePrice) * float64(v.Buycurpositionqty) * goods.Agreeunit
					item.PositionPL, _ = strconv.ParseFloat(utils.FormatFloat(item.PositionPL, 2), 64)
				}
				// 逐笔浮盈【实时行情更新】（MTP：开仓盈亏、平仓盈亏） 买方向 = (最新价 - 开仓均价) * 买期末头寸 * 合约单位；卖方向 = (开仓均价 - 最新价) * 卖期末头寸 * 合约单位
				if item.Last != 0 {
					item.OpenPL = (item.Last - item.OpenAveragePrice) * float64(v.Buycurpositionqty) * goods.Agreeunit
					item.OpenPL, _ = strconv.ParseFloat(utils.FormatFloat(item.OpenPL, 2), 64)
				}
				// 持仓盈亏比例 = 持仓盈亏 / 开仓成本
				if item.PositionPL != 0 && item.OpenCost != 0 {
					item.PositionPLRate = item.PositionPL / item.OpenCost
					item.PositionPLRate, _ = strconv.ParseFloat(utils.FormatFloat(item.PositionPLRate, 4), 64)
				}

				rsp = append(rsp, item)
			}
			if v.Sellcurpositionqty > 0 {
				// 卖方向
				item := QueryErmcpTradePositionRsp{
					BuyOrSell:            1,
					EnableQTY:            v.Sellcurpositionqty - v.Sellfrozenqty, // 买可用 = 买当前持仓总数量 - 买持仓冻结数量
					CurPositionQTY:       v.Sellcurpositionqty,
					CurTDPosition:        v.Sellcurtdposition,
					CurTDPositionEnabled: v.Sellcurtdposition - v.Sellfretdposition, // 今仓买可用 = 期末今日买头寸 - 冻结今日买头寸
					Goodsid:              int64(v.Goodsid),
				}
				// 获取对应市场信息
				market, err := models.GetMarketByGoodsID(int(v.Goodsid))
				if err != nil {
					// 查询失败
					logger.GetLogger().Errorf("QueryErmcpTradePosition failed: %s", err.Error())
					appG.Response(http.StatusBadRequest, e.ERROR_GET_MARKET_FAILED, nil)
					return
				}
				if market == nil {
					logger.GetLogger().Errorf("QueryErmcpTradePosition failed")
					appG.Response(http.StatusBadRequest, e.ERROR_GET_MARKET_FAILED, nil)
					return
				}
				item.Marketid = int64(market.Marketid)
				// 获取对应商品信息
				goods, err := models.GetGoods(int(v.Goodsid))
				if err != nil {
					// 查询失败
					logger.GetLogger().Errorf("QueryErmcpTradePosition failed: %s", err.Error())
					appG.Response(http.StatusBadRequest, e.ERROR_GET_GOODS_FAILED, nil)
					return
				}
				if goods == nil {
					logger.GetLogger().Errorf("QueryErmcpTradePosition failed")
					appG.Response(http.StatusBadRequest, e.ERROR_GET_GOODS_FAILED, nil)
					return
				}
				item.Goodscode = goods.Goodscode
				item.Outgoodscode = goods.Outgoodscode
				item.Goodsname = goods.Goodsname
				item.Agreeunit = goods.Agreeunit
				item.Decimalplace = goods.Decimalplace
				// 获取对应外部交易所名称
				exchange, err := models.GetExternalexchangeByGoodsGroupID(int(goods.Goodsgroupid))
				if err != nil {
					// 查询失败
					logger.GetLogger().Errorf("QueryErmcpTradePosition failed: %s", err.Error())
					appG.Response(http.StatusBadRequest, e.ERROR_GET_EXEXCHANGE_FAILED, nil)
					return
				}
				if exchange == nil {
					logger.GetLogger().Errorf("QueryErmcpTradePosition failed")
					appG.Response(http.StatusBadRequest, e.ERROR_GET_EXEXCHANGE_FAILED, nil)
					return
				}
				item.ExExehangeName = exchange.Exchangefullname
				// 获取对应商品盘面信息
				quoteDays, err := models.GetQuoteDays("'" + goods.Outgoodscode + "'")
				if err != nil {
					logger.GetLogger().Errorf("QueryErmcpTradePosition failed: %s", err.Error())
					appG.Response(http.StatusBadRequest, e.ERROR_GET_QUOTE_FAILED, nil)
					return
				}
				if len(quoteDays) > 0 {
					if quoteDays[0].Last != 0 {
						item.Last = utils.IntToFloat64(int(quoteDays[0].Last), int(goods.Decimalplace))
					}
					// 没有现价则尝试用昨结
					if item.Last == 0 && quoteDays[0].Presettle != 0 {
						item.Last = utils.IntToFloat64(int(quoteDays[0].Presettle), int(goods.Decimalplace))
					}
				}
				// 子账户需要从内部持仓明细（通道）表汇总计划开仓成本和开仓均价
				hedgeInnerHolderDetails, _ := models.GetHedgeInnerHolderDetails(req.AccountID, int(item.Goodsid), 1)
				for _, detail := range hedgeInnerHolderDetails {
					// 开仓成本 = 建仓价 * 持仓数量 * 合约单位
					item.OpenCost += detail.Openprice * float64(detail.Holderqty) * goods.Agreeunit
				}
				// 开仓均价 = 开仓成本 / 期末头寸 / 合约单位
				item.OpenAveragePrice = item.OpenCost / float64(item.CurPositionQTY) / goods.Agreeunit
				item.OpenAveragePrice, _ = strconv.ParseFloat(utils.FormatFloat(item.OpenAveragePrice, int(goods.Decimalplace)), 64)
				// 持仓成本
				item.PositionCost = v.Sellcurholderamount
				// 持仓均价 = 持仓成本 / 期末头寸 / 合约单位
				item.PositionAveragePrice = v.Sellcurholderamount / float64(v.Sellcurpositionqty) / goods.Agreeunit
				item.PositionAveragePrice, _ = strconv.ParseFloat(utils.FormatFloat(item.PositionAveragePrice, int(goods.Decimalplace)), 64)
				// 盯市浮盈【实时行情更新】（MTP：浮动盈亏、持仓盈亏） 买方向 = (最新价 - 持仓均价) * 买期末头寸 * 合约单位；卖方向 = (持仓均价 - 最新价) * 卖期末头寸 * 合约单位
				if item.Last != 0 {
					item.PositionPL = (item.PositionAveragePrice - item.Last) * float64(v.Sellcurpositionqty) * goods.Agreeunit
					item.PositionPL, _ = strconv.ParseFloat(utils.FormatFloat(item.PositionPL, 2), 64)
				}
				// 逐笔浮盈【实时行情更新】（MTP：开仓盈亏、平仓盈亏） 买方向 = (最新价 - 开仓均价) * 买期末头寸 * 合约单位；卖方向 = (开仓均价 - 最新价) * 卖期末头寸 * 合约单位
				if item.Last != 0 {
					item.OpenPL = (item.OpenAveragePrice - item.Last) * float64(v.Sellcurpositionqty) * goods.Agreeunit
					item.OpenPL, _ = strconv.ParseFloat(utils.FormatFloat(item.OpenPL, 2), 64)
				}
				// 持仓盈亏比例 = 持仓盈亏 / 开仓成本
				if item.PositionPL != 0 && item.OpenCost != 0 {
					item.PositionPLRate = item.PositionPL / item.OpenCost
					item.PositionPLRate, _ = strconv.ParseFloat(utils.FormatFloat(item.PositionPLRate, 4), 64)
				}

				rsp = append(rsp, item)
			}
		}
	}

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

// QueryErmcpInnerHolderDetailsReq 获取企业风管期货内部持仓单信息请求参数
type QueryErmcpInnerHolderDetailsReq struct {
	AccountID int `form:"accountID" binding:"required"`
	GoodsID   int `form:"goodsID"`
	BuyOrSell int `form:"buyOrSell"`
}

// QueryErmcpInnerHolderDetails 获取企业风管期货内部持仓单信息
// @Summary 获取企业风管期货内部持仓单信息
// @Produce json
// @Security ApiKeyAuth
// @Param accountID query int true "资金账户ID"
// @Param goodsID query int false "商品ID"
// @Param buyOrSell query int false "买卖方向，0：买 1：卖"
// @Success 200 {object} models.Hedgeinnerholderdetail
// @Failure 500 {object} app.Response
// @Router /Ermcp/QueryErmcpInnerHolderDetails [get]
// @Tags 企业风险管理(app)
func QueryErmcpInnerHolderDetails(c *gin.Context) {
	appG := app.Gin{C: c}

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

	var r models.Hedgeinnerholderdetail
	rst, err := r.GetList(req.AccountID, req.GoodsID, req.BuyOrSell)
	if err != nil {
		logger.GetLogger().Errorf("QueryErmcpInnerHolderDetails failed: %s", err.Error())
		appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
		return
	}

	// 查询成功返回
	logger.GetLogger().Debugln("QueryErmcpInnerHolderDetails successed: %v", rst)
	appG.Response(http.StatusOK, e.SUCCESS, rst)
}

// QueryErmcpOrderDetailsReq 获取企业风管期货委托单信息请求参数
type QueryErmcpOrderDetailsReq struct {
	AccountID int `form:"accountID" binding:"required"`
}

// QueryErmcpOrderDetails 获取企业风管期货委托单信息
// @Summary 获取企业风管期货委托单信息
// @Produce json
// @Security ApiKeyAuth
// @Param accountID query int true "资金账户ID"
// @Success 200 {object} models.QueryHedgeOrderDetailRsp
// @Failure 500 {object} app.Response
// @Router /Ermcp/QueryErmcpOrderDetails [get]
// @Tags 企业风险管理(app)
func QueryErmcpOrderDetails(c *gin.Context) {
	appG := app.Gin{C: c}

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

	// 获取资金账户信息
	taAccount, err := models.GetTaAccountByID(req.AccountID)
	if err != nil {
		logger.GetLogger().Errorf("QueryErmcpOrderDetails failed: %s", err.Error())
		appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
		return
	}
	if taAccount == nil {
		logger.GetLogger().Errorf("QueryErmcpOrderDetails failed")
		appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
		return
	}

	rst := make([]models.QueryHedgeOrderDetailRsp, 0)
	if taAccount.Ismain == 1 {
		// 母账户 -> 外部委托单
		rst, err = models.GetHedgeOutOrderDetails(req.AccountID)
		if err != nil {
			// 查询失败
			logger.GetLogger().Errorf("QueryErmcpOrderDetails failed: %s", err.Error())
			appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
			return
		}
	} else {
		// 子账户 -> 内部委托单
		rst, err = models.GetHedgeInnerOrderDetails(req.AccountID)
		if err != nil {
			// 查询失败
			logger.GetLogger().Errorf("QueryErmcpOrderDetails failed: %s", err.Error())
			appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
			return
		}
	}

	// 查询成功返回
	logger.GetLogger().Debugln("QueryErmcpOrderDetails successed: %v", rst)
	appG.Response(http.StatusOK, e.SUCCESS, rst)
}

// QueryErmcpHisOrderDetailsReq 获取企业风管期货历史委托单信息请求参数
type QueryErmcpHisOrderDetailsReq struct {
	AccountID int    `form:"accountID" binding:"required"`
	StartDate string `form:"startDate"` // 开始时间
	EndDate   string `form:"endDate"`   // 结束时间
}

// QueryErmcpHisOrderDetails 获取企业风管期货历史委托单信息
// @Summary 获取企业风管期货历史委托单信息
// @Produce json
// @Security ApiKeyAuth
// @Param accountID query int true "资金账户ID"
// @Param startDate query string false "开始时间 - 闭区间，格式：yyyy-MM-dd"
// @Param endDate query string false "结束时间 - 闭区间，格式：yyyy-MM-dd"
// @Success 200 {object} models.QueryHedgeOrderDetailRsp
// @Failure 500 {object} app.Response
// @Router /Ermcp/QueryErmcpHisOrderDetails [get]
// @Tags 企业风险管理(app)
func QueryErmcpHisOrderDetails(c *gin.Context) {
	appG := app.Gin{C: c}

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

	// 获取资金账户信息
	taAccount, err := models.GetTaAccountByID(req.AccountID)
	if err != nil {
		logger.GetLogger().Errorf("QueryErmcpHisOrderDetails failed: %s", err.Error())
		appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
		return
	}
	if taAccount == nil {
		logger.GetLogger().Errorf("QueryErmcpHisOrderDetails failed")
		appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
		return
	}

	rst := make([]models.QueryHedgeOrderDetailRsp, 0)
	if taAccount.Ismain == 1 {
		// 母账户 -> 外部历史委托单
		rst, err = models.GetHisHedgeOutOrderDetails(req.AccountID, req.StartDate, req.EndDate)
		if err != nil {
			// 查询失败
			logger.GetLogger().Errorf("QueryErmcpHisOrderDetails failed: %s", err.Error())
			appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
			return
		}
	} else {
		// 子账户 -> 内部历史委托单
		rst, err = models.GetHisHedgeInnerOrderDetails(req.AccountID, req.StartDate, req.EndDate)
		if err != nil {
			// 查询失败
			logger.GetLogger().Errorf("QueryErmcpHisOrderDetails failed: %s", err.Error())
			appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
			return
		}
	}

	// 查询成功返回
	logger.GetLogger().Debugln("QueryErmcpHisOrderDetails successed: %v", rst)
	appG.Response(http.StatusOK, e.SUCCESS, rst)
}

// QueryHedgeTradeDetailReq 获取企业风管期货成交单信息请求参数
type QueryHedgeTradeDetailReq struct {
	AccountID int `form:"accountID" binding:"required"`
	GoodsID   int `form:"goodsID"`
	BuyOrSell int `form:"buyOrSell"`
	OrderID   int `form:"orderID"`
}

// QueryErmcpTradeDetails 获取企业风管期货成交单信息
// @Summary 获取企业风管期货成交单信息
// @Produce json
// @Security ApiKeyAuth
// @Param accountID query int true "资金账户ID"
// @Param goodsID query int false "商品ID"
// @Param buyOrSell query int false "买卖方向，0：买 1：卖"
// @Param orderID query int false "关联委托单号"
// @Success 200 {object} models.QueryHedgeTradeDetailRsp
// @Failure 500 {object} app.Response
// @Router /Ermcp/QueryErmcpTradeDetails [get]
// @Tags 企业风险管理(app)
func QueryErmcpTradeDetails(c *gin.Context) {
	appG := app.Gin{C: c}

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

	// 获取资金账户信息
	taAccount, err := models.GetTaAccountByID(req.AccountID)
	if err != nil {
		logger.GetLogger().Errorf("QueryErmcpTradeDetails failed: %s", err.Error())
		appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
		return
	}
	if taAccount == nil {
		logger.GetLogger().Errorf("QueryErmcpTradeDetails failed")
		appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
		return
	}

	rst := make([]models.QueryHedgeTradeDetailRsp, 0)
	if taAccount.Ismain == 1 {
		// 母账户 -> 外部成交单
		rst, err = models.GetHedgeOutTradeDetails(req.AccountID, req.GoodsID, req.BuyOrSell, req.OrderID)
		if err != nil {
			// 查询失败
			logger.GetLogger().Errorf("QueryErmcpTradeDetails failed: %s", err.Error())
			appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
			return
		}
	} else {
		// 子账户 -> 内部成交单
		rst, err = models.GetHedgeInnerTradeDetails(req.AccountID, req.GoodsID, req.BuyOrSell, req.OrderID)
		if err != nil {
			// 查询失败
			logger.GetLogger().Errorf("QueryErmcpTradeDetails failed: %s", err.Error())
			appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
			return
		}
	}

	// 查询成功返回
	logger.GetLogger().Debugln("QueryErmcpTradeDetails successed: %v", rst)
	appG.Response(http.StatusOK, e.SUCCESS, rst)
}

// QueryHedgeHisTradeDetaislReq 获取企业风管期货历史成交单信息请求参数
type QueryHedgeHisTradeDetaislReq struct {
	AccountID int    `form:"accountID" binding:"required"`
	GoodsID   int    `form:"goodsID"`
	BuyOrSell int    `form:"buyOrSell"`
	OrderID   int    `form:"orderID"`
	StartDate string `form:"startDate"` // 开始时间
	EndDate   string `form:"endDate"`   // 结束时间
}

// QueryErmcpHisTradeDetails 获取企业风管期货历史成交单信息
// @Summary 获取企业风管期货历史成交单信息
// @Produce json
// @Security ApiKeyAuth
// @Param accountID query int true "资金账户ID"
// @Param goodsID query int false "商品ID"
// @Param buyOrSell query int false "买卖方向，0：买 1：卖"
// @Param orderID query int false "关联委托单号"
// @Param startDate query string false "开始时间 - 闭区间，格式：yyyy-MM-dd"
// @Param endDate query string false "结束时间 - 闭区间，格式：yyyy-MM-dd"
// @Success 200 {object} models.QueryHedgeTradeDetailRsp
// @Failure 500 {object} app.Response
// @Router /Ermcp/QueryErmcpHisTradeDetails [get]
// @Tags 企业风险管理(app)
func QueryErmcpHisTradeDetails(c *gin.Context) {
	appG := app.Gin{C: c}

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

	// 获取资金账户信息
	taAccount, err := models.GetTaAccountByID(req.AccountID)
	if err != nil {
		logger.GetLogger().Errorf("QueryErmcpHisTradeDetails failed: %s", err.Error())
		appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
		return
	}
	if taAccount == nil {
		logger.GetLogger().Errorf("QueryErmcpHisTradeDetails failed")
		appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
		return
	}

	rst := make([]models.QueryHedgeTradeDetailRsp, 0)
	if taAccount.Ismain == 1 {
		// 母账户 -> 外部历史成交单
		rst, err = models.GetHisHedgeOutTradeDetails(req.AccountID, req.GoodsID, req.BuyOrSell, req.OrderID, req.StartDate, req.EndDate)
		if err != nil {
			// 查询失败
			logger.GetLogger().Errorf("QueryErmcpHisTradeDetails failed: %s", err.Error())
			appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
			return
		}
	} else {
		// 子账户 -> 内部历史成交单
		rst, err = models.GetHisHedgeInnerTradeDetails(req.AccountID, req.GoodsID, req.BuyOrSell, req.OrderID, req.StartDate, req.EndDate)
		if err != nil {
			// 查询失败
			logger.GetLogger().Errorf("QueryErmcpHisTradeDetails failed: %s", err.Error())
			appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
			return
		}
	}

	// 查询成功返回
	logger.GetLogger().Debugln("QueryErmcpHisTradeDetails successed: %v", rst)
	appG.Response(http.StatusOK, e.SUCCESS, rst)
}
