// Package models 10.2商品管理
package models

import (
	"fmt"
	"mtp2_if/db"
	"strings"
	"time"
)

// Goods 商品表
type Goods struct {
	Goodsid               int64     `json:"goodsid"  xorm:"'GOODSID'" binding:"required"`          // 商品ID(自增ID SEQ_GOODS)
	Goodscode             string    `json:"goodscode"  xorm:"'GOODSCODE'" binding:"required"`      // 商品代码(内部)
	Goodsname             string    `json:"goodsname"  xorm:"'GOODSNAME'" binding:"required"`      // 商品名称
	Marketid              int64     `json:"marketid"  xorm:"'MARKETID'" binding:"required"`        // 所属市场ID
	Goodsgroupid          int64     `json:"goodsgroupid"  xorm:"'GOODSGROUPID'"`                   // 所属商品组ID
	Goodsstatus           int64     `json:"goodsstatus"  xorm:"'GOODSSTATUS'"`                     // 商品状态- 1:待审核 2:未上市 3:上市 4:已注销 5:审核拒绝 6:退市 7:待退市
	Currencyid            int64     `json:"currencyid"  xorm:"'CURRENCYID'"`                       // 报价货币ID
	Goodunitid            int64     `json:"goodunitid"  xorm:"'GOODUNITID'"`                       // 报价单位ID
	Agreeunit             float64   `json:"agreeunit"  xorm:"'AGREEUNIT'"`                         // 合约单位
	Decimalplace          int64     `json:"decimalplace"  xorm:"'DECIMALPLACE'"`                   // 报价小数位
	Listingdate           time.Time `json:"listingdate"  xorm:"'LISTINGDATE'"`                     // 交易开始日期
	Lasttradedate         time.Time `json:"lasttradedate"  xorm:"'LASTTRADEDATE'"`                 // 最后交易日期(状态：待退市)
	Delistingdate         time.Time `json:"delistingdate"  xorm:"'DELISTINGDATE'"`                 // 商品退市时间(状态：退市) -- 已作废
	Deliveryflag          int64     `json:"deliveryflag"  xorm:"'DELIVERYFLAG'"`                   // 交割标志 - 0:不可交割  1:可交割
	Hasquoter             int64     `json:"hasquoter"  xorm:"'HASQUOTER'"`                         // 是否有报价商 - 0:无报价商 1:有报价商
	Hqprotecttime         int64     `json:"hqprotecttime"  xorm:"'HQPROTECTTIME'"`                 // 行情保护时间(秒)
	Quoteshowtype         int64     `json:"quoteshowtype"  xorm:"'QUOTESHOWTYPE'"`                 // 行情报价类型: 1:成交价 2:买卖中间价 3:含买价 4:含卖价做市模式固定为3:含买价
	Quoteshowtypeinterval int64     `json:"quoteshowtypeinterval"  xorm:"'QUOTESHOWTYPEINTERVAL'"` // 行情报价间隔时间(秒)(成交价时为0)
	Modifystatus          int64     `json:"modifystatus"  xorm:"'MODIFYSTATUS'"`                   // 变更状态 - 1:未变更 2:变更中 3:待审核 4:已审核
	Goodstradetype        int64     `json:"goodstradetype"  xorm:"'GOODSTRADETYPE'"`               // 商品交易权限类型 - 1:可建可平 3:不可建可平
	Creatorid             int64     `json:"creatorid"  xorm:"'CREATORID'"`                         // 创建人
	Createtime            time.Time `json:"createtime"  xorm:"'CREATETIME'"`                       // 创建时间
	Auditaccountid        int64     `json:"auditaccountid"  xorm:"'AUDITACCOUNTID'"`               // 审核操作员账号
	Audittime             time.Time `json:"audittime"  xorm:"'AUDITTIME'"`                         // 审核时间
	Modifytime            time.Time `json:"modifytime"  xorm:"'MODIFYTIME'"`                       // 修改时间
	Modifierid            int64     `json:"modifierid"  xorm:"'MODIFIERID'"`                       // 修改人
	Cancelaccountid       int64     `json:"cancelaccountid"  xorm:"'CANCELACCOUNTID'"`             // 注销操作员账号
	Remark                string    `json:"remark"  xorm:"'REMARK'"`                               // 备注
	Canceltime            time.Time `json:"canceltime"  xorm:"'CANCELTIME'"`                       // 注销时间
	Delistingmode         int64     `json:"delistingmode"  xorm:"'DELISTINGMODE'"`                 // 退市方式 - 1:退市平仓 2:退市交收 3:不处理(仅期权\币币兑换)
	Forceclosemode        int64     `json:"forceclosemode"  xorm:"'FORCECLOSEMODE'"`               // 定期强平方式 - 1:无 2:每日 3:每周 4:每月[收益权]
	Forceclosevalue       int64     `json:"forceclosevalue"  xorm:"'FORCECLOSEVALUE'"`             // 定期强平参数 [收益权]
	Cutmode               int64     `json:"cutmode"  xorm:"'CUTMODE'"`                             // 斩仓方式 - 1:不斩仓 2:自动斩仓 3:半自动斩仓
	Quoteminunit          int64     `json:"quoteminunit"  xorm:"'QUOTEMINUNIT'"`                   // 行情最小变动单位 [整数，报价小数位一起使用]
	Isbuylimited          int64     `json:"isbuylimited"  xorm:"'ISBUYLIMITED'"`                   // 是否限制建仓量 - 0:不限制 1:限制
	Innerdealmode         int64     `json:"innerdealmode"  xorm:"'INNERDEALMODE'"`                 // 内部成交方式[通道交易] - 1:净头寸 2:开平 3:平今
	Outerdealmode         int64     `json:"outerdealmode"  xorm:"'OUTERDEALMODE'"`                 // 外部成交方式[通道交易]- 1:净头寸 2:开平 3:平今
	Closepricemode        int64     `json:"closepricemode"  xorm:"'CLOSEPRICEMODE'"`               // 强平价格方式 - 1:市价 2:最新价 3:涨跌停（未实现）
	Closepriceparam       float64   `json:"closepriceparam"  xorm:"'CLOSEPRICEPARAM'"`             // 强平最新价浮动比例 - 方式为2时使用  (<1)买 上浮 (1+x)*最新价卖 下浮 (1-x)*最新价
	Qtydecimalplace       int64     `json:"qtydecimalplace"  xorm:"'QTYDECIMALPLACE'"`             // 成交量小数位
	Goodscurrencyid       int64     `json:"goodscurrencyid"  xorm:"'GOODSCURRENCYID'"`             // 合约货币ID
	Goodsquotetype        int64     `json:"goodsquotetype"  xorm:"'GOODSQUOTETYPE'"`               // 合约报价类型: 1-直接报价  2-间接报价
	Quotegear             int64     `json:"quotegear"  xorm:"'QUOTEGEAR'"`                         // 行情档位(1-10)
	Outgoodscode          string    `json:"outgoodscode"  xorm:"'OUTGOODSCODE'"`                   // 商品代码(外部)
	Isvisible             int32     `json:"isvisible"  xorm:"ISVISIBLE"`                           // 游客是否可见 - 0:不可见 1:可见
	Areauserid            int64     `json:"areauserid"  xorm:"AREAUSERID"`                         // 所属机构
	Pictureurl            string    `json:"pictureurl"  xorm:"PICTUREURL"`                         // 商品图片
}

