package eta_forum

import (
	"encoding/json"
	"eta/eta_api/models/data_manage"
	"eta/eta_api/models/data_manage/chart_theme"
	"eta/eta_api/models/system"
	"eta/eta_api/services/alarm_msg"
	"eta/eta_api/utils"
	"fmt"
)

type UploadChartToForumReq struct {
	ChartInfoId int    `description:"图表ID"`
	Description string `description:"逻辑简述"`
}

type UpdateChartToForumReq struct {
	ChartInfoId int `description:"图表ID"`
}

type ChartSaveLibReq struct {
	ChartInfo               *data_manage.ChartInfo
	Description             string `description:"逻辑简述"`
	EdbInfoList             []*data_manage.EdbInfo
	ChartThemeList          []*chart_theme.ChartTheme
	EdbInfoDataList         []*AddEdbDataReq
	ChartEdbMapping         []*data_manage.ChartEdbMapping
	EdbInfoCalculateMapping []*data_manage.EdbInfoCalculateMapping
	CreatorInfo             *system.Admin //创建者的账号信息
	UploaderInfo            *system.Admin //上传者的账号信息
}

type ChartSaveLibResp struct {
	Ret         int
	Msg         string
	ErrMsg      string
	ErrCode     string
	Data        *data_manage.AddChartInfoResp
	Success     bool `description:"true 执行成功，false 执行失败"`
	IsSendEmail bool `json:"-" description:"true 发送邮件，false 不发送邮件"`
	IsAddLog    bool `json:"-" description:"true 新增操作日志，false 不新增操作日志" `
}

type AddEdbDataReq struct {
	EdbCode  string
	EdbType  int
	DataList []*data_manage.EdbDataBase
}

type DeleteChartReq struct {
	ChartInfoId int `description:"图表id"`
}

// UploadChart 上传图表接口
func UploadChart(chartInfoId int, description string, uploaderInfo *system.Admin) (err error, errMsg string) {
	defer func() {
		if err != nil {
			go alarm_msg.SendAlarmMsg(fmt.Sprintf("上传图表至社区失败：Err:%v,ErrMsg:%s", err, errMsg), 3)
		}
	}()
	// 查询图表信息
	chartInfo, err := data_manage.GetChartInfoById(chartInfoId)
	if err != nil {
		if err.Error() == utils.ErrNoRow() {
			errMsg = "图表不存在"
			err = fmt.Errorf(errMsg)
			return
		}
		errMsg = "获取图表信息失败"
		err = fmt.Errorf("获取图表信息失败,Err:" + err.Error())
		return
	}
	if chartInfo.ForumChartInfoId > 0 {
		errMsg = "该图表已上传至社区，无法再次上传"
		err = fmt.Errorf(errMsg)
		return
	}
	//查询图表主题

	//查询图表指标
	//获取原图表关联的指标信息列表
	chartMappingList, err := data_manage.GetChartMappingList(chartInfoId)
	if err != nil {
		errMsg = "获取图表关联的指标信息失败"
		err = fmt.Errorf("获取图表关联的指标信息失败,Err:" + err.Error())
		return
	}
	edbIds := make([]int, 0)
	for _, v := range chartMappingList {
		edbIds = append(edbIds, v.EdbInfoId)
	}
	var (
		edbInfoList     []*data_manage.EdbInfo
		edbMappingList  []*data_manage.EdbInfoCalculateMapping
		edbInfoDataList []*AddEdbDataReq
	)
	//查询指标详情
	edbInfoList, edbMappingList, edbInfoDataList, err = GetEdbListByEdbInfoId(edbIds)
	if err != nil {
		errMsg = "获取指标详情失败"
		err = fmt.Errorf("获取指标详情失败,Err:" + err.Error())
		return
	}

	req := new(ChartSaveLibReq)
	req.ChartInfo = chartInfo
	req.ChartEdbMapping = chartMappingList
	req.EdbInfoList = edbInfoList
	req.EdbInfoDataList = edbInfoDataList
	req.EdbInfoCalculateMapping = edbMappingList
	req.Description = description

	// 查询创建者信息
	creatorInfo, _ := system.GetSysAdminById(chartInfo.SysUserId)
	if creatorInfo != nil {
		req.CreatorInfo = creatorInfo
	}

	req.UploaderInfo = uploaderInfo
	// 添加计算指标
	reqJson, err := json.Marshal(req)
	if err != nil {
		errMsg = "参数解析异常"
		err = fmt.Errorf("参数解析异常,Err:" + err.Error())
		return
	}
	respItem, err := ChartSaveLib(string(reqJson))
	if err != nil {
		errMsg = "上传失败"
		err = fmt.Errorf("上传失败,Err:" + err.Error())
		return
	}
	if respItem.Ret != 200 {
		errMsg = "上传失败"
		err = fmt.Errorf(respItem.ErrMsg)
		return
	}

	if respItem.Data != nil && respItem.Data.ChartInfoId != 0 {
		// 更新社区返回的图表ID
		err = data_manage.SetForumChartInfoId(chartInfoId, respItem.Data.ChartInfoId)
		if err != nil {
			errMsg = "更新图表ID失败"
			err = fmt.Errorf("更新图表ID失败,Err:" + err.Error())
			return
		}
	}

	return
}

