package order

import (
	"encoding/json"
	"fmt"
	"mtp2_if/db"
	"mtp2_if/global/app"
	"mtp2_if/global/e"
	"mtp2_if/logger"
	"mtp2_if/models"
	"mtp2_if/utils"
	"net/http"
	"strconv"
	"time"

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

// QueryTradePositionReq 持仓汇总查询请求参数（合约市场）
type QueryTradePositionReq struct {
	AccountID string `form:"accountID" binding:"required"`
	TradeMode string `form:"tradeMode"`
}

// QueryTradePositionRsp 持仓汇总查询返回模型（合约市场）
type QueryTradePositionRsp struct {
	AccountID       int64   `json:"accountid"  xorm:"'ACCOUNTID'"`                // 资金账户
	BuyOrSell       int64   `json:"buyorsell"  xorm:"'BUYORSELL'" `               // 方向 - 0:买 1:卖
	Goodsid         int32   `json:"goodsid"  xorm:"'GOODSID'" binding:"required"` // 商品Id
	GoodsCode       string  `json:"goodscode" xorm:"GOODSCODE"`                   // 商品代码
	GoodsName       string  `json:"goodsname" xorm:"GOODSNAME"`                   // 商品名称
	AgreeUnit       float64 `json:"agreeunit"  xorm:"'AGREEUNIT'"`                // 合约单位
	CurrencyID      int64   `json:"currencyid"  xorm:"'CURRENCYID'"`              // 报价货币ID
	GoodUnitID      int64   `json:"goodunitid"  xorm:"'GOODUNITID'"`              // 报价单位ID
	Goodunit        string  `json:"goodunit" xorm:"'GOODUNIT'"`                   // 报价单位
	DecimalPlace    int64   `json:"decimalplace"  xorm:"'DECIMALPLACE'"`          // 报价小数位
	MarketID        int64   `json:"marketid"  xorm:"'MARKETID'"`                  // 所属市场ID
	TradeMode       int32   `json:"trademode"  xorm:"'TRADEMODE'"`                // 交易模式
	PositionQTY     int64   `json:"positionqty"  xorm:"'POSITIONQTY'"`            // 期初持仓数量
	HolderAmount    float64 `json:"holderamount"  xorm:"'HOLDERAMOUNT'"`          // 期初持仓总金额[商品币种]
	CurPositionQTY  int64   `json:"curpositionqty"  xorm:"'CURPOSITIONQTY'"`      // 当前持仓总数量
	CurHolderAmount float64 `json:"curholderamount"  xorm:"'CURHOLDERAMOUNT'"`    // 当前持仓总金额[商品币种]
	FrozenQTY       int64   `json:"frozenqty"  xorm:"'FROZENQTY'"`                // 持仓冻结数量
	OtherFrozenQTY  int64   `json:"otherfrozenqty"  xorm:"'OTHERFROZENQTY'"`      // 持仓其他冻结数量(交割冻结)
	OpenReqQTY      int64   `json:"openreqqty"  xorm:"'OPENREQQTY'"`              // 开仓申请数量(用于比较最大持仓数量)
	OpenTotalQTY    int64   `json:"opentotalqty"  xorm:"'OPENTOTALQTY'"`          // 开仓总数量
	CloseTotalQTY   int64   `json:"closetotalqty"  xorm:"'CLOSETOTALQTY'"`        // 平仓总数量
	TNQTY           int64   `json:"tnqty"  xorm:"'TNQTY'"`                        // T+N冻结总量
	TNUsedQTY       int64   `json:"tnusedqty"  xorm:"'TNUSEDQTY'"`                // T+N使用量(可以使用T+N的冻结数量)
	CurTDPosition   int64   `json:"curtdposition"  xorm:"'CURTDPOSITION'"`        // 期末今日头寸
	FreTDPosition   int64   `json:"fretdposition"  xorm:"'FRETDPOSITION'"`        // 冻结今日头寸
	EnableQTY       int64   `json:"enableqty"  xorm:"'ENABLEQTY'"`                // 可用量
	AveragePrice    float64 `json:"averageprice" xorm:"AVERAGEPRICE"`             // 持仓均价
	Usedmargin      float64 `json:"usedmargin"  xorm:"'USEDMARGIN'"`              // 占用保证金[商品币种]
}

// QueryTradePosition 持仓汇总查询（合约市场）
// @Summary 持仓汇总查询（合约市场）
// @Produce json
// @Security ApiKeyAuth
// @Param accountID query string true "资金账户 - 格式：1,2,3"
// @Param tradeMode query string false "交易模式 - 格式：1,2,3"
// @Success 200 {object} QueryTradePositionRsp
// @Failure 500 {object} app.Response
// @Router /Order/QueryTradePosition [get]
// @Tags 通用单据
// 参考通用查询：SearchTradePositionDetail
func QueryTradePosition(c *gin.Context) {
	appG := app.Gin{C: c}

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

	// 查询数据
	type tradePosition struct {
		models.Tradeposition `xorm:"extends"`
		Goodscode            string  `json:"goodscode"  xorm:"'GOODSCODE'"`       // 商品代码(内部)
		Goodsname            string  `json:"goodsname"  xorm:"'GOODSNAME'"`       // 商品名称
		Currencyid           int64   `json:"currencyid"  xorm:"'CURRENCYID'"`     // 报价货币ID
		Goodunitid           int64   `json:"goodunitid"  xorm:"'GOODUNITID'"`     // 报价单位ID
		Goodunit             string  `json:"goodunit" xorm:"'GOODUNIT'"`          // 报价单位
		Agreeunit            float64 `json:"agreeunit"  xorm:"'AGREEUNIT'"`       // 合约单位
		Decimalplace         int64   `json:"decimalplace"  xorm:"'DECIMALPLACE'"` // 报价小数位
		Marketid             int32   `json:"marketid"  xorm:"'MARKETID'"`         // 市场ID
		Trademode            int32   `json:"trademode"  xorm:"'TRADEMODE'"`       // 交易模式
	}
	datas := make([]tradePosition, 0)
	engine := db.GetEngine()
	// ORACLE好像在JOIN里不支持别名功能（在XORM中）
	s := engine.Table("TRADEPOSITION").
		Join("LEFT", "GOODS", "TRADEPOSITION.GOODSID = GOODS.GOODSID").
		Join("LEFT", "MARKET", "GOODS.MARKETID = MARKET.MARKETID").
		Join("LEFT", "ENUMDICITEM", "GOODS.GOODUNITID = ENUMDICITEM.ENUMITEMNAME and ENUMDICITEM.ENUMDICCODE = 'goodsunit'").
		Select("TRADEPOSITION.*, GOODS.GOODSCODE, GOODS.GOODSNAME, GOODS.CURRENCYID, GOODS.GOODUNITID, ENUMDICITEM.ENUMDICNAME as GOODUNIT, GOODS.AGREEUNIT, GOODS.DECIMALPLACE, MARKET.MARKETID, MARKET.TRADEMODE").
		Where(fmt.Sprintf(`TRADEPOSITION.ACCOUNTID in (%s)`, req.AccountID))
	if len(req.TradeMode) > 0 {
		s = s.And(fmt.Sprintf(`MARKET.TRADEMODE in (%s)`, req.TradeMode))
	}
	if err := s.Find(&datas); err != nil {
		// 查询失败
		logger.GetLogger().Errorf("QueryTradePosition failed: %s", err.Error())
		appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
		return
	}
	// 构建返回数据
	rst := make([]QueryTradePositionRsp, 0)
	for _, v := range datas {
		// 构建买方向持仓汇总
		if v.Buycurpositionqty > 0 {
			var tradePosition QueryTradePositionRsp
			// 反射数据
			// struct -> json
			if jsonBytes, err := json.Marshal(v); err == nil {
				// json -> struct
				json.Unmarshal(jsonBytes, &tradePosition)
				tradePosition.BuyOrSell = 0
				tradePosition.PositionQTY = v.Buypositionqty
				tradePosition.HolderAmount = v.Buyholderamount
				tradePosition.CurPositionQTY = v.Buycurpositionqty
				tradePosition.CurHolderAmount = v.Buycurholderamount
				tradePosition.FrozenQTY = v.Buyfrozenqty
				tradePosition.OtherFrozenQTY = v.Buyotherfrozenqty
				tradePosition.OpenReqQTY = v.Buyopenreqqty
				tradePosition.OpenTotalQTY = v.Buyopentotalqty
				tradePosition.CloseTotalQTY = v.Buyclosetotalqty
				tradePosition.TNQTY = v.Buytnqty
				tradePosition.TNUsedQTY = v.Buytnusedqty
				tradePosition.CurTDPosition = v.Buycurtdposition
				tradePosition.FreTDPosition = v.Buyfretdposition
				tradePosition.EnableQTY = v.Buycurpositionqty - v.Buyfrozenqty - v.Buyotherfrozenqty
				// 计算持仓均价
				averagePrice := tradePosition.CurHolderAmount / float64(tradePosition.CurPositionQTY) / tradePosition.AgreeUnit
				tradePosition.AveragePrice, _ = strconv.ParseFloat(utils.FormatFloat(averagePrice, int(v.Decimalplace)), 64)
				rst = append(rst, tradePosition)
			}
		}

		// 构建卖方向持仓汇总
		if v.Tradeproperty != 2 && v.Sellcurpositionqty > 0 {
			var tradePosition QueryTradePositionRsp
			// 反射数据
			// struct -> json
			if jsonBytes, err := json.Marshal(v); err == nil {
				// json -> struct
				json.Unmarshal(jsonBytes, &tradePosition)
				tradePosition.BuyOrSell = 1
				tradePosition.PositionQTY = v.Sellpositionqty
				tradePosition.HolderAmount = v.Sellholderamount
				tradePosition.CurPositionQTY = v.Sellcurpositionqty
				tradePosition.CurHolderAmount = v.Sellcurholderamount
				tradePosition.FrozenQTY = v.Sellfrozenqty
				tradePosition.OtherFrozenQTY = v.Sellotherfrozenqty
				tradePosition.OpenReqQTY = v.Sellopenreqqty
				tradePosition.OpenTotalQTY = v.Sellopentotalqty
				tradePosition.CloseTotalQTY = v.Sellclosetotalqty
				tradePosition.TNQTY = v.Selltnqty
				tradePosition.TNUsedQTY = v.Selltnusedqty
				tradePosition.CurTDPosition = v.Sellcurtdposition
				tradePosition.FreTDPosition = v.Sellfretdposition
				tradePosition.EnableQTY = v.Sellcurpositionqty - v.Sellfrozenqty - v.Sellotherfrozenqty
				// 计算持仓均价
				averagePrice := tradePosition.CurHolderAmount / float64(tradePosition.CurPositionQTY) / tradePosition.AgreeUnit
				tradePosition.AveragePrice, _ = strconv.ParseFloat(utils.FormatFloat(averagePrice, int(v.Decimalplace)), 64)

				rst = append(rst, tradePosition)
			}
		}
	}

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

// QueryTradeOrderDetailReq 委托单查询请求参数（合约市场）
type QueryTradeOrderDetailReq struct {
	AccountID   string `form:"accountID" binding:"required"`
	OrderStatus string `form:"orderStatus"`
	TradeMode   string `form:"tradeMode"`
	OrderID     int    `form:"orderID"`
}

// QueryTradeOrderDetailRsp 委托单查询返回模型（合约市场）
type QueryTradeOrderDetailRsp struct {
	Orderid             string    `json:"orderid"  xorm:"'ORDERID'"`                            // 委托单号(100+Unix秒时间戳(10位)+2位(MarketServiceID)+xxxx)
	Tradedate           string    `json:"tradedate"  xorm:"'TRADEDATE'" binding:"required"`     // 交易日(yyyyMMdd)
	Buildtype           int64     `json:"buildtype"  xorm:"'BUILDTYPE'" binding:"required"`     // 委托单据类型 - 1:建仓 2:平仓 3:先平后建
	Preorderid          string    `json:"preorderid"  xorm:"'PREORDERID'"`                      // 关联预埋单号(止盈止损单时填写)
	Cancelorderid       string    `json:"cancelorderid"  xorm:"'CANCELORDERID'"`                // 撤单单号(撤单时填写)
	Relatedid           string    `json:"relatedid"  xorm:"'RELATEDID'"`                        // 关联单号(交割单)
	Marketid            int64     `json:"marketid"  xorm:"'MARKETID'" binding:"required"`       // 市场ID
	Goodsid             int64     `json:"goodsid"  xorm:"'GOODSID'" binding:"required"`         // 商品ID
	Accountid           int64     `json:"accountid"  xorm:"'ACCOUNTID'" binding:"required"`     // 账户ID[报价币种]
	Buyorsell           int64     `json:"buyorsell"  xorm:"'BUYORSELL'" binding:"required"`     // 买卖 - 0:买 1:卖
	Pricemode           int64     `json:"pricemode"  xorm:"'PRICEMODE'" binding:"required"`     // 取价方式 - 1:市价 2: 限价
	Orderprice          float64   `json:"orderprice"  xorm:"'ORDERPRICE'"`                      // 委托价格
	Orderqty            int64     `json:"orderqty"  xorm:"'ORDERQTY'" binding:"required"`       // 委托数量
	Tradeqty            int64     `json:"tradeqty"  xorm:"'TRADEQTY'"`                          // 成交数量
	Cancelqty           int64     `json:"cancelqty"  xorm:"'CANCELQTY'"`                        // 撤单数量
	Openqty             int64     `json:"openqty"  xorm:"'OPENQTY'"`                            // 开仓数量(先建后平操作,需要记录)
	Closeqty            int64     `json:"closeqty"  xorm:"'CLOSEQTY'"`                          // 平仓数量(先建后平操作 需要记录)
	Opentradeqty        int64     `json:"opentradeqty"  xorm:"'OPENTRADEQTY'"`                  // 开仓成交数量(先建后平操作,需要记录)
	Closetradeqty       int64     `json:"closetradeqty"  xorm:"'CLOSETRADEQTY'"`                // 平仓成交数量(先建后平操作,需要记录)
	Freezemargin        float64   `json:"freezemargin"  xorm:"'FREEZEMARGIN'"`                  // 冻结保证金(冻结交易金额)
	Unfreezemargin      float64   `json:"unfreezemargin"  xorm:"'UNFREEZEMARGIN'"`              // 解冻保证金
	Freezecharge        float64   `json:"freezecharge"  xorm:"'FREEZECHARGE'"`                  // 冻结手续费
	Unfreezecharge      float64   `json:"unfreezecharge"  xorm:"'UNFREEZECHARGE'"`              // 解冻手续费
	Openfreezecharge    float64   `json:"openfreezecharge"  xorm:"'OPENFREEZECHARGE'"`          // 开仓冻结手续费(先建后平操作,需要记录)
	Closefreezecharge   float64   `json:"closefreezecharge"  xorm:"'CLOSEFREEZECHARGE'"`        // 平仓冻结手续费(先建后平操作,需要记录)
	Openunfreezecharge  float64   `json:"openunfreezecharge"  xorm:"'OPENUNFREEZECHARGE'"`      // 开仓解冻手续费(先建后平操作,需要记录)
	Closeunfreezecharge float64   `json:"closeunfreezecharge"  xorm:"'CLOSEUNFREEZECHARGE'"`    // 平仓解冻手续费(先建后平操作,需要记录)
	Validtype           int64     `json:"validtype"  xorm:"'VALIDTYPE'" binding:"required"`     // 有效类型 - 1当日有效 2本周有效 3指定日期有效 4一直有效 5指定时间有效
	Validtime           time.Time `json:"validtime"  xorm:"'VALIDTIME'"`                        // 有效期限
	Volumetype          int64     `json:"volumetype"  xorm:"'VOLUMETYPE'"`                      // 当时间有效类型为 “立即执行否则取消 IOC” 时，需要此项 - 0:任意量  1:最小量（暂时不支持） 2:全部量
	Operatetype         int64     `json:"operatetype"  xorm:"'OPERATETYPE'" binding:"required"` // 操作类型 - 1:正常下单 2:斩仓 3:转单 4:结算撤单 5:系统卖出(适用于先平后建的卖出) 6:行情源报价 7:（结算)到期强平 8:（结算)协议转让 9:系统对冲单 10:（结算)到期无效 11:交割协议转让 12:交割协议平仓 13:交割成交(所有权) 14:管理端强行平仓 15:管理端协议转让
	Ordertime           time.Time `json:"ordertime"  xorm:"'ORDERTIME'" binding:"required"`     // 委托时间
	Orderstatus         int64     `json:"orderstatus"  xorm:"'ORDERSTATUS'"`                    // 委托状态 - 1： 委托请求 2：待冻结 3：委托成功 4： 委托失败 5：配对成功 6： 已撤销 7：部分成交 8：已成交 9：部成部撤 10：成交失败 11：已拒绝 12:经过摘牌(先摘后挂专用-先摘后挂已摘过) 13:冻结成功(通道交易专用) 14:通道已撤 15:通道部成部撤 16:成交失败违约(荷兰式竞拍专用)
	Listingselecttype   int64     `json:"listingselecttype"  xorm:"'LISTINGSELECTTYPE'"`        // 挂牌点选类型 - 1:挂牌 2:摘牌 3:先摘后挂
	Delistingtype       int64     `json:"delistingtype"  xorm:"'DELISTINGTYPE'"`                // 摘牌类型 - 1:价格最优 2:点选成交
	Ordersrc            int64     `json:"ordersrc"  xorm:"'ORDERSRC'"`                          // 委托来源 -  1:客户端 2:管理端 3:风控服务 4:交割服务 5:交易服务 6:交易日结 7:商品强平 8:管理端商品退市强平 9:交易接口 10:交割服务商被动(受托竞价) 11:预埋触发
	Clienttype          int64     `json:"clienttype"  xorm:"'CLIENTTYPE'"`                      // 客户端类型 - 0:保留为未填终端类型 1:PC管理端 2:PC交易端 3:手机客户端_安卓 4:网页客户端 5:微信客户端 6:手机客户端_苹果 7:网上开户客户端 8:无效终端编号 9:报价终端(中江)
	Operatorid          int64     `json:"operatorid"  xorm:"'OPERATORID'"`                      // 登录账号(LoginID)

	GoodsCode  string `json:"goodscode" xorm:"GOODSCODE"`      // 商品代码
	GoodsName  string `json:"goodsname" xorm:"GOODSNAME"`      // 商品名称
	Marketname string `json:"marketname"  xorm:"'MARKETNAME'"` // 市场名称
	TradeMode  int32  `json:"trademode"  xorm:"'TRADEMODE'"`   // 交易模式

	Enableqty int64 `json:"enableqty" xorm:"ENABLEQTY"` // 可用数量 = 委托数量 - 成交数量 - 撤单数量
}

// QueryTradeOrderDetail 委托单查询请求（合约市场）
// @Summary 委托单查询请求（合约市场）
// @Produce json
// @Security ApiKeyAuth
// @Param accountID query string true "资金账户 - 格式：1,2,3"
// @Param tradeMode query string false "交易模式 - 格式：1,2,3"
// @Param orderStatus query string false "委托状态 - 格式：1,2,3"
// @Param orderID query int false "委托单号"
// @Success 200 {object} QueryTradeOrderDetailRsp
// @Failure 500 {object} app.Response
// @Router /Order/QueryTradeOrderDetail [get]
// @Tags 通用单据
// 参考通用查询：SearchTradeOrderDetail
func QueryTradeOrderDetail(c *gin.Context) {
	appG := app.Gin{C: c}

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

	datas := make([]QueryTradeOrderDetailRsp, 0)
	engine := db.GetEngine()
	// 由于int64类型数据（单号）过长是获取会有问题（可能是oci8组件问题），所以这里将可能会出问题的单号都用to_char来输出
	s := engine.Table("TRADE_ORDERDETAIL").
		Join("LEFT", "GOODS", "GOODS.GOODSID = TRADE_ORDERDETAIL.GOODSID").
		Join("LEFT", "MARKET", "MARKET.MARKETID = TRADE_ORDERDETAIL.MARKETID").
		Select(`to_char(TRADE_ORDERDETAIL.ORDERID) as ORDERID, to_char(TRADE_ORDERDETAIL.PREORDERID) as PREORDERID, to_char(TRADE_ORDERDETAIL.CANCELORDERID) as CANCELORDERID, to_char(TRADE_ORDERDETAIL.RELATEDID) as RELATEDID,
				TRADE_ORDERDETAIL.*, TRADE_ORDERDETAIL.ORDERQTY - TRADE_ORDERDETAIL.TRADEQTY - TRADE_ORDERDETAIL.CANCELQTY as ENABLEQTY, 
				GOODS.GOODSCODE, GOODS.GOODSNAME, MARKET.MARKETNAME, MARKET.TRADEMODE`).
		Where(fmt.Sprintf(`TRADE_ORDERDETAIL.ORDERSRC != 10 and TRADE_ORDERDETAIL.ACCOUNTID in (%s)`, req.AccountID)).
		Desc("TRADE_ORDERDETAIL.ORDERTIME")
	if len(req.OrderStatus) > 0 {
		s = s.And(fmt.Sprintf(`TRADE_ORDERDETAIL.ORDERSTATUS in (%s)`, req.OrderStatus))
	}
	if len(req.TradeMode) > 0 {
		s = s.And(fmt.Sprintf(`MARKET.TRADEMODE in (%s)`, req.TradeMode))
	}
	if req.OrderID > 0 {
		s = s.And("TRADE_ORDERDETAIL.ORDERID = ?", req.OrderID)
	}
	if err := s.Find(&datas); err != nil {
		// 查询失败
		logger.GetLogger().Errorf("QueryTradeOrderDetail failed: %s", err.Error())
		appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
		return
	}

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

// QueryHisTradeOrderDetailReq 历史委托单查询请求参数（合约市场）
type QueryHisTradeOrderDetailReq struct {
	AccountID   string `form:"accountID" binding:"required"` // 资金账户 - 格式：1,2,3
	OrderStatus string `form:"orderStatus"`                  // 委托状态 - 格式：1,2,3
	TradeMode   string `form:"tradeMode"`                    // 交易模式 - 格式：1,2,3
	OrderID     int    `form:"orderID"`                      // 委托单号
	StartDate   string `form:"startDate"`                    // 开始时间
	EndDate     string `form:"endDate"`                      // 结束时间
}

// QueryHisTradeOrderDetailRsp 历史委托单查询返回模型（合约市场）
type QueryHisTradeOrderDetailRsp struct {
	models.Histradeorderdetail `xorm:"extends"`

	GoodsCode  string `json:"goodscode" xorm:"GOODSCODE"`      // 商品代码
	GoodsName  string `json:"goodsname" xorm:"GOODSNAME"`      // 商品名称
	Marketname string `json:"marketname"  xorm:"'MARKETNAME'"` // 市场名称
	TradeMode  int32  `json:"trademode"  xorm:"'TRADEMODE'"`   // 交易模式
}

// QueryHisTradeOrderDetail 历史委托单查询请求（合约市场）
// @Summary 历史委托单查询请求（合约市场）
// @Produce json
// @Security ApiKeyAuth
// @Param accountID query string true "资金账户 - 格式：1,2,3"
// @Param tradeMode query string false "交易模式 - 格式：1,2,3"
// @Param orderStatus query string false "委托状态 - 格式：1,2,3"
// @Param orderID query int false "委托单号"
// @Param startDate query string false "开始时间 - 闭区间，格式：yyyy-MM-dd"
// @Param endDate query string false "结束时间 - 闭区间，格式：yyyy-MM-dd"
// @Success 200 {object} QueryHisTradeOrderDetailRsp
// @Failure 500 {object} app.Response
// @Router /Order/QueryHisTradeOrderDetail [get]
// @Tags 通用单据
// 参考通用查询：Client_QueryHis_trade_orderdetail
func QueryHisTradeOrderDetail(c *gin.Context) {
	appG := app.Gin{C: c}

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

	datas := make([]QueryHisTradeOrderDetailRsp, 0)
	engine := db.GetEngine()
	s := engine.Table("HIS_TRADE_ORDERDETAIL").
		Join("LEFT", "GOODS", "GOODS.GOODSID = HIS_TRADE_ORDERDETAIL.GOODSID").
		Join("LEFT", "MARKET", "MARKET.MARKETID = HIS_TRADE_ORDERDETAIL.MARKETID").
		Select(`to_char(HIS_TRADE_ORDERDETAIL.ORDERID) as ORDERID, to_char(HIS_TRADE_ORDERDETAIL.PREORDERID) as PREORDERID, to_char(HIS_TRADE_ORDERDETAIL.CANCELORDERID) as CANCELORDERID, to_char(HIS_TRADE_ORDERDETAIL.RELATEDID) as RELATEDID,
				HIS_TRADE_ORDERDETAIL.*, 
				GOODS.GOODSCODE, GOODS.GOODSNAME, MARKET.MARKETNAME, MARKET.TRADEMODE`).
		Where(fmt.Sprintf(`HIS_TRADE_ORDERDETAIL.ORDERSRC != 10 and HIS_TRADE_ORDERDETAIL.ISVALIDDATA = 1 and HIS_TRADE_ORDERDETAIL.ACCOUNTID in (%s)`, req.AccountID)).
		Desc("HIS_TRADE_ORDERDETAIL.ORDERTIME")
	if len(req.OrderStatus) > 0 {
		s = s.And(fmt.Sprintf(`HIS_TRADE_ORDERDETAIL.ORDERSTATUS in (%s)`, req.OrderStatus))
	}
	if len(req.TradeMode) > 0 {
		s = s.And(fmt.Sprintf(`MARKET.TRADEMODE in (%s)`, req.TradeMode))
	}
	if req.OrderID > 0 {
		s = s.And("HIS_TRADE_ORDERDETAIL.ORDERID = ?", req.OrderID)
	}
	if len(req.StartDate) > 0 {
		s = s.And(fmt.Sprintf("to_date(HIS_TRADE_ORDERDETAIL.HISTRADEDATE,'yyyyMMdd') >= to_date('%s','yyyy-MM-dd')", req.StartDate))
	}
	if len(req.EndDate) > 0 {
		s = s.And(fmt.Sprintf("to_date(HIS_TRADE_ORDERDETAIL.HISTRADEDATE,'yyyyMMdd') <= to_date('%s','yyyy-MM-dd')", req.EndDate))
	}
	if err := s.Find(&datas); err != nil {
		// 查询失败
		logger.GetLogger().Errorf("QueryHisTradeOrderDetail failed: %s", err.Error())
		appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
		return
	}

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

// QueryTradeDetailReq 成交单查询请求参数
type QueryTradeDetailReq struct {
	AccountID string `form:"accountID" binding:"required"`
	TradeID   int    `form:"tradeID"`
	OrderID   int    `form:"orderID"`
	TradeMode string `form:"tradeMode"`
	BuildType int    `form:"buildType"`
	TradeType string `form:"tradeType"`
}

// QueryTradeDetailRsp 成交单查询返回模型
type QueryTradeDetailRsp struct {
	models.Tradetradedetail `xorm:"extends"`

	GoodsCode         string `json:"goodscode" xorm:"GOODSCODE"`                    // 商品代码
	GoodsName         string `json:"goodsname" xorm:"GOODSNAME"`                    // 商品名称
	Marketname        string `json:"marketname"  xorm:"'MARKETNAME'"`               // 市场名称
	TradeMode         int32  `json:"trademode"  xorm:"'TRADEMODE'"`                 // 交易模式
	ListingSelectType int32  `json:"listingselecttype"  xorm:"'LISTINGSELECTTYPE'"` // 关联委托单挂牌点选类型 - 1:挂牌 2:摘牌 3:先摘后挂

	Charge float64 `json:"charge" xorm:"CHARGE"` // 手续费
}

// QueryTradeDetail 成交单查询（合约市场）
// @Summary 成交单查询（合约市场）
// @Produce json
// @Security ApiKeyAuth
// @Param accountID query string true "资金账户 - 格式：1,2,3"
// @Param tradeID query int false "成交单号"
// @Param orderID query int false "委托单号"
// @Param tradeMode query string false "交易模式 - 格式：1,2,3"
// @Param buildType query int false "委托单据类型"
// @Param tradeType query string false "成交类别 - 格式：1,2,3"
// @Success 200 {object} QueryTradeDetailRsp
// @Failure 500 {object} app.Response
// @Router /Order/QueryTradeDetail [get]
// @Tags 通用单据
// 参考通用查询：SearchAllTransactionDetailOrder
func QueryTradeDetail(c *gin.Context) {
	appG := app.Gin{C: c}

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

	datas := make([]QueryTradeDetailRsp, 0)
	engine := db.GetEngine()
	s := engine.Table("TRADE_TRADEDETAIL").
		Join("LEFT", "GOODS", "GOODS.GOODSID = TRADE_TRADEDETAIL.GOODSID").
		Join("LEFT", "MARKET", "MARKET.MARKETID = TRADE_TRADEDETAIL.MARKETID").
		Join("LEFT", "TRADE_ORDERDETAIL", "TRADE_ORDERDETAIL.ORDERID = TRADE_TRADEDETAIL.ORDERID").
		Select(`to_char(TRADE_TRADEDETAIL.TRADEID) as TRADEID, to_char(TRADE_TRADEDETAIL.ORDERID) as ORDERID, 
				TRADE_TRADEDETAIL.*, CASE TRADE_TRADEDETAIL.BUILDTYPE WHEN 1 THEN TRADE_TRADEDETAIL.OPENCHARGE ELSE TRADE_TRADEDETAIL.CLOSECHARGE END as CHARGE,
				GOODS.GOODSCODE, GOODS.GOODSNAME, MARKET.MARKETNAME, MARKET.TRADEMODE, 
				TRADE_ORDERDETAIL.LISTINGSELECTTYPE`).
		Where(fmt.Sprintf("TRADE_TRADEDETAIL.TRADETYPE <= 13 and TRADE_TRADEDETAIL.ACCOUNTID in (%s)", req.AccountID)).
		Desc("TRADE_TRADEDETAIL.TRADETIME")
	if req.TradeID > 0 {
		s = s.And("TRADE_TRADEDETAIL.TRADEID = ?", req.TradeID)
	}
	if req.OrderID > 0 {
		s = s.And("TRADE_TRADEDETAIL.ORDERID = ?", req.OrderID)
	}
	if len(req.TradeMode) > 0 {
		s = s.And(fmt.Sprintf("MARKET.TRADEMODE in (%s)", req.TradeMode))
	}
	if req.BuildType > 0 {
		s = s.And("TRADE_TRADEDETAIL.BUILDTYPE = ?", req.BuildType)
	}
	if len(req.TradeType) > 0 {
		s = s.And(fmt.Sprintf("TRADE_TRADEDETAIL.TRADETYPE in (%s)", req.TradeType))
	}
	if err := s.Find(&datas); err != nil {
		// 查询失败
		logger.GetLogger().Errorf("QueryTradeDetail failed: %s", err.Error())
		appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
		return
	}

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

// QueryHisTradeDetailReq 历史成交单查询请求参数
type QueryHisTradeDetailReq struct {
	AccountID string `form:"accountID" binding:"required"`
	TradeID   int    `form:"tradeID"`
	OrderID   int    `form:"orderID"`
	TradeMode string `form:"tradeMode"`
	BuildType int    `form:"buildType"`
	TradeType string `form:"tradeType"`
	StartDate string `form:"startDate"` // 开始时间
	EndDate   string `form:"endDate"`   // 结束时间
}

// QueryHisTradeDetailRsp 历史成交单查询返回模型
type QueryHisTradeDetailRsp struct {
	models.Histradetradedetail `xorm:"extends"`

	GoodsCode         string `json:"goodscode" xorm:"GOODSCODE"`                    // 商品代码
	GoodsName         string `json:"goodsname" xorm:"GOODSNAME"`                    // 商品名称
	Marketname        string `json:"marketname"  xorm:"'MARKETNAME'"`               // 市场名称
	TradeMode         int32  `json:"trademode"  xorm:"'TRADEMODE'"`                 // 交易模式
	ListingSelectType int32  `json:"listingselecttype"  xorm:"'LISTINGSELECTTYPE'"` // 关联委托单挂牌点选类型 - 1:挂牌 2:摘牌 3:先摘后挂

	Charge float64 `json:"charge" xorm:"CHARGE"` // 手续费
}

// QueryHisTradeDetail 历史成交单查询（合约市场）
// @Summary 历史成交单查询（合约市场）
// @Produce json
// @Security ApiKeyAuth
// @Param accountID query string true "资金账户 - 格式：1,2,3"
// @Param tradeID query int false "成交单号"
// @Param orderID query int false "委托单号"
// @Param tradeMode query string false "交易模式 - 格式：1,2,3"
// @Param buildType query int false "委托单据类型"
// @Param tradeType query string false "成交类别 - 格式：1,2,3"
// @Param startDate query string false "开始时间 - 闭区间，格式：yyyy-MM-dd"
// @Param endDate query string false "结束时间 - 闭区间，格式：yyyy-MM-dd"
// @Success 200 {object} QueryHisTradeDetailRsp
// @Failure 500 {object} app.Response
// @Router /Order/QueryHisTradeDetail [get]
// @Tags 通用单据
// 参考通用查询：Client_QueryHis_trade_transactiondetail
func QueryHisTradeDetail(c *gin.Context) {
	appG := app.Gin{C: c}

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

	datas := make([]QueryHisTradeDetailRsp, 0)
	engine := db.GetEngine()
	s := engine.Table("HIS_TRADE_TRADEDETAIL").
		Join("LEFT", "GOODS", "GOODS.GOODSID = HIS_TRADE_TRADEDETAIL.GOODSID").
		Join("LEFT", "MARKET", "MARKET.MARKETID = HIS_TRADE_TRADEDETAIL.MARKETID").
		Join("LEFT", "HIS_TRADE_ORDERDETAIL", "HIS_TRADE_ORDERDETAIL.ORDERID = HIS_TRADE_TRADEDETAIL.ORDERID").
		Select(`to_char(HIS_TRADE_TRADEDETAIL.TRADEID) as TRADEID, to_char(HIS_TRADE_TRADEDETAIL.ORDERID) as ORDERID, 
				HIS_TRADE_TRADEDETAIL.*, CASE HIS_TRADE_TRADEDETAIL.BUILDTYPE WHEN 1 THEN HIS_TRADE_TRADEDETAIL.OPENCHARGE ELSE HIS_TRADE_TRADEDETAIL.CLOSECHARGE END as CHARGE,
				GOODS.GOODSCODE, GOODS.GOODSNAME, MARKET.MARKETNAME, MARKET.TRADEMODE, 
				HIS_TRADE_ORDERDETAIL.LISTINGSELECTTYPE`).
		Where(fmt.Sprintf("HIS_TRADE_TRADEDETAIL.TRADETYPE <= 13 and HIS_TRADE_TRADEDETAIL.ISVALIDDATA = 1 and HIS_TRADE_TRADEDETAIL.ACCOUNTID in (%s)", req.AccountID)).
		Desc("HIS_TRADE_TRADEDETAIL.TRADETIME")
	if req.TradeID > 0 {
		s = s.And("HIS_TRADE_TRADEDETAIL.TRADEID = ?", req.TradeID)
	}
	if req.OrderID > 0 {
		s = s.And("HIS_TRADE_TRADEDETAIL.ORDERID = ?", req.OrderID)
	}
	if len(req.TradeMode) > 0 {
		s = s.And(fmt.Sprintf("MARKET.TRADEMODE in (%s)", req.TradeMode))
	}
	if req.BuildType > 0 {
		s = s.And("HIS_TRADE_TRADEDETAIL.BUILDTYPE = ?", req.BuildType)
	}
	if len(req.TradeType) > 0 {
		s = s.And(fmt.Sprintf("HIS_TRADE_TRADEDETAIL.TRADETYPE in (%s)", req.TradeType))
	}
	if len(req.StartDate) > 0 {
		s = s.And(fmt.Sprintf("to_date(HIS_TRADE_TRADEDETAIL.HISTRADEDATE,'yyyyMMdd') >= to_date('%s','yyyy-MM-dd')", req.StartDate))
	}
	if len(req.EndDate) > 0 {
		s = s.And(fmt.Sprintf("to_date(HIS_TRADE_TRADEDETAIL.HISTRADEDATE,'yyyyMMdd') <= to_date('%s','yyyy-MM-dd')", req.EndDate))
	}
	if err := s.Find(&datas); err != nil {
		// 查询失败
		logger.GetLogger().Errorf("QueryHisTradeDetail failed: %s", err.Error())
		appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
		return
	}

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