package data

import (
	"encoding/json"
	"errors"
	"eta/eta_api/models/data_manage"
	"eta/eta_api/models/data_manage/edb_refresh"
	"eta/eta_api/models/data_manage/edb_refresh/request"
	"eta/eta_api/services/elastic"
	"eta/eta_api/utils"
	"fmt"
	"strings"
	"time"
)

// 所有刷新配置key
var allDefaultEdbRefreshConfigKey = `edb_refresh_config:default:all:`

// GetAllDefaultEdbRefreshConfigListBySourceList
// @Description: 获取默认的所有刷新配置列表
// @author: Roc
// @datetime 2024-01-10 15:03:36
// @param source int
// @param subSource int
// @return list []*edb_refresh.EdbRefreshDefaultConfig
// @return err error
func GetAllDefaultEdbRefreshConfigListBySourceList(source, subSource int) (list []*edb_refresh.EdbRefreshDefaultConfig, err error) {
	key := getAllDefaultEdbRefreshConfigKey(source, subSource)
	if utils.Re == nil {
		if utils.Re == nil && utils.Rc.IsExist(key) {
			if data, err1 := utils.Rc.RedisBytes(key); err1 == nil {
				err = json.Unmarshal(data, &list)
				return
			}
		}
	}

	list, err = edb_refresh.GetAllListBySourceList(source, subSource)
	if err != nil {
		return
	}

	// 将数据加入缓存
	if utils.Re == nil {
		data, _ := json.Marshal(list)
		utils.Rc.Put(key, data, 2*time.Hour)
	}

	return
}

// SaveEdbRefreshDefaultConfig
// @Description: 设置默认的指标刷新配置接口
// @author: Roc
// @datetime 2024-01-10 15:11:19
// @param source int
// @param subSource int
// @param frequency string
// @param list []request.RefreshConfigReq
// @return err error
// @return errMsg string
// @return isSendEmail bool
func SaveEdbRefreshDefaultConfig(source, subSource int, frequency string, list []request.RefreshConfigReq) (err error, errMsg string, isSendEmail bool) {
	isSendEmail = true
	errMsg = `保存失败`

	if source <= 0 {
		errMsg = "来源不能为空"
		err = errors.New(errMsg)
		isSendEmail = false
		return
	}

	// 非有色的来源,频度不能为空
	if source != utils.DATA_SOURCE_YS && frequency == `` {
		errMsg = "频度不能为空"
		err = errors.New(errMsg)
		isSendEmail = false
		return
	}

	lenConf := len(list)
	if lenConf == 0 {
		errMsg = "至少需要一个刷新配置"
		err = errors.New(errMsg)
		isSendEmail = false
		return
	}
	if lenConf > 5 {
		errMsg = "刷新时间设置最多不超过5个"
		err = errors.New(errMsg)
		isSendEmail = false
		return
	}

	tmpArr := []string{"每周", "每旬", "每月", "每季", "每半年", "每年"}
	// 配置的map,避免同一种类型配置同一个时间
	configMap := make(map[string]string)
	for _, v := range list {
		if utils.InArrayByStr(tmpArr, v.RefreshFrequency) && v.RefreshFrequencyDay < 0 {
			errMsg = "请选择具体日期"
			err = errors.New(errMsg)
			isSendEmail = false
			return
		}

		if v.RefreshTime == "" {
			errMsg = "请选择具体时间"
			err = errors.New(errMsg)
			isSendEmail = false
			return
		}

		// 配置的map,避免同一种类型配置同一个时间
		key := fmt.Sprint(v.RefreshFrequency, "_", v.RefreshFrequencyDay, "_", v.RefreshTime)
		if _, ok := configMap[key]; ok {
			errMsg = "刷新频率和日期不能重复"
			err = errors.New(errMsg)
			isSendEmail = false
			return
		}
		configMap[key] = key
	}

	addList := make([]*edb_refresh.EdbRefreshDefaultConfig, 0)
	for _, v := range list {
		addList = append(addList, &edb_refresh.EdbRefreshDefaultConfig{
			Source:              source,
			SubSource:           subSource,
			Frequency:           frequency,
			RefreshFrequency:    v.RefreshFrequency,
			RefreshFrequencyDay: v.RefreshFrequencyDay,
			RefreshAllData:      v.RefreshAllData,
			RefreshTime:         v.RefreshTime,
			RefreshDataNum:      v.RefreshDataNum,
			ModifyTime:          time.Now(),
			CreateTime:          time.Now(),
		})
	}

	// 保存
	err = edb_refresh.SaveEdbRefreshDefaultConfig(source, subSource, frequency, addList)

	// 清除缓存
	{
		key := getAllDefaultEdbRefreshConfigKey(source, subSource)
		if utils.Re == nil {
			_ = utils.Rc.Delete(key)
		}
	}

	return
}

