package trade_analysis

import (
	tradeAnalysisModel "eta/eta_api/models/data_manage/trade_analysis"
	"eta/eta_api/utils"
	"fmt"
	"strconv"
	"strings"
)

// TradeAnalysisInterface 持仓分析查询接口
type TradeAnalysisInterface interface {
	GetTradeDataByClassifyAndCompany(exchange, classifyName string, contracts, queryCompanies []string) (items []*tradeAnalysisModel.OriginTradeData, err error) // 根据品种和公司获取原始数据
	GetLastTradeDataByClassify(exchange, classifyName string, contracts []string) (items []*tradeAnalysisModel.OriginTradeData, err error)                       // 获取品种末位数据
}

// BaseTradeAnalysis 通用交易所
type BaseTradeAnalysis struct{}

func (b *BaseTradeAnalysis) GetTradeDataByClassifyAndCompany(exchange, classifyName string, contracts, queryCompanies []string) (items []*tradeAnalysisModel.OriginTradeData, err error) {
	return tradeAnalysisModel.GetTradeDataByClassifyAndCompany(exchange, classifyName, contracts, queryCompanies)
}

func (b *BaseTradeAnalysis) GetLastTradeDataByClassify(exchange, classifyName string, contracts []string) (items []*tradeAnalysisModel.OriginTradeData, err error) {
	return tradeAnalysisModel.GetLastTradeDataByClassify(exchange, classifyName, contracts)
}

// ZhengzhouTradeAnalysis 郑商所
type ZhengzhouTradeAnalysis struct{}

func (z *ZhengzhouTradeAnalysis) GetTradeDataByClassifyAndCompany(exchange, classifyName string, contracts, queryCompanies []string) (items []*tradeAnalysisModel.OriginTradeData, err error) {
	return tradeAnalysisModel.GetTradeZhengzhouDataByClassifyAndCompany(exchange, contracts, queryCompanies)
}

func (z *ZhengzhouTradeAnalysis) GetLastTradeDataByClassify(exchange, classifyName string, contracts []string) (items []*tradeAnalysisModel.OriginTradeData, err error) {
	return tradeAnalysisModel.GetLastTradeZhengzhouDataByClassify(exchange, contracts)
}

// GuangzhouTradeAnalysis 广期所
type GuangzhouTradeAnalysis struct{}

func (g *GuangzhouTradeAnalysis) GetTradeDataByClassifyAndCompany(exchange, classifyName string, contracts, queryCompanies []string) (items []*tradeAnalysisModel.OriginTradeData, err error) {
	classifyIdMap := map[string]int{"si": 7, "lc": 8}
	classifyId := classifyIdMap[classifyName]
	if classifyId == 0 {
		err = fmt.Errorf("品种有误")
		return
	}

	// TOP20
	seatNameArr := []string{tradeAnalysisModel.GuangZhouSeatNameBuy, tradeAnalysisModel.GuangZhouSeatNameSold}
	if utils.InArrayByStr(queryCompanies, tradeAnalysisModel.TradeFuturesCompanyTop20) {
		seatNameArr = append(seatNameArr, tradeAnalysisModel.GuangZhouTopSeatNameBuy, tradeAnalysisModel.GuangZhouTopSeatNameSold)
	}

	// 查询品种下所有指标
	indexes, e := tradeAnalysisModel.GetBaseFromTradeGuangzhouIndexByClassifyId(classifyId)
	if e != nil {
		err = fmt.Errorf("获取广期所指标失败, %v", e)
		return
	}
	var indexIds []int
	indexInfo := make(map[int]*tradeAnalysisModel.OriginTradeData)
	for _, v := range indexes {
		// eg.永安期货_si2401_持买单量
		nameArr := strings.Split(v.IndexName, "_")
		if len(nameArr) != 3 {
			continue
		}
		companyName := nameArr[0]
		if nameArr[0] == tradeAnalysisModel.GuangZhouTopCompanyAliasName {
			companyName = tradeAnalysisModel.TradeFuturesCompanyTop20
		}
		if !utils.InArrayByStr(seatNameArr, nameArr[2]) {
			continue
		}
		if !utils.InArrayByStr(queryCompanies, companyName) {
			continue
		}
		if !utils.InArrayByStr(contracts, nameArr[1]) {
			continue
		}
		indexIds = append(indexIds, v.BaseFromTradeGuangzhouIndexId)
		if indexInfo[v.BaseFromTradeGuangzhouIndexId] == nil {
			if tradeAnalysisModel.GuangzhouSeatNameValType[nameArr[2]] == 0 {
				continue
			}
			indexInfo[v.BaseFromTradeGuangzhouIndexId] = new(tradeAnalysisModel.OriginTradeData)
			indexInfo[v.BaseFromTradeGuangzhouIndexId].CompanyName = companyName
			indexInfo[v.BaseFromTradeGuangzhouIndexId].ClassifyName = classifyName
			indexInfo[v.BaseFromTradeGuangzhouIndexId].ClassifyType = nameArr[1]
			indexInfo[v.BaseFromTradeGuangzhouIndexId].ValType = tradeAnalysisModel.GuangzhouSeatNameValType[nameArr[2]]
		}
	}
	if len(indexIds) == 0 {
		return
	}

	// 查询指标数据
	indexesData, e := tradeAnalysisModel.GetBaseFromTradeGuangzhouDataByIndexIds(indexIds)
	if e != nil {
		err = fmt.Errorf("获取广期所指标数据失败, %v", e)
		return
	}
	items = make([]*tradeAnalysisModel.OriginTradeData, 0)
	for _, v := range indexesData {
		info, ok := indexInfo[v.BaseFromTradeGuangzhouIndexId]
		if !ok {
			continue
		}
		items = append(items, &tradeAnalysisModel.OriginTradeData{
			CompanyName:  info.CompanyName,
			Val:          int(v.Value),
			ValChange:    int(v.QtySub),
			DataTime:     v.DataTime,
			ClassifyName: info.ClassifyName,
			ClassifyType: info.ClassifyType,
			ValType:      info.ValType,
		})
	}
	return
}

