package models

import (
	"eta/eta_index_lib/utils"
	"fmt"
	"github.com/beego/beego/v2/client/orm"
	"strconv"
	"strings"
	"time"
)

type BaseFromTradeEicIndex struct {
	BaseFromEicIndexId     int `orm:"column(base_from_eic_index_id);pk"`
	Country                string
	Type                   string
	EicCode                string
	ShortName              string
	Name                   string
	Status                 string
	GasDayStartedOn        string
	GasInStorage           string
	GasInStorageCode       string
	Full                   string
	FullCode               string
	Trend                  string
	TrendCode              string
	Injection              string
	InjectionCode          string
	Withdrawal             string
	WithdrawalCode         string
	WorkingGasVolume       string
	WorkingGasVolumeCode   string
	InjectionCapacity      string
	InjectionCapacityCode  string
	WithdrawalCapacity     string
	WithdrawalCapacityCode string
	Info                   string
	CreateTime             time.Time
	ModifyTime             time.Time
}

type BaseFromTradeEicIndexV2 struct {
	BaseFromEicIndexId     int `orm:"column(base_from_eic_index_id);pk"`
	Type                   string
	EicCode                string
	Name                   string
	Status                 string
	GasDayStart            string
	GasInStorage           string
	GasInStorageCode       string
	Consumption            string
	ConsumptionCode        string
	ConsumptionFull        string
	ConsumptionFullCode    string
	Full                   string
	FullCode               string
	Trend                  string
	TrendCode              string
	Injection              string
	InjectionCode          string
	Withdrawal             string
	WithdrawalCode         string
	WorkingGasVolume       string
	WorkingGasVolumeCode   string
	InjectionCapacity      string
	InjectionCapacityCode  string
	WithdrawalCapacity     string
	WithdrawalCapacityCode string
	Info                   string
	Parent                 string
	CreateTime             time.Time
	ModifyTime             time.Time
}

func GetBaseFromEicDataAllByIndexCode(indexCode, suffix string) (list []*BaseFromTradeEicIndexV2, err error) {
	o := orm.NewOrm()
	var name string
	if suffix == "" {
		name = "eic_code"
	} else if suffix == "GS" {
		name = "gas_in_storage_code"
	} else if suffix == "C" {
		name = "consumption_code"
	} else if suffix == "CF" {
		name = "consumption_full_code"
	} else if suffix == "F" {
		name = "full_code"
	} else if suffix == "T" {
		name = "trend_code"
	} else if suffix == "In" {
		name = "injection_code"
	} else if suffix == "Out" {
		name = "withdrawal_code"
	} else if suffix == "WGV" {
		name = "working_gas_volume_code"
	} else if suffix == "IC" {
		name = "injection_capacity_code"
	} else if suffix == "WC" {
		name = "withdrawal_capacity_code"
	}
	sql := `SELECT * FROM base_from_trade_eic_index_v2 WHERE %s=? `
	sql = fmt.Sprintf(sql, name)
	_, err = o.Raw(sql, indexCode).QueryRows(&list)
	return
}

func GetGieDataByTradeCode(condition string, pars []interface{}) (item []*BaseFromTradeEicIndex, err error) {
	sql := ` SELECT * FROM base_from_trade_eic_index WHERE 1=1 `
	o := orm.NewOrm()
	if condition != "" {
		sql += condition
	}
	sql += ` ORDER BY gas_day_started_on DESC `
	fmt.Println(sql, pars)
	_, err = o.Raw(sql, pars).QueryRows(&item)
	return
}

func GetGieDataByTradeCodeV2(condition string, pars []interface{}) (item []*BaseFromTradeEicIndexV2, err error) {
	sql := ` SELECT * FROM base_from_trade_eic_index_v2 WHERE 1=1 `
	o := orm.NewOrm()
	if condition != "" {
		sql += condition
	}
	sql += ` ORDER BY gas_day_start DESC `
	fmt.Println(sql, pars)
	_, err = o.Raw(sql, pars).QueryRows(&item)
	return
}