// UpdateChart 更新社区里的图表接口
func UpdateChart(chartInfoId int) (err error, errMsg string) {
	defer func() {
		if err != nil {
			go alarm_msg.SendAlarmMsg(fmt.Sprintf("同步图表信息至社区失败：Err:%v,ErrMsg:%s", err, errMsg), 3)
		}
	}()
	// 查询图表信息
	chartInfo, err := data_manage.GetChartInfoById(chartInfoId)
	if err != nil {
		if err.Error() == utils.ErrNoRow() {
			errMsg = "图表不存在"
			err = fmt.Errorf(errMsg)
			return
		}
		errMsg = "获取图表信息失败"
		err = fmt.Errorf("获取图表信息失败,Err:" + err.Error())
		return
	}

	if chartInfo.ForumChartInfoId <= 0 {
		errMsg = "该图表未上传至社区"
		err = fmt.Errorf(errMsg)
		return
	}
	//查询图表主题

	//查询图表指标
	//获取原图表关联的指标信息列表
	chartMappingList, err := data_manage.GetChartMappingList(chartInfoId)
	if err != nil {
		errMsg = "获取图表关联的指标信息失败"
		err = fmt.Errorf("获取图表关联的指标信息失败,Err:" + err.Error())
		return
	}
	edbIds := make([]int, 0)
	for _, v := range chartMappingList {
		edbIds = append(edbIds, v.EdbInfoId)
	}
	var (
		edbInfoList     []*data_manage.EdbInfo
		edbMappingList  []*data_manage.EdbInfoCalculateMapping
		edbInfoDataList []*AddEdbDataReq
	)
	//查询指标详情
	edbInfoList, edbMappingList, edbInfoDataList, err = GetEdbListByEdbInfoId(edbIds)
	if err != nil {
		errMsg = "获取指标详情失败"
		err = fmt.Errorf("获取指标详情失败,Err:" + err.Error())
		return
	}
	req := new(ChartSaveLibReq)
	req.ChartInfo = chartInfo
	req.ChartInfo.ChartInfoId = chartInfo.ForumChartInfoId
	req.ChartEdbMapping = chartMappingList
	req.EdbInfoList = edbInfoList
	req.EdbInfoDataList = edbInfoDataList
	req.EdbInfoCalculateMapping = edbMappingList
	// 查询创建者信息
	creatorInfo, _ := system.GetSysAdminById(chartInfo.SysUserId)
	if creatorInfo != nil {
		req.CreatorInfo = creatorInfo
	}

	// 添加计算指标
	reqJson, err := json.Marshal(req)
	if err != nil {
		errMsg = "参数解析异常"
		err = fmt.Errorf("参数解析异常,Err:" + err.Error())
		return
	}
	respItem, err := ChartUpdateLib(string(reqJson))
	if err != nil {
		errMsg = "更新失败"
		err = fmt.Errorf("上传失败,Err:" + err.Error())
		return
	}
	if respItem.Ret != 200 {
		errMsg = "更新失败"
		err = fmt.Errorf(respItem.ErrMsg)
		return
	}

	return
}