// SaveEdbRefreshConfig
// @Description: 设置指标刷新配置接口
// @author: Roc
// @datetime 2024-01-10 15:41:45
// @param source int
// @param subSource int
// @param classifyId string
// @param terminalCode string
// @param frequency string
// @param keyword string
// @param status string
// @param sysUserIdStr string
// @param isSelectAll bool
// @param list []request.RefreshConfigReq
// @param edbSelectIdList []int
// @param sysUserId int
// @param sysUserRealName string
// @return err error
// @return errMsg string
// @return isSendEmail bool
func SaveEdbRefreshConfig(source, subSource int, classifyId, terminalCode, frequency, keyword, status, sysUserIdStr string, isSelectAll bool, list []request.RefreshConfigReq, edbSelectIdList []int, sysUserId int, sysUserRealName string) (err error, errMsg string, isSendEmail bool) {
	isSendEmail = true
	errMsg = `保存失败`

	if source <= 0 {
		errMsg = "来源不能为空"
		err = errors.New(errMsg)
		isSendEmail = false
		return
	}

	lenConf := len(list)
	if lenConf == 0 {
		errMsg = "至少需要一个刷新配置"
		err = errors.New(errMsg)
		isSendEmail = false
		return
	}
	if lenConf > 5 {
		errMsg = "刷新时间设置最多不超过5个"
		err = errors.New(errMsg)
		isSendEmail = false
		return
	}

	tmpArr := []string{"每周", "每旬", "每月", "每季", "每半年", "每年"}

	// 配置的map,避免同一种类型配置同一个时间
	configMap := make(map[string]string)
	for _, v := range list {
		if utils.InArrayByStr(tmpArr, v.RefreshFrequency) && v.RefreshFrequencyDay < 0 {
			errMsg = "请选择具体日期"
			err = errors.New(errMsg)
			isSendEmail = false
			return
		}

		if v.RefreshTime == "" {
			errMsg = "请选择具体时间"
			err = errors.New(errMsg)
			isSendEmail = false
			return
		}

		// 配置的map,避免同一种类型配置同一个时间
		key := fmt.Sprint(v.RefreshFrequency, "_", v.RefreshFrequencyDay, "_", v.RefreshTime)
		if _, ok := configMap[key]; ok {
			errMsg = "刷新频率和日期不能重复"
			err = errors.New(errMsg)
			isSendEmail = false
			return
		}
		configMap[key] = key
	}

	edbIdList := make([]int, 0)
	// 指标id列表
	if isSelectAll {
		// 如果是列表全选
		_, edbList, tmpErr := GetList(source, subSource, classifyId, terminalCode, sysUserIdStr, frequency, keyword, status, 0, 100000, "", "")
		if tmpErr != nil && tmpErr.Error() != utils.ErrNoRow() {
			err = tmpErr
			return
		}

		// 不配置的指标id
		notIdMap := make(map[int]int, 0)
		for _, v := range edbSelectIdList {
			notIdMap[v] = v
		}

		for _, v := range edbList {
			_, ok := notIdMap[v.EdbInfoId]
			// 在不配置的指标id列表内的话,那就过滤
			if ok {
				continue
			}

			// 加入到待配置的指标列表id
			edbIdList = append(edbIdList, v.EdbInfoId)
		}
	} else {
		edbIdList = edbSelectIdList
	}

	if len(edbIdList) <= 0 {
		errMsg = "指标不能为空"
		err = errors.New(errMsg)
		isSendEmail = false
		return
	}

	// 待添加的配置关系数据
	addMappingList := make([]*edb_refresh.EdbRefreshMapping, 0)

	// 待添加的日期配置项
	addConfigList := make([]*edb_refresh.EdbRefreshConfig, 0)
	for _, v := range list {
		item, tmpErr := edb_refresh.GetEdbRefreshConfigListByCondition(v.RefreshFrequency, v.RefreshTime, v.RefreshFrequencyDay, v.RefreshAllData, v.RefreshDataNum)
		if tmpErr != nil {
			if tmpErr.Error() != utils.ErrNoRow() {
				err = tmpErr
				return
			}

			addConfigList = append(addConfigList, &edb_refresh.EdbRefreshConfig{
				RefreshFrequency:    v.RefreshFrequency,
				RefreshFrequencyDay: v.RefreshFrequencyDay,
				RefreshTime:         v.RefreshTime,
				RefreshAllData:      v.RefreshAllData,
				RefreshDataNum:      v.RefreshDataNum,
				ModifyTime:          time.Now(),
				CreateTime:          time.Now(),
			})
			continue
		}

		for _, edbId := range edbIdList {
			addMappingList = append(addMappingList, &edb_refresh.EdbRefreshMapping{
				EdbRefreshMappingId: 0,
				Source:              source,
				SubSource:           subSource,
				EdbInfoId:           edbId,
				EdbRefreshConfigId:  item.EdbRefreshConfigId,
				SysUserId:           sysUserId,
				SysUserRealName:     sysUserRealName,
				ModifyTime:          time.Now(),
				CreateTime:          time.Now(),
			})
		}
	}

	// 保存
	err = edb_refresh.SaveEdbRefreshConfig(source, subSource, sysUserId, sysUserRealName, addConfigList, addMappingList, edbIdList)

	return
}

