package services

import (
	"encoding/json"
	"errors"
	"eta/eta_index_lib/models"
	"eta/eta_index_lib/utils"
	"fmt"
	"github.com/rdlucklib/rdluck_tools/http"
	"strings"
)

func GetEdbDataFromThsDs(stockCode, edbCode, startDate, endDate, edbTerminalCode string) (item models.EdbDataFromThs, err error) {
	terminal, err := GetTerminal(utils.DATA_SOURCE_THS, edbTerminalCode)
	if err != nil {
		err = fmt.Errorf("获取同花顺接口配置出错 Err: %s", err)
		return
	}
	if terminal.ServerUrl == "" {
		err = fmt.Errorf("同花顺接口未配置")
		return
	}

	if edbTerminalCode == "" {
		// 设置指标与终端关系的缓存
		terminalCodeCacheKey := utils.CACHE_EDB_TERMINAL_CODE_URL + stockCode
		_ = utils.Rc.Put(terminalCodeCacheKey, terminal.TerminalCode, utils.GetTodayLastSecond())
	}

	// 如果没有配置，获取配置的方式是api，那么就走官方接口
	if utils.ThsDataMethod == "" || utils.ThsDataMethod == "api" {
		var token string
		token, err = GetAccessToken(false, terminal.Value)
		if err != nil {
			return
		}
		return getEdbDataFromThsDsHttp(stockCode, edbCode, startDate, endDate, terminal.Value, token)
	}

	return getEdbDataFromThsDsApp(stockCode, edbCode, startDate, endDate, 0, terminal.ServerUrl)
}

type EdbDataFromThsSdInterface struct {
	Errorcode   int         `json:"errorcode"`
	Errmsg      string      `json:"errmsg"`
	Tables      []Table     `json:"tables"`
	Datatype    []Type      `json:"datatype"`
	InputParams interface{} `json:"inputParams"`
	DataVol     int         `json:"dataVol"`
	Perf        int         `json:"perf"`
}

type Table struct {
	Thscode string                 `json:"thscode"`
	Time    []string               `json:"time"`
	Table   map[string]interface{} `json:"table"`
}

type StockData struct {
	THSOpenPriceStock     []float64 `json:"ths_open_price_stock"`
	THSHighPriceStock     []float64 `json:"ths_high_price_stock"`
	THSLowStock           []float64 `json:"ths_low_stock"`
	THSClosePriceStock    []float64 `json:"ths_close_price_stock"`
	THSChgRatioStock      []float64 `json:"ths_chg_ratio_stock"`
	THSChgStock           []float64 `json:"ths_chg_stock"`
	THSVolStock           []float64 `json:"ths_vol_stock"`
	THSPreCloseStock      []float64 `json:"ths_pre_close_stock"`
	THSSwingStock         []float64 `json:"ths_swing_stock"`
	THSTurnoverRatioStock []float64 `json:"ths_turnover_ratio_stock"`
	THSAmtStock           []float64 `json:"ths_amt_stock"`
}

type Type struct {
	Itemid string `json:"itemid"`
	Type   string `json:"type"`
}

//
//type Params struct {
//	Jsonrpc bool     `json:"jsonrpc"`
//	Params  []Param  `json:"params"`
//}
//
//type Param struct {
//	Function string   `json:"function"`
//	ID       string   `json:"id"`
//	Params   []Param2 `json:"params"`
//}
//
//type Param2 struct {
//	Name   string `json:"name"`
//	System string `json:"system"`
//	Value  string `json:"value"`
//}