// TableName is GOODS
func (Goods) TableName() string {
	return "GOODS"
}

// GetGoodsByGoodsCode 通过商品代码获取商品信息
// 参数 goodsCode string 商品代码
// 返回值 *Goods 商品信息
// 返回值 error 错误
func GetGoodsByGoodsCode(goodsCode string) (*Goods, error) {
	engine := db.GetEngine()

	var goods Goods
	has, err := engine.Where("GOODSCODE = ?", goodsCode).Get(&goods)
	if err != nil {
		return nil, err
	}
	if !has {
		// 如果通过GoodsCode找不到，则尝试通过OutGoodsCode来查找
		if _, err := engine.Where("OUTGOODSCODE = ?", goodsCode).Get(&goods); err != nil {
			return nil, err
		}
	}

	return &goods, nil
}

// GetGoods 获取商品信息
// 参数 goodsID int 商品ID
// 返回值 *Goods 商品信息
// 返回值 error 错误
func GetGoods(goodsID int) (*Goods, error) {
	engine := db.GetEngine()

	var goods Goods
	if _, err := engine.Where("GOODSID = ?", goodsID).Get(&goods); err != nil {
		return nil, err
	}

	return &goods, nil
}

// GoodsInfo 商品信息
type GoodsInfo struct {
	Goods     `xorm:"extends"`
	GoodsUnit string `json:"goodsunit" xorm:"GOODSUNIT"` // 报价单位
}