// HandleRefreshTime
// @Description: 处理刷新时间的显示
// @author: Roc
// @datetime 2024-01-10 17:00:03
// @param source int
// @param subSource int
// @param list []*data_manage.BaseRefreshEdbInfo
// @return newList []*data_manage.BaseRefreshEdbInfo
// @return err error
// @return errMsg string
// @return isSendEmail bool
func HandleRefreshTime(source, subSource int, list []*data_manage.BaseRefreshEdbInfo) (newList []*data_manage.BaseRefreshEdbInfo, err error, errMsg string, isSendEmail bool) {
	isSendEmail = true
	errMsg = "获取失败"
	newList = list

	// 默认刷新配置
	defaultEdbRefreshConfigMap := make(map[string]string)
	{
		// 获取默认配置
		allDefaultEdbRefreshConfigList, tmpErr := GetAllDefaultEdbRefreshConfigListBySourceList(source, subSource)
		if tmpErr != nil {
			err = tmpErr
			return
		}

		defaultEdbRefreshConfigListMap := make(map[string][]string)
		for _, v := range allDefaultEdbRefreshConfigList {
			tmp, ok := defaultEdbRefreshConfigListMap[v.Frequency]
			if !ok {
				tmp = make([]string, 0)
			}
			defaultEdbRefreshConfigListMap[v.Frequency] = append(tmp, GetRefreshStr(v.RefreshFrequency, v.RefreshFrequencyDay, v.RefreshTime))
		}
		for k, v := range defaultEdbRefreshConfigListMap {
			defaultEdbRefreshConfigMap[k] = strings.Join(v, ",")
		}

	}

	edbInfoIdList := make([]int, 0)
	for _, v := range newList {
		edbInfoIdList = append(edbInfoIdList, v.EdbInfoId)
	}

	// 指标的刷新时间配置
	edbRefreshConfigMap := make(map[int]string)
	{
		// 获取指标的单独配置
		configList, tmpErr := edb_refresh.GetEdbRefreshConfigAndEdbListBySourceAndeEdbInfoId(source, subSource, edbInfoIdList)
		if tmpErr != nil {
			err = tmpErr
			return
		}

		edbRefreshConfigListMap := make(map[int][]string)
		for _, v := range configList {
			tmp, ok := edbRefreshConfigListMap[v.EdbInfoId]
			if !ok {
				tmp = make([]string, 0)
			}
			edbRefreshConfigListMap[v.EdbInfoId] = append(tmp, GetRefreshStr(v.RefreshFrequency, v.RefreshFrequencyDay, v.RefreshTime))
		}
		for k, v := range edbRefreshConfigListMap {
			edbRefreshConfigMap[k] = strings.Join(v, ",")
		}
	}

	// 处理刷新时间
	for _, v := range newList {
		refreshTime, ok := edbRefreshConfigMap[v.EdbInfoId]
		if ok {
			v.RefreshTime = refreshTime
			continue
		}
		if source == utils.DATA_SOURCE_YS {
			v.RefreshTime = defaultEdbRefreshConfigMap[``]
		} else {
			v.RefreshTime = defaultEdbRefreshConfigMap[v.Frequency]
		}
	}

	return
}