// 新增欧洲天然气指标数据
func AddEdbDataFromGie(edbCode string) (err error) {
	var suffix string
	l := len(edbCode)
	if strings.Contains(edbCode[l-2:], "GS") {
		suffix = "GS"
	} else if strings.Contains(edbCode[l-2:], "CF") {
		suffix = "CF"
	} else if strings.Contains(edbCode[l-1:], "T") {
		suffix = "T"
	} else if strings.Contains(edbCode[l-2:], "In") {
		suffix = "In"
	} else if strings.Contains(edbCode[l-3:], "Out") {
		suffix = "Out"
	} else if strings.Contains(edbCode[l-3:], "WGV") {
		suffix = "WGV"
	} else if strings.Contains(edbCode[l-2:], "IC") {
		suffix = "IC"
	} else if strings.Contains(edbCode[l-2:], "WC") {
		suffix = "WC"
	} else if strings.Contains(edbCode[l-1:], "F") {
		suffix = "F"
	} else if strings.Contains(edbCode[l-1:], "C") {
		suffix = "C"
	} else {
		suffix = ""
	}

	o := orm.NewOrm()
	eicBaseDataAll, err := GetBaseFromEicDataAllByIndexCode(edbCode, suffix)
	if err != nil && err.Error() != utils.ErrNoRow() {
		fmt.Println("GetBaseFromEicDataAllByIndexCode err:", err)
		return
	}

	var isAdd bool
	addSql := ` INSERT INTO edb_data_gie(edb_info_id,edb_code,data_time,value,create_time,modify_time,data_timestamp) values `
	existMap := make(map[string]string)

	for _, sv := range eicBaseDataAll {
		eDate := sv.GasDayStart
		dataTime, err := time.ParseInLocation(utils.FormatDate, eDate, time.Local)
		if err != nil {
			fmt.Println("time.Parse Err:" + eDate)
			return err
		}
		timestamp := dataTime.UnixNano() / 1e6
		timeStr := fmt.Sprintf("%d", timestamp)
		//var name string
		if _, ok := existMap[eDate]; !ok {
			if suffix == "GS" {
				//name = "gas_in_storage"
				addSql += GetAddSql("0", edbCode, eDate, timeStr, sv.GasInStorage)
				existMap[eDate] = sv.GasInStorage
			} else if suffix == "C" {
				//name = "consumption"
				addSql += GetAddSql("0", edbCode, eDate, timeStr, sv.Full)
				existMap[eDate] = sv.Consumption
			} else if suffix == "CF" {
				//name = "consumption_full"
				addSql += GetAddSql("0", edbCode, eDate, timeStr, sv.Full)
				existMap[eDate] = sv.ConsumptionFull
			} else if suffix == "F" {
				//name = "full"
				addSql += GetAddSql("0", edbCode, eDate, timeStr, sv.Full)
				existMap[eDate] = sv.Full
			} else if suffix == "T" {
				//name = "trend"
				addSql += GetAddSql("0", edbCode, eDate, timeStr, sv.Trend)
				existMap[eDate] = sv.Trend
			} else if suffix == "In" {
				//name = "injection"
				addSql += GetAddSql("0", edbCode, eDate, timeStr, sv.Injection)
				existMap[eDate] = sv.Injection
			} else if suffix == "Out" {
				//name = "withdrawal"
				addSql += GetAddSql("0", edbCode, eDate, timeStr, sv.Withdrawal)
				existMap[eDate] = sv.Withdrawal
			} else if suffix == "WGV" {
				//name = "working_gas_volume"
				addSql += GetAddSql("0", edbCode, eDate, timeStr, sv.WorkingGasVolume)
				existMap[eDate] = sv.WorkingGasVolume
			} else if suffix == "IC" {
				//name = "injection_capacity"
				addSql += GetAddSql("0", edbCode, eDate, timeStr, sv.InjectionCapacity)
				existMap[eDate] = sv.InjectionCapacity
			} else if suffix == "WC" {
				//name = "withdrawal_capacity"
				addSql += GetAddSql("0", edbCode, eDate, timeStr, sv.WithdrawalCapacity)
				existMap[eDate] = sv.WithdrawalCapacity
			}
			isAdd = true
		}
	}
	if isAdd {
		addSql = strings.TrimRight(addSql, ",")
		utils.FileLog.Info("addSql:" + addSql)
		_, err = o.Raw(addSql).Exec()
		if err != nil {
			fmt.Println("addSql err:", err)
			return err
		}
	}
	return
}