// getEdbDataFromThsDs 获取同花顺接口数据
func getEdbDataFromThsDsApp(stockCode, edbCode, startDate, endDate string, num int, serverUrl string) (item models.EdbDataFromThs, err error) {
	if serverUrl == `` {
		err = errors.New("同花顺接口未配置")
		return
	}
	thsUrl := serverUrl + `edbInfo/ths/ds?StockCode=%s&EdbCode=%s&StartDate=%s&EndDate=%s`
	thsUrl = fmt.Sprintf(thsUrl, stockCode, edbCode, startDate, endDate)
	utils.FileLog.Info("thsUrl:" + thsUrl)
	body, err := http.Get(thsUrl)
	utils.FileLog.Info("ths result:" + string(body))
	if err != nil {
		err = errors.New(" Err:" + err.Error() + ";result:" + string(body))
		return
	}
	if string(body) == "null" {
		err = errors.New("同花顺数据获取异常:" + err.Error() + ";result:" + string(body))
		return
	}
	println(string(body))
	tablesList := make([]models.Tables, 0)
	var errCode int64
	if strings.Contains(edbCode, ",") {
		var jsonArray []string
		if err = json.Unmarshal(body, &jsonArray); err != nil {
			fmt.Println("json.Unmarshal Err:", err)
			return
		}
		// 解码数组内的每个 JSON 字符串
		//var responses []TerminalResponse

		for _, data := range jsonArray {
			data = strings.Replace(data, "NaN", "null", -1)
			tableTimeList := make([]string, 0)
			tableValueList := make([]float64, 0)
			var response TerminalResponse
			if err = json.Unmarshal([]byte(data), &response); err != nil {
				fmt.Println("json.Unmarshal Err:", err)
				return
			}

			errCode = int64(response.ErrorCode)
			if response.ErrorCode != 0 {
				//session has expired,please re-login after using the system
				//如果是同花顺登录session失效了，那么就重新请求获取数据
				if response.ErrorCode == -1020 && num == 0 {
					return getEdbDataFromThsDsApp(stockCode, edbCode, startDate, endDate, 1, serverUrl)
				}
				err = errors.New(string(body))
				return
			}

			for _, stockData := range response.Data {
				time := stockData["time"].(string)
				//thsCode := stockData["thscode"].(string)
				//tableTimeList = append(tableTimeList, time)

				for k, v := range stockData {
					if k != "time" && k != "thscode" {
						if v != nil {
							tableTimeList = append(tableTimeList, time)
							tableValueList = append(tableValueList, v.(float64))
						}
					}
				}
			}
			tmpTable := models.Tables{
				ID:    []string{},
				Time:  tableTimeList,
				Value: tableValueList,
			}
			tablesList = append(tablesList, tmpTable)
		}
	} else {
		var data string
		if err = json.Unmarshal(body, &data); err != nil {
			fmt.Println("json.Unmarshal Err:", err)
			return
		}
		// 解码数组内的每个 JSON 字符串
		//var responses []TerminalResponse
		data = strings.Replace(data, "NaN", "null", -1)
		tableTimeList := make([]string, 0)
		tableValueList := make([]float64, 0)
		var response TerminalResponse
		if err = json.Unmarshal([]byte(data), &response); err != nil {
			fmt.Println("json.Unmarshal Err:", err)
			return
		}

		errCode = int64(response.ErrorCode)
		if response.ErrorCode != 0 {
			//session has expired,please re-login after using the system
			//如果是同花顺登录session失效了，那么就重新请求获取数据
			if response.ErrorCode == -1020 && num == 0 {
				return getEdbDataFromThsDsApp(stockCode, edbCode, startDate, endDate, 1, serverUrl)
			}
			err = errors.New(string(body))
			return
		}

		for _, stockData := range response.Data {
			time := stockData["time"].(string)
			//thsCode := stockData["thscode"].(string)

			for k, v := range stockData {
				if k != "time" && k != "thscode" {
					if v != nil {
						tableTimeList = append(tableTimeList, time)
						tableValueList = append(tableValueList, v.(float64))
					}
				}
			}
		}
		tmpTable := models.Tables{
			ID:    []string{},
			Time:  tableTimeList,
			Value: tableValueList,
		}
		tablesList = append(tablesList, tmpTable)

	}

	item = models.EdbDataFromThs{
		DataVol:   0,
		Errmsg:    "",
		Errorcode: errCode,
		Perf:      "",
		Tables:    tablesList,
	}
	//tmpItems := new([]TerminalResponse)
	//err = json.Unmarshal(body, &tmpItems)
	//if err != nil {
	//	err = errors.New("GetEdbDataFromThs json.Unmarshal Err:" + err.Error())
	//	return
	//}

	//// 因为table里面的value有的时候返回的是string,有的是float64，所以需要用interface来反射取值
	//tablesList := make([]models.Tables, 0)
	//for _, table := range tmpItems.Tables {
	//	tableIdList := make([]string, 0)
	//	tableTimeList := make([]string, 0)
	//	tableValueList := make([]float64, 0)
	//
	//	for _, tableId := range table.ID {
	//		tableIdList = append(tableIdList, tableId)
	//	}
	//	for _, tableTime := range table.Time {
	//		tableTimeList = append(tableTimeList, tableTime)
	//	}
	//
	//	//指标数据
	//	for _, tmpValue := range table.Value {
	//		var tableValue float64
	//		if reflect.TypeOf(tmpValue).Kind() == reflect.Float64 {
	//			tableValue = reflect.ValueOf(tmpValue).Float()
	//		} else if reflect.TypeOf(tmpValue).Kind() == reflect.String {
	//			tmpTableValue, tmpErr := decimal.NewFromString(reflect.ValueOf(tmpValue).String())
	//			if tmpErr != nil {
	//				err = tmpErr
	//				return
	//			}
	//			tableValue, _ = tmpTableValue.Truncate(4).Float64()
	//		} else {
	//			err = errors.New("错误的数据类型" + reflect.TypeOf(tmpValue).String())
	//			return
	//		}
	//		tableValueList = append(tableValueList, tableValue)
	//	}
	//	tmpTable := models.Tables{
	//		ID:    tableIdList,
	//		Time:  tableTimeList,
	//		Value: tableValueList,
	//	}
	//	tablesList = append(tablesList, tmpTable)
	//}
	//item = models.EdbDataFromThs{
	//	DataVol:   tmpItems.DataVol,
	//	Errmsg:    tmpItems.Errmsg,
	//	Errorcode: tmpItems.Errorcode,
	//	Perf:      tmpItems.Perf,
	//	Tables:    tablesList,
	//}
	return item, nil
}