func GetEdbListByEdbInfoId(edbInfoIds []int) (edbInfoList []*data_manage.EdbInfo, edbMappingList []*data_manage.EdbInfoCalculateMapping, edbInfoDataList []*AddEdbDataReq, err error) {
	//查询指标信息
	//查询指标映射
	//查询所有指标数据
	//查询这个指标相关的mapping信息放到数组里，
	//将得到的指标ID信息放到数组里
	hasFindMap := make(map[int]struct{})
	edbInfoIdMap := make(map[int]struct{})
	edbMappingList = make([]*data_manage.EdbInfoCalculateMapping, 0)
	edbMappingMap := make(map[int]struct{})
	for _, edbInfoId := range edbInfoIds {
		edbMappingList, err = traceEdbInfoByEdbInfoId(edbInfoId, hasFindMap, edbInfoIdMap, edbMappingList, edbMappingMap)
		if err != nil {
			err = fmt.Errorf(" traceEdbInfoByEdbInfoId err: %s", err.Error())
			return
		}
	}

	// 指标信息map
	edbInfoIdList := make([]int, 0)
	for k, _ := range edbInfoIdMap {
		edbInfoIdList = append(edbInfoIdList, k)
	}
	edbInfoList, err = data_manage.GetEdbInfoByIdList(edbInfoIdList)
	if err != nil {
		err = fmt.Errorf(" GetEdbInfoByIdList err: %s", err.Error())
		return
	}

	for _, v := range edbInfoList {
		var dataList []*data_manage.EdbDataBase
		if v.Source == utils.DATA_SOURCE_BUSINESS {
			dataList, err = data_manage.GetEdbDataBaseMongoByEdbInfoId(v.EdbInfoId, v.Source, v.SubSource)
		} else {
			dataList, err = data_manage.GetEdbDataBaseByEdbInfoId(v.EdbInfoId, v.Source, v.SubSource)
		}

		if err != nil {
			err = fmt.Errorf("查询指标数据失败 Err: %s", err.Error())
			return
		}

		tmp := new(AddEdbDataReq)
		tmp.EdbCode = v.EdbCode
		tmp.EdbType = v.EdbType
		tmp.DataList = dataList
		edbInfoDataList = append(edbInfoDataList, tmp)
	}
	return
}