// GetGoodsesByStatus 获取指定状态的商品信息
// 输入 goodsStatus int 商品状态- 1:待审核 2:未上市 3:上市 4:已注销 5:审核拒绝 6:退市 7:待退市
func GetGoodsesByStatus(goodsStatus int) ([]GoodsInfo, error) {
	engine := db.GetEngine()

	goodsInfos := make([]GoodsInfo, 0)
	if err := engine.Table("GOODS").Select("GOODS.*, E1.ENUMDICNAME GOODSUNIT").
		Join("LEFT", "ENUMDICITEM E1", "E1.ENUMITEMNAME = GOODS.GOODUNITID and E1.ENUMDICCODE = 'GOODSUNIT'").
		Where("GOODSSTATUS = ?", goodsStatus).Find(&goodsInfos); err != nil {
		return nil, err
	}

	return goodsInfos, nil
}

// GoodsIDAndName 商品ID与名称
type GoodsIDAndName struct {
	Goodsid   int64  `json:"goodsid"  xorm:"'GOODSID'" binding:"required"`     // 商品ID(自增ID SEQ_GOODS)
	Goodscode string `json:"goodscode"  xorm:"'GOODSCODE'" binding:"required"` // 商品代码(内部)
	Goodsname string `json:"goodsname"  xorm:"'GOODSNAME'" binding:"required"` // 商品名称
	Marketid  int64  `json:"marketid"  xorm:"'MARKETID'" binding:"required"`   // 所属市场ID
}

// GetGoodsInfosByTradeModes 获取指定交易模式的商品信息
// 输入 tradeModes string 交易模式列表，格式 1,2,3
func GetGoodsInfosByTradeModes(tradeModes string) ([]GoodsIDAndName, error) {
	engine := db.GetEngine()

	goodsIDAndNames := make([]GoodsIDAndName, 0)
	if err := engine.Table("GOODS").Select("GOODS.*").
		Join("LEFT", "MARKET M", "M.MARKETID = GOODS.MARKETID").
		Where("GOODS.GOODSSTATUS = 3 and M.TRADEMODE IN (?)", tradeModes).Find(&goodsIDAndNames); err != nil {
		return nil, err
	}

	return goodsIDAndNames, nil
}

// SearchGoods 检索商品信息
type SearchGoods struct {
	Goodsid   int64  `json:"goodsid"  xorm:"'GOODSID'" binding:"required"`     // 商品ID(自增ID SEQ_GOODS)
	Goodscode string `json:"goodscode"  xorm:"'GOODSCODE'" binding:"required"` // 商品代码(内部)
	Goodsname string `json:"goodsname"  xorm:"'GOODSNAME'" binding:"required"` // 商品名称
	Marketid  int64  `json:"marketid"  xorm:"'MARKETID'" binding:"required"`   // 所属市场ID

	Marketname string `json:"marketname"  xorm:"'MARKETNAME'"`                  // 市场名称
	Trademode  int32  `json:"trademode"  xorm:"'TRADEMODE'" binding:"required"` // 交易模式 - 10:做市 13:竞价 15:通道交易 16:挂牌点选 17:仓单贸易 18:期权 19:竞拍-降价式 20:竞拍-竞价式 21:竞拍-大宗式 22:受托竞价
}

// SearchGoodses 检索商品信息的方法
func SearchGoodses(content, tradeModes string) ([]SearchGoods, error) {
	engine := db.GetEngine()

	searchGoodses := make([]SearchGoods, 0)
	session := engine.Table("GOODS G").
		Select(`G.*, 
				M.MARKETNAME, M.TRADEMODE`).
		Join("INNER", "MARKET M", "M.MARKETID = G.MARKETID").
		Where(fmt.Sprintf("(G.GOODSSTATUS in (2,3)) and (G.GOODSCODE like '%%%s%%' or G.GOODSNAME like '%%%s%%')", content, content))
	if len(tradeModes) > 0 {
		session = session.And(fmt.Sprintf("M.TRADEMODE in (%s)", tradeModes))
	}
	if err := session.Find(&searchGoodses); err != nil {
		return nil, err
	}

	return searchGoodses, nil
}

// GetGoodsByLoginID 获取登录账号有权限的商品信息
func GetGoodsByLoginID(loginID int, marketIDs string) ([]Goods, error) {
	// 获取此账号相关有权限的市场
	markets, err := GetMarketsByLoginID(loginID)
	if err != nil {
		return nil, err
	}

	// 构建市场ID列表
	ids := make([]int, 0)
	reqIDs := fmt.Sprintf(",%s,", marketIDs)
	for _, market := range markets {
		if len(marketIDs) > 0 {
			if !strings.Contains(reqIDs, fmt.Sprintf(",%d,", market.Marketid)) {
				continue
			}
		}
		ids = append(ids, int(market.Marketid))
	}

	// 获取对应商品信息
	engine := db.GetEngine()
	goodses := make([]Goods, 0)
	if err := engine.Table("GOODS G").In("G.MARKETID", ids).Find(&goodses); err != nil {
		return nil, err
	}

	return goodses, nil
}