// GetList
// @Description: 获取指标列表
// @author: Roc
// @datetime 2024-01-08 15:14:16
// @param source int
// @param subSource int
// @param classifyId string
// @param terminalCode string
// @param sysUserId string
// @param frequency string
// @param keyword string
// @param startSize int
// @param pageSize int
// @return total int
// @return list []*data_manage.BaseRefreshEdbInfo
// @return err error
func GetList(source, subSource int, classifyId, terminalCode, sysUserId, frequency, keyword, status string, startSize, pageSize int, sortParam, sortType string) (total int, list []*data_manage.BaseRefreshEdbInfo, err error) {
	var pars []interface{}
	var condition string

	list = make([]*data_manage.BaseRefreshEdbInfo, 0)

	isStop := -1
	if status == `暂停` {
		isStop = 1
	} else if status == "启用" {
		isStop = 0
	}
	keyword = strings.TrimSpace(keyword)

	switch source {
	case utils.DATA_SOURCE_MYSTEEL_CHEMICAL: // 钢联
		if classifyId != `` {
			classifyIdSlice := strings.Split(classifyId, ",")
			condition += ` AND base_from_mysteel_chemical_classify_id IN (` + utils.GetOrmInReplace(len(classifyIdSlice)) + `)`
			pars = append(pars, classifyIdSlice)
		}
		if terminalCode != `` {
			condition += " AND terminal_code = ? "
			pars = append(pars, terminalCode)
		}
		if sysUserId != `` {
			sysUserIdSlice := strings.Split(sysUserId, ",")
			condition += ` AND sys_user_id IN (` + utils.GetOrmInReplace(len(sysUserIdSlice)) + `)`
			pars = append(pars, sysUserIdSlice)
		}
		if frequency != `` {
			frequencySlice := strings.Split(frequency, ",")
			condition += ` AND frequency IN (` + utils.GetOrmInReplace(len(frequencySlice)) + `)`
			pars = append(pars, frequencySlice)
		}
		if keyword != `` {
			//keywordSlice := strings.Split(keyword, " ")
			//if len(keywordSlice) > 0 {
			//	tmpConditionSlice := make([]string, 0)
			//	tmpConditionSlice = append(tmpConditionSlice, ` index_name like ? or index_code like ? `)
			//	pars = utils.GetLikeKeywordPars(pars, keyword, 2)
			//
			//	for _, v := range keywordSlice {
			//		if v == ` ` || v == `` {
			//			continue
			//		}
			//		tmpConditionSlice = append(tmpConditionSlice, ` index_name like ? or index_code like ? `)
			//		pars = utils.GetLikeKeywordPars(pars, v, 2)
			//	}
			//	condition += ` AND (` + strings.Join(tmpConditionSlice, " or ") + `)`
			//
			//} else {
			//	condition += ` index_name like ? or index_code like ? `
			//	pars = utils.GetLikeKeywordPars(pars, keyword, 2)
			//}

			// 走ES搜
			_, esList, e := elastic.SearchDataSourceIndex(utils.EsDataSourceIndexName, keyword, utils.DATA_SOURCE_MYSTEEL_CHEMICAL, 0, []int{}, []int{}, []string{}, startSize, pageSize)
			if e != nil {
				err = fmt.Errorf("ES-搜索钢联原始指标失败, %v", e)
				return
			}
			var codes []string
			for _, v := range esList {
				codes = append(codes, v.IndexCode)
			}
			if len(codes) == 0 {
				total = 0
				list = make([]*data_manage.BaseRefreshEdbInfo, 0)
				return
			}
			condition += fmt.Sprintf(` AND index_code IN (%s)`, utils.GetOrmInReplace(len(codes)))
			pars = append(pars, codes)
		}

		if isStop >= 0 {
			condition += " AND is_stop = ? "
			pars = append(pars, isStop)
		}
		sortStr := ``
		if sortParam != `` {
			sortStr = fmt.Sprintf("%s %s,base_from_mysteel_chemical_index_id desc ", sortParam, sortType)
		}
		total, list, err = data_manage.GetMysteelChemicalBaseInfoList(condition, pars, sortStr, startSize, pageSize)
	case utils.DATA_SOURCE_YS: // 有色
		if classifyId != `` {
			classifyIdSlice := strings.Split(classifyId, ",")
			condition += ` AND classify_id IN (` + utils.GetOrmInReplace(len(classifyIdSlice)) + `)`
			pars = append(pars, classifyIdSlice)
		}
		if terminalCode != `` {
			condition += " AND terminal_code = ? "
			pars = append(pars, terminalCode)
		}
		if frequency != `` {
			frequencySlice := strings.Split(frequency, ",")
			condition += ` AND frequency IN (` + utils.GetOrmInReplace(len(frequencySlice)) + `)`
			pars = append(pars, frequencySlice)
		}
		if keyword != `` {
			//keywordSlice := strings.Split(keyword, " ")
			//if len(keywordSlice) > 0 {
			//	tmpConditionSlice := make([]string, 0)
			//	tmpConditionSlice = append(tmpConditionSlice, ` index_name like ? or index_code like ? `)
			//	pars = utils.GetLikeKeywordPars(pars, keyword, 2)
			//
			//	for _, v := range keywordSlice {
			//		if v == ` ` || v == `` {
			//			continue
			//		}
			//		tmpConditionSlice = append(tmpConditionSlice, ` index_name like ? or index_code like ? `)
			//		pars = utils.GetLikeKeywordPars(pars, v, 2)
			//	}
			//	condition += ` AND (` + strings.Join(tmpConditionSlice, " or ") + `)`
			//
			//} else {
			//	condition += ` index_name like ? or index_code like ? `
			//	pars = utils.GetLikeKeywordPars(pars, keyword, 2)
			//}

			// 走ES搜
			_, esList, e := elastic.SearchDataSourceIndex(utils.EsDataSourceIndexName, keyword, utils.DATA_SOURCE_YS, 0, []int{}, []int{}, []string{}, startSize, pageSize)
			if e != nil {
				err = fmt.Errorf("ES-搜索SMM原始指标失败, %v", e)
				return
			}
			var codes []string
			for _, v := range esList {
				codes = append(codes, v.IndexCode)
			}
			if len(codes) == 0 {
				total = 0
				list = make([]*data_manage.BaseRefreshEdbInfo, 0)
				return
			}
			condition += fmt.Sprintf(` AND index_code IN (%s)`, utils.GetOrmInReplace(len(codes)))
			pars = append(pars, codes)
		}

		if isStop >= 0 {
			condition += " AND is_stop = ? "
			pars = append(pars, isStop)
		}

		sortStr := ``
		if sortParam != `` {
			sortStr = fmt.Sprintf("%s %s,base_from_smm_index_id desc ", sortParam, sortType)
		}

		total, list, err = data_manage.GetSmmBaseInfoList(condition, pars, sortStr, startSize, pageSize)
	default:
		condition += ` AND source = ? AND sub_source = ? `
		pars = append(pars, source, subSource)

		if isStop >= 0 {
			condition += " AND no_update = ? "
			pars = append(pars, isStop)
		}

		if classifyId != `` {
			classifyIdSlice := strings.Split(classifyId, ",")
			condition += ` AND classify_id IN (` + utils.GetOrmInReplace(len(classifyIdSlice)) + `)`
			pars = append(pars, classifyIdSlice)
		}
		if terminalCode != `` {
			condition += " AND terminal_code = ? "
			pars = append(pars, terminalCode)
		}
		if sysUserId != `` {
			sysUserIdSlice := strings.Split(sysUserId, ",")
			condition += ` AND sys_user_id IN (` + utils.GetOrmInReplace(len(sysUserIdSlice)) + `)`
			pars = append(pars, sysUserIdSlice)
		}
		if frequency != `` {
			frequencySlice := strings.Split(frequency, ",")
			condition += ` AND frequency IN (` + utils.GetOrmInReplace(len(frequencySlice)) + `)`
			pars = append(pars, frequencySlice)
		}
		if keyword != `` {
			//keywordSlice := strings.Split(keyword, " ")
			//if len(keywordSlice) > 0 {
			//	tmpConditionSlice := make([]string, 0)
			//	tmpConditionSlice = append(tmpConditionSlice, ` edb_name like ? or edb_code like ? `)
			//	pars = utils.GetLikeKeywordPars(pars, keyword, 2)
			//
			//	for _, v := range keywordSlice {
			//		if v == ` ` || v == `` {
			//			continue
			//		}
			//		tmpConditionSlice = append(tmpConditionSlice, ` edb_name like ? or edb_code like ? `)
			//		pars = utils.GetLikeKeywordPars(pars, v, 2)
			//	}
			//	condition += ` AND (` + strings.Join(tmpConditionSlice, " or ") + `)`
			//
			//} else {
			//	condition += ` edb_name like ? or edb_code like ? `
			//	pars = utils.GetLikeKeywordPars(pars, keyword, 2)
			//}

			// 走ES搜
			_, esList, e := elastic.SearchEdbInfoData(utils.DATA_INDEX_NAME, keyword, startSize, pageSize, 0, source, 0, frequency, []int{})
			if e != nil {
				err = fmt.Errorf("ES-搜索指标失败, %v", e)
				return
			}
			var codes []string
			for _, v := range esList {
				codes = append(codes, v.EdbCode)
			}
			if len(codes) == 0 {
				total = 0
				list = make([]*data_manage.BaseRefreshEdbInfo, 0)
				return
			}
			condition += fmt.Sprintf(` AND edb_code IN (%s)`, utils.GetOrmInReplace(len(codes)))
			pars = append(pars, codes)
		}

		sortStr := ``
		if sortParam != `` {
			sortStr = fmt.Sprintf("%s %s,edb_info_id desc ", sortParam, sortType)
		}

		total, list, err = data_manage.GetEdbBaseInfoList(condition, pars, sortStr, startSize, pageSize)
	}

	return
}