// traceEdbInfoByEdbInfoId 指标追溯
func traceEdbInfoByEdbInfoId(edbInfoId int, hasFindMap map[int]struct{}, edbInfoIdMap map[int]struct{}, edbMappingList []*data_manage.EdbInfoCalculateMapping, edbMappingMap map[int]struct{}) (newEdbMappingList []*data_manage.EdbInfoCalculateMapping, err error) {
	newEdbMappingList = edbMappingList

	_, ok := hasFindMap[edbInfoId]
	if ok {
		return
	}

	if _, ok1 := edbInfoIdMap[edbInfoId]; !ok1 {
		edbInfoIdMap[edbInfoId] = struct{}{}
	}

	edbInfoMappingList, e := data_manage.GetEdbInfoCalculateMappingListByEdbInfoId(edbInfoId)
	if e != nil {
		err = fmt.Errorf("GetEdbInfoCalculateMappingListByEdbInfoId err: %s", e.Error())
		return
	}

	if len(edbInfoMappingList) > 0 {
		fromEdbInfoIdList := make([]int, 0)
		for _, v := range edbInfoMappingList {
			fromEdbInfoIdList = append(fromEdbInfoIdList, v.FromEdbInfoId)
			if _, ok1 := edbInfoIdMap[v.FromEdbInfoId]; !ok1 {
				edbInfoIdMap[v.FromEdbInfoId] = struct{}{}
			}
			if _, ok2 := edbMappingMap[v.EdbInfoCalculateMappingId]; !ok2 {
				edbMappingMap[v.EdbInfoCalculateMappingId] = struct{}{}
				tmp := &data_manage.EdbInfoCalculateMapping{
					EdbInfoCalculateMappingId: v.EdbInfoCalculateMappingId,
					EdbInfoId:                 v.EdbInfoId,
					Source:                    v.Source,
					SourceName:                v.SourceName,
					EdbCode:                   v.EdbCode,
					FromEdbInfoId:             v.FromEdbInfoId,
					FromEdbCode:               v.FromEdbCode,
					FromEdbName:               v.FromEdbName,
					FromSource:                v.FromSource,
					FromSourceName:            v.FromSourceName,
					FromTag:                   v.FromTag,
					Sort:                      v.Sort,
					CreateTime:                v.CreateTime,
					ModifyTime:                v.ModifyTime,
				}
				newEdbMappingList = append(newEdbMappingList, tmp)
			}

			if edbInfoId != v.FromEdbInfoId && (v.FromEdbType == 2 || v.FromEdbInfoType == 1) {
				// 查过了就不查了
				if _, ok2 := hasFindMap[v.FromEdbInfoId]; !ok2 {
					newEdbMappingList, e = traceEdbInfoByEdbInfoId(v.FromEdbInfoId, hasFindMap, edbInfoIdMap, newEdbMappingList, edbMappingMap)
					if e != nil {
						err = fmt.Errorf("traceEdbInfoByEdbInfoId err: %s", e.Error())
						return
					}
				}
			}
			hasFindMap[v.FromEdbInfoId] = struct{}{}
		}
	}

	hasFindMap[edbInfoId] = struct{}{}
	return
}

// DeleteChart 上传图表接口
func DeleteChart(chartInfoId int) (err error, errMsg string) {
	// 查询图表信息
	chartInfo, err := data_manage.GetChartInfoById(chartInfoId)
	if err != nil {
		if err.Error() == utils.ErrNoRow() {
			errMsg = "图表不存在"
			err = fmt.Errorf(errMsg)
			return
		}
		errMsg = "获取图表信息失败"
		err = fmt.Errorf("获取图表信息失败,Err:" + err.Error())
		return
	}
	if chartInfo.ForumChartInfoId <= 0 {
		errMsg = "该图表未上传至社区，无需撤回"
		err = fmt.Errorf(errMsg)
		return
	}

	req := new(DeleteChartReq)
	req.ChartInfoId = chartInfo.ForumChartInfoId

	// 添加计算指标
	reqJson, err := json.Marshal(req)
	if err != nil {
		errMsg = "参数解析异常"
		err = fmt.Errorf("参数解析异常,Err:" + err.Error())
		return
	}
	respItem, err := ChartDeleteLib(string(reqJson))
	if err != nil {
		errMsg = "撤回失败"
		err = fmt.Errorf("撤回失败,Err:" + err.Error())
		return
	}
	if respItem.Ret != 200 {
		errMsg = "撤回失败"
		err = fmt.Errorf(respItem.ErrMsg)
		return
	}

	// 更新社区返回的图表ID
	err = data_manage.SetForumChartInfoId(chartInfoId, 0)
	if err != nil {
		errMsg = "撤回失败"
		err = fmt.Errorf("更新图表ID失败,Err:" + err.Error())
		return
	}

	return
}

type AdminSaveReq struct {
	*system.Admin
	BusinessCode string `description:"商家编码"`
}