// 刷新欧洲天然气指标数据
func RefreshEdbDataFromGie(edbInfoId int, edbCode, startDate string) (err error) {
	source := utils.DATA_SOURCE_GIE
	subSource := utils.DATA_SUB_SOURCE_EDB

	o := orm.NewOrm()
	if err != nil {
		return
	}
	var suffix string
	l := len(edbCode)
	if strings.Contains(edbCode[l-2:], "GS") {
		suffix = "GS"
	} else if strings.Contains(edbCode[l-2:], "CF") {
		suffix = "CF"
	} else if strings.Contains(edbCode[l-1:], "T") {
		suffix = "T"
	} else if strings.Contains(edbCode[l-2:], "In") {
		suffix = "In"
	} else if strings.Contains(edbCode[l-3:], "Out") {
		suffix = "Out"
	} else if strings.Contains(edbCode[l-3:], "WGV") {
		suffix = "WGV"
	} else if strings.Contains(edbCode[l-2:], "IC") {
		suffix = "IC"
	} else if strings.Contains(edbCode[l-2:], "WC") {
		suffix = "WC"
	} else if strings.Contains(edbCode[l-1:], "F") {
		suffix = "F"
	} else if strings.Contains(edbCode[l-1:], "C") {
		suffix = "C"
	} else {
		suffix = ""
	}
	edbInfoIdStr := strconv.Itoa(edbInfoId)
	//计算数据
	var condition string
	var pars []interface{}

	if edbCode != "" {
		condition += " AND eic_code=? "
		pars = append(pars, edbCode[:l-len(suffix)])
	}

	if startDate != "" {
		condition += " AND gas_day_start>=? "
		pars = append(pars, startDate)
	}
	eicDataList, err := GetGieDataByTradeCodeV2(condition, pars)
	if err != nil {
		return
	}
	fmt.Println("all eicDataList", len(eicDataList))

	// 真实数据的最大日期  , 插入规则配置的日期
	var realDataMaxDate, edbDataInsertConfigDate time.Time
	var edbDataInsertConfig *EdbDataInsertConfig
	var isFindConfigDateRealData bool //是否找到配置日期的实际数据的值
	{
		edbDataInsertConfig, err = GetEdbDataInsertConfigByEdbId(edbInfoId)
		if err != nil && err.Error() != utils.ErrNoRow() {
			return
		}
		if edbDataInsertConfig != nil {
			edbDataInsertConfigDate = edbDataInsertConfig.Date
		}
	}

	//获取指标所有数据
	var existCondition string
	var existPars []interface{}

	existCondition += " AND edb_info_id=? "
	existPars = append(existPars, edbInfoId)
	if startDate != "" {
		existCondition += " AND data_time>=? "
		existPars = append(existPars, startDate)
	}

	existList, err := GetEdbDataByCondition(source, subSource, existCondition, existPars)
	if err != nil {
		return err
	}
	existMap := make(map[string]*EdbInfoSearchData)
	for _, v := range existList {
		existMap[v.DataTime] = v
	}

	addSql := ` INSERT INTO edb_data_gie(edb_info_id,edb_code,data_time,value,create_time,modify_time,data_timestamp) values `
	var isAdd bool
	dataMap := make(map[string]interface{})
	for _, v := range eicDataList {
		var value string
		if suffix == "GS" {
			value = v.GasInStorage
		} else if suffix == "C" {
			value = v.Consumption
		} else if suffix == "CF" {
			value = v.ConsumptionFull
		} else if suffix == "F" {
			value = v.Full
		} else if suffix == "T" {
			value = v.Trend
		} else if suffix == "In" {
			value = v.Injection
		} else if suffix == "Out" {
			value = v.Withdrawal
		} else if suffix == "WGV" {
			value = v.WorkingGasVolume
		} else if suffix == "IC" {
			value = v.InjectionCapacity
		} else if suffix == "WC" {
			value = v.WithdrawalCapacity
		}
		item := v
		itemValue := value
		eDate := item.GasDayStart
		dataTime, err := time.ParseInLocation(utils.FormatDate, eDate, time.Local)
		if err != nil {
			return err
		}
		if findItem, ok := existMap[v.GasDayStart]; !ok {
			sValue := itemValue
			if sValue != "" {
				timestamp := dataTime.UnixNano() / 1e6
				timeStr := fmt.Sprintf("%d", timestamp)
				saveValue := sValue

				if _, ok := dataMap[eDate]; !ok {
					addSql += GetAddSql(edbInfoIdStr, edbCode, eDate, timeStr, saveValue)
					isAdd = true
				}
			}
		} else {
			if findItem != nil && utils.SubFloatToString(findItem.Value, 30) != itemValue {
				err = ModifyEdbDataById(source, subSource, findItem.EdbDataId, itemValue)
				if err != nil {
					return err
				}
			}
		}
		dataMap[v.GasDayStart] = v.GasDayStart

		// 下面代码主要目的是处理掉手动插入的数据判断
		{
			if realDataMaxDate.IsZero() || dataTime.After(realDataMaxDate) {
				realDataMaxDate = dataTime
			}
			if edbDataInsertConfigDate.IsZero() || dataTime.Equal(edbDataInsertConfigDate) {
				isFindConfigDateRealData = true
			}
		}
	}

	// 处理手工数据补充的配置
	HandleConfigInsertEdbData(realDataMaxDate, edbDataInsertConfig, edbInfoId, source, subSource, existMap, isFindConfigDateRealData)

	if isAdd {
		addSql = strings.TrimRight(addSql, ",")
		_, err = o.Raw(addSql).Exec()
		if err != nil {
			return err
		}
	}
	return
}