// getAllDefaultEdbRefreshConfigKey
// @Description: 获取默认的所有刷新配置key
// @author: Roc
// @datetime 2024-01-10 15:02:49
// @param source int
// @param subSource int
// @return string
func getAllDefaultEdbRefreshConfigKey(source, subSource int) string {
	return allDefaultEdbRefreshConfigKey + fmt.Sprintf("%d_%d", source, subSource)
}

// GetRefreshStr
// @Description: 获取刷新配置的中文字符串
// @author: Roc
// @datetime 2024-01-10 16:05:10
// @param refreshFrequency string
// @param refreshFrequencyDay int
// @param refreshTime string
// @return string
func GetRefreshStr(refreshFrequency string, refreshFrequencyDay int, refreshTime string) string {
	refreshDayStr := ``
	//if refreshFrequency != "每自然日" && refreshFrequency != "每交易日"
	switch refreshFrequency {
	case "每自然日", "每交易日":
	case "每周":
		switch refreshFrequencyDay {
		case 0:
			refreshDayStr = "日"
		case 1:
			refreshDayStr = "一"
		case 2:
			refreshDayStr = "二"
		case 3:
			refreshDayStr = "三"
		case 4:
			refreshDayStr = "四"
		case 5:
			refreshDayStr = "五"
		case 6:
			refreshDayStr = "六"
		case 7:
			refreshDayStr = "日"
		}
	default:
		if refreshFrequencyDay > 0 {
			refreshDayStr = fmt.Sprintf("第%d天", refreshFrequencyDay)
		} else {
			refreshDayStr = `最后一天`
		}
	}
	return refreshFrequency + refreshDayStr + " " + refreshTime
}