func (g *GuangzhouTradeAnalysis) GetLastTradeDataByClassify(exchange, classifyName string, contracts []string) (items []*tradeAnalysisModel.OriginTradeData, err error) {
	classifyIdMap := map[string]int{"si": 7, "lc": 8}
	classifyId := classifyIdMap[classifyName]
	if classifyId == 0 {
		err = fmt.Errorf("品种有误")
		return
	}
	seatNameArr := []string{tradeAnalysisModel.GuangZhouSeatNameBuy, tradeAnalysisModel.GuangZhouSeatNameSold}

	// 查询品种下所有指标
	indexes, e := tradeAnalysisModel.GetBaseFromTradeGuangzhouIndexByClassifyId(classifyId)
	if e != nil {
		err = fmt.Errorf("获取广期所指标失败, %v", e)
		return
	}

	// 获取各合约下的指标
	contractIndexIds := make(map[string][]int)
	for _, v := range indexes {
		// eg.永安期货_si2401_持买单量
		nameArr := strings.Split(v.IndexName, "_")
		if len(nameArr) != 3 {
			continue
		}
		if !utils.InArrayByStr(contracts, nameArr[1]) {
			continue
		}
		if !utils.InArrayByStr(seatNameArr, nameArr[2]) {
			continue
		}
		if tradeAnalysisModel.GuangzhouSeatNameValType[nameArr[2]] == 0 {
			continue
		}
		k := fmt.Sprintf("%s-%d", nameArr[1], tradeAnalysisModel.GuangzhouSeatNameValType[nameArr[2]])
		contractIndexIds[k] = append(contractIndexIds[k], v.BaseFromTradeGuangzhouIndexId)
	}

	// ps.如果后面如果有空可以优化一下这里, 把末位数据每天写进一张表里面
	for k, v := range contractIndexIds {
		keyArr := strings.Split(k, "-")
		contract := keyArr[0]
		valType, _ := strconv.Atoi(keyArr[1])
		lastVales, e := tradeAnalysisModel.GetBaseFromTradeGuangzhouMinDataByIndexIds(v)
		if e != nil {
			err = fmt.Errorf("获取合约末位数据失败, %v", e)
			return
		}
		for _, vv := range lastVales {
			items = append(items, &tradeAnalysisModel.OriginTradeData{
				Val:          int(vv.Value),
				DataTime:     vv.DataTime,
				ClassifyType: contract,
				ValType:      valType,
			})
		}
	}
	return
}