// 上传管理员信息
func AdminSave(adminId int) (err error) {
	if utils.BusinessCode == "" || (utils.BusinessCode != utils.BusinessCodeRelease && utils.BusinessCode != utils.BusinessCodeDebug && utils.BusinessCode != utils.BusinessCodeSandbox) {
		return
	}
	//查询用户信息
	adminInfo, err := system.GetSysAdminById(adminId)
	if err != nil {
		if err.Error() == utils.ErrNoRow() {
			err = fmt.Errorf("用户不存在")
			return
		}
		err = fmt.Errorf("获取用户信息失败,Err:" + err.Error())
		return
	}
	var req AdminSaveReq
	req.Admin = adminInfo
	req.BusinessCode = utils.BusinessCode
	reqJson, err := json.Marshal(req)
	if err != nil {
		err = fmt.Errorf("参数解析异常,Err:" + err.Error())
		return
	}
	respItem, err := AdminSaveLib(string(reqJson))
	if err != nil {
		err = fmt.Errorf("上传管理员信息失败,Err:" + err.Error())
		return
	}
	if respItem.Ret != 200 {
		err = fmt.Errorf("上传管理员信息失败,Err:%v,errMsg:%v", respItem.Msg, respItem.ErrMsg)
		return
	}
	return
}

type AdminDeleteReq struct {
	AdminName    string
	BusinessCode string `description:"商家编码"`
}

// 上传管理员信息
func AdminDelete(adminName string) (err error) {
	if utils.BusinessCode == "" || (utils.BusinessCode != utils.BusinessCodeRelease && utils.BusinessCode != utils.BusinessCodeDebug && utils.BusinessCode != utils.BusinessCodeSandbox) {
		return
	}
	var req AdminDeleteReq
	req.AdminName = adminName
	req.BusinessCode = utils.BusinessCode
	reqJson, err := json.Marshal(req)
	if err != nil {
		err = fmt.Errorf("参数解析异常,Err:" + err.Error())
		return
	}
	respItem, err := AdminDeleteLib(string(reqJson))
	if err != nil {
		err = fmt.Errorf("删除管理员信息失败,Err:" + err.Error())
		return
	}
	if respItem.Ret != 200 {
		err = fmt.Errorf("删除管理员信息失败,Err:%v,errMsg:%v", respItem.Msg, respItem.ErrMsg)
		return
	}
	return
}

type ChartThemeReq struct {
	*chart_theme.ChartTheme
	BusinessCode string `description:"商家编码"`
}

// 上传主题信息
func ChartThemeSave(theme *chart_theme.ChartTheme) (err error) {
	if utils.BusinessCode == "" || (utils.BusinessCode != utils.BusinessCodeRelease && utils.BusinessCode != utils.BusinessCodeDebug && utils.BusinessCode != utils.BusinessCodeSandbox) {
		return
	}
	var req ChartThemeReq
	req.ChartTheme = theme
	req.BusinessCode = utils.BusinessCode
	reqJson, err := json.Marshal(req)
	if err != nil {
		err = fmt.Errorf("参数解析异常,Err:" + err.Error())
		return
	}
	respItem, err := ChartThemeSaveLib(string(reqJson))
	if err != nil {
		err = fmt.Errorf("上传图表主题信息失败,Err:" + err.Error())
		return
	}
	if respItem.Ret != 200 {
		err = fmt.Errorf("上传图表主题信息失败,Err:%v,errMsg:%v", respItem.Msg, respItem.ErrMsg)
		return
	}
	return
}

// ChartThemeTypeSave  上传主题类型信息
func ChartThemeTypeSave(theme *chart_theme.ChartThemeType) (err error) {
	if utils.BusinessCode == "" || (utils.BusinessCode != utils.BusinessCodeRelease && utils.BusinessCode != utils.BusinessCodeDebug && utils.BusinessCode != utils.BusinessCodeSandbox) {
		return
	}
	//req.BusinessCode = utils.BusinessCode
	reqJson, err := json.Marshal(theme)
	if err != nil {
		err = fmt.Errorf("参数解析异常,Err:" + err.Error())
		return
	}
	respItem, err := ChartThemeTypeSaveLib(string(reqJson))
	if err != nil {
		err = fmt.Errorf("上传图表主题信息失败,Err:" + err.Error())
		return
	}
	if respItem.Ret != 200 {
		err = fmt.Errorf("上传图表主题信息失败,Err:%v,errMsg:%v", respItem.Msg, respItem.ErrMsg)
		return
	}
	return
}
