package data_manage

import (
	"encoding/json"
	"eta/eta_api/controllers"
	"eta/eta_api/models"
	"eta/eta_api/models/data_manage"
	"eta/eta_api/models/system"
	"eta/eta_api/services/data"
	etaTrialService "eta/eta_api/services/eta_trial"
	"eta/eta_api/utils"
	"fmt"
	"github.com/rdlucklib/rdluck_tools/paging"
	"strconv"
	"strings"
	"time"
)

// BloombergDataController 彭博数据源
type BloombergDataController struct {
	controllers.BaseAuthController
}

// List
// @Title 指标列表
// @Description 指标列表
// @Param   PageSize  query  int  false  "每页数据量"
// @Param   CurrentIndex  query  int  false  "页码"
// @Param   Frequency  query  string  false  "频度"
// @Param   Keywords  query  string  false  "指标ID/指标名称"
// @Param   ListAll  query  bool  false  "列表全选"
// @Param   SortField  query  int  false  "排序字段: 0-默认; 1-开始时间; 2-最新时间; 3-更新时间"
// @Param   SortRule  query  int  false  "排序方式: 0-默认; 1-正序; 2-倒序"
// @Success 200 {object} data_manage.BloombergSourceListResp
// @router /bloomberg_source/list [get]
func (this *BloombergDataController) List() {
	br := new(models.BaseResponse).Init()
	defer func() {
		if br.ErrMsg == "" {
			br.IsSendEmail = false
		}
		this.Data["json"] = br
		this.ServeJSON()
	}()
	sysUser := this.SysUser
	if sysUser == nil {
		br.Msg = "请登录"
		br.ErrMsg = "请登录,SysUser Is Empty"
		br.Ret = 408
		return
	}
	params := new(data_manage.BloombergSourceListReq)
	if e := this.ParseForm(params); e != nil {
		br.Msg = "获取失败"
		br.ErrMsg = "参数解析失败, Err: " + e.Error()
		return
	}

	cond := ``
	pars := make([]interface{}, 0)
	// 筛选项
	{
		params.Keywords = strings.TrimSpace(params.Keywords)
		if params.Keywords != "" {
			cond += fmt.Sprintf(` AND (%s LIKE ? OR %s LIKE ?)`, data_manage.BaseFromBloombergIndexCols.IndexCode, data_manage.BaseFromBloombergIndexCols.IndexName)
			kw := fmt.Sprint("%", params.Keywords, "%")
			pars = append(pars, kw, kw)
		}
		if params.Frequency != "" {
			cond += fmt.Sprintf(` AND %s = ?`, data_manage.BaseFromBloombergIndexCols.Frequency)
			pars = append(pars, params.Frequency)
		}
	}

	// 分页列表
	bloombergOb := new(data_manage.BaseFromBloombergIndex)
	total, e := bloombergOb.GetCountByCondition(cond, pars)
	if e != nil {
		br.Msg = "获取失败"
		br.ErrMsg = "获取Bloomberg原始指标列表总数失败, Err: " + e.Error()
		return
	}
	var startSize int
	if params.PageSize <= 0 {
		params.PageSize = utils.PageSize20
	}
	if params.CurrentIndex <= 0 {
		params.CurrentIndex = 1
	}
	startSize = utils.StartIndex(params.CurrentIndex, params.PageSize)

	// 排序, 默认创建时间倒序
	orderFields := map[int]string{
		0: data_manage.BaseFromBloombergIndexCols.CreateTime, 1: data_manage.BaseFromBloombergIndexCols.StartDate,
		2: data_manage.BaseFromBloombergIndexCols.EndDate, 3: data_manage.BaseFromBloombergIndexCols.ModifyTime,
	}
	orderType := map[int]string{0: "DESC", 1: "ASC", 2: "DESC"}
	orderRule := fmt.Sprintf("%s %s", orderFields[params.SortField], orderType[params.SortRule])

	// 列表
	edbList := make([]*data_manage.BaseFromBloombergIndex, 0)
	if params.ListAll {
		list, e := bloombergOb.GetItemsByCondition(cond, pars, []string{}, orderRule, 0)
		if e != nil {
			br.Msg = "获取失败"
			br.ErrMsg = "获取Bloomberg原始指标列表失败, Err: " + e.Error()
			return
		}
		edbList = list
	} else {
		list, e := bloombergOb.GetPageItemsByCondition(cond, pars, []string{}, orderRule, startSize, params.PageSize)
		if e != nil {
			br.Msg = "获取失败"
			br.ErrMsg = "获取Bloomberg原始指标分页列表失败, Err: " + e.Error()
			return
		}
		edbList = list
	}

	// 获取指标库已有指标
	existsEdb, e := data_manage.GetEdbCodesBySource(utils.DATA_SOURCE_BLOOMBERG)
	if e != nil {
		br.Msg = "获取失败"
		br.ErrMsg = "获取Bloomberg已添加的指标失败, Err: " + e.Error()
		return
	}
	existMap := make(map[string]*data_manage.EdbInfo)
	for _, v := range existsEdb {
		existMap[v.EdbCode] = v
	}

	respList := make([]*data_manage.BaseFromBloombergIndexItem, 0)
	for _, v := range edbList {
		t := data_manage.FormatBaseFromBloombergIndex2Item(v)
		ed := existMap[v.IndexCode]
		if ed != nil {
			t.EdbExist = 1
			t.EdbInfoId = ed.EdbInfoId
			t.EdbUniqueCode = ed.UniqueCode
			t.EdbClassifyId = ed.ClassifyId
		}
		respList = append(respList, t)
	}
	page := paging.GetPaging(params.CurrentIndex, params.PageSize, total)
	dataResp := new(data_manage.BloombergSourceListResp)
	dataResp.Paging = page
	dataResp.List = respList

	br.Data = dataResp
	br.Ret = 200
	br.Success = true
	br.Msg = "获取成功"
}

// BatchAdd
// @Title 批量新增
// @Description 批量新增
// @Param	request	body data_manage.AddEdbInfoReq true "type json string"
// @Success 200 string "操作成功"
// @router /bloomberg_source/batch_add [post]
func (this *BloombergDataController) BatchAdd() {
	br := new(models.BaseResponse).Init()
	defer func() {
		if br.ErrMsg == "" {
			br.IsSendEmail = false
		}
		this.Data["json"] = br
		this.ServeJSON()
	}()
	sysUser := this.SysUser
	if sysUser == nil {
		br.Msg = "请登录"
		br.ErrMsg = "请登录,SysUser Is Empty"
		br.Ret = 408
		return
	}

	deleteCache := true
	cacheKey := "CACHE_EDB_INFO_BATCH_ADD_BLOOMBERG_" + strconv.Itoa(sysUser.AdminId)
	defer func() {
		if deleteCache {
			_ = utils.Rc.Delete(cacheKey)
		}
	}()
	if !utils.Rc.SetNX(cacheKey, 1, 30*time.Second) {
		deleteCache = false
		br.Msg = "系统处理中,请稍后重试!"
		br.ErrMsg = "系统处理中,请稍后重试!" + sysUser.RealName + ";data:" + string(this.Ctx.Input.RequestBody)
		return
	}
	var req []*data_manage.AddEdbInfoReq
	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
		br.Msg = "参数解析异常!"
		br.ErrMsg = "参数解析失败,Err:" + e.Error()
		return
	}
	if len(req) == 0 {
		br.Msg = "请选择指标"
		return
	}
	if len(req) > 30 {
		br.Msg = "批量添加指标数量不得超过30个"
		return
	}
	indexNames := make([]string, 0)
	for _, v := range req {
		v.EdbCode = strings.TrimSpace(v.EdbCode)
		if v.EdbCode == "" {
			br.Msg = "指标ID不可为空"
			return
		}
		v.EdbName = strings.TrimSpace(v.EdbName)
		if v.EdbName == "" {
			br.Msg = "请输入指标名称"
			return
		}
		indexNames = append(indexNames, v.EdbName)
		v.Frequency = strings.TrimSpace(v.Frequency)
		if v.Frequency == "" {
			br.Msg = "请选择频度"
			return
		}
		v.Unit = strings.TrimSpace(v.Unit)
		if v.Unit == "" {
			br.Msg = "请输入单位"
			return
		}
		if v.ClassifyId <= 0 {
			br.Msg = "请选择分类"
			return
		}
	}

	// 限定同一时间最多批量新增30个指标
	for _, v := range req {
		var r data.BloombergIndexSource2EdbReq
		r.EdbCode = v.EdbCode
		r.EdbName = v.EdbName
		r.Frequency = v.Frequency
		r.Unit = v.Unit
		r.ClassifyId = v.ClassifyId
		r.AdminId = sysUser.AdminId
		r.AdminRealName = sysUser.RealName

		edbInfo, e, errMsg, skip := data.BloombergIndexSource2Edb(r, this.Lang)
		if e != nil {
			br.Msg = "操作失败"
			if errMsg != "" {
				br.Msg = errMsg
			}
			br.ErrMsg = e.Error()
			return
		}
		if skip {
			continue
		}

		// 试用平台更新用户累计新增指标数
		if utils.BusinessCode == utils.BusinessCodeSandbox {
			go func() {
				adminItem, e := system.GetSysAdminById(sysUser.AdminId)
				if e != nil {
					tips := fmt.Sprintf("试用平台更新用户累计新增指标数-获取用户失败, Err: " + e.Error())
					utils.FileLog.Info(tips)
					return
				}
				if adminItem.DepartmentName != "ETA试用客户" {
					return
				}
				var ur etaTrialService.EtaTrialUserReq
				ur.Mobile = adminItem.Mobile
				_, _ = etaTrialService.UpdateUserIndexNum(ur)
			}()
		}

		// 新增操作日志
		{
			edbLog := new(data_manage.EdbInfoLog)
			edbLog.EdbInfoId = edbInfo.EdbInfoId
			edbLog.SourceName = edbInfo.SourceName
			edbLog.Source = edbInfo.Source
			edbLog.EdbCode = edbInfo.EdbCode
			edbLog.EdbName = edbInfo.EdbName
			edbLog.ClassifyId = edbInfo.ClassifyId
			edbLog.SysUserId = sysUser.AdminId
			edbLog.SysUserRealName = sysUser.RealName
			edbLog.CreateTime = time.Now()
			edbLog.Content = string(this.Ctx.Input.RequestBody)
			edbLog.Status = "新增指标"
			edbLog.Method = this.Ctx.Input.URI()
			go data_manage.AddEdbInfoLog(edbLog)
		}
	}

	br.Msg = "操作成功"
	br.Ret = 200
	br.Success = true
	br.IsAddLog = true
}

// NameCheck
// @Title 重名校验
// @Description 批量新增
// @Param	request	body data_manage.AddEdbInfoReq true "type json string"
// @Success 200 string "操作成功"
// @router /bloomberg_source/name_check [post]
func (this *BloombergDataController) NameCheck() {
	br := new(models.BaseResponse).Init()
	defer func() {
		if br.ErrMsg == "" {
			br.IsSendEmail = false
		}
		this.Data["json"] = br
		this.ServeJSON()
	}()
	sysUser := this.SysUser
	if sysUser == nil {
		br.Msg = "请登录"
		br.ErrMsg = "请登录,SysUser Is Empty"
		br.Ret = 408
		return
	}
	var req []*data_manage.AddEdbInfoReq
	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
		br.Msg = "参数解析异常!"
		br.ErrMsg = "参数解析失败,Err:" + e.Error()
		return
	}
	if len(req) == 0 {
		br.Msg = "请选择指标"
		return
	}

	type NameCheckResult struct {
		EdbCode string
		EdbName string
		Exist   bool
	}
	indexNames := make([]string, 0)
	resp := make([]*NameCheckResult, 0)
	for _, v := range req {
		v.EdbCode = strings.TrimSpace(v.EdbCode)
		if v.EdbCode == "" {
			br.Msg = "指标ID不可为空"
			return
		}
		v.EdbName = strings.TrimSpace(v.EdbName)
		if v.EdbName == "" {
			br.Msg = "请输入指标名称"
			return
		}
		indexNames = append(indexNames, v.EdbName)
		resp = append(resp, &NameCheckResult{
			EdbCode: v.EdbCode,
			EdbName: v.EdbName,
		})
	}

	// 重名校验
	edbList, e := data_manage.GetEdbInfoByNameArr(indexNames, utils.EDB_INFO_TYPE)
	if e != nil {
		br.Msg = "操作失败"
		br.ErrMsg = "获取重名指标失败, Err: " + e.Error()
		return
	}
	nameExists := make(map[string]bool)
	for _, v := range edbList {
		nameExists[v.EdbName] = true
	}
	if len(nameExists) > 0 {
		for _, v := range resp {
			v.Exist = nameExists[v.EdbName]
		}
	}

	br.Data = resp
	br.Msg = "操作成功"
	br.Ret = 200
	br.Success = true
}

// AddCheck
// @Title 新增校验
// @Description 新增校验
// @Param	request	body data_manage.BloombergSourceBatchAddCheckReq true "type json string"
// @Success 200 string "操作成功"
// @router /bloomberg_source/add_check [post]
func (this *BloombergDataController) AddCheck() {
	br := new(models.BaseResponse).Init()
	defer func() {
		if br.ErrMsg == "" {
			br.IsSendEmail = false
		}
		this.Data["json"] = br
		this.ServeJSON()
	}()
	sysUser := this.SysUser
	if sysUser == nil {
		br.Msg = "请登录"
		br.ErrMsg = "请登录,SysUser Is Empty"
		br.Ret = 408
		return
	}
	var req *data_manage.BloombergSourceBatchAddCheckReq
	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
		br.Msg = "参数解析异常!"
		br.ErrMsg = "参数解析失败,Err:" + e.Error()
		return
	}
	codeMax := 30
	codeLen := len(req.IndexCodes)

	// 排序, 默认创建时间倒序
	orderFields := map[int]string{
		0: data_manage.BaseFromBloombergIndexCols.CreateTime, 1: data_manage.BaseFromBloombergIndexCols.StartDate,
		2: data_manage.BaseFromBloombergIndexCols.EndDate, 3: data_manage.BaseFromBloombergIndexCols.ModifyTime,
	}
	orderType := map[int]string{0: "DESC", 1: "ASC", 2: "DESC"}
	orderRule := fmt.Sprintf("%s %s", orderFields[req.SortField], orderType[req.SortRule])

	// 获取指标库已有指标
	existsEdb, e := data_manage.GetEdbCodesBySource(utils.DATA_SOURCE_BLOOMBERG)
	if e != nil {
		br.Msg = "获取失败"
		br.ErrMsg = "获取Bloomberg已添加的指标失败, Err: " + e.Error()
		return
	}
	existMap := make(map[string]*data_manage.EdbInfo)
	for _, v := range existsEdb {
		existMap[v.EdbCode] = v
	}

	// 非全选-不需要频率等筛选条件
	bloombergOb := new(data_manage.BaseFromBloombergIndex)
	if !req.ListAll {
		if codeLen == 0 {
			br.Msg = "请选择指标"
			return
		}
		if codeLen > codeMax {
			br.Msg = fmt.Sprintf("最多只能选择%d个指标", codeMax)
			return
		}

		// 查询选中的指标
		cond := fmt.Sprintf(` AND %s IN (%s)`, data_manage.BaseFromBloombergIndexCols.IndexCode, utils.GetOrmInReplace(codeLen))
		pars := make([]interface{}, 0)
		pars = append(pars, req.IndexCodes)
		list, e := bloombergOb.GetItemsByCondition(cond, pars, []string{}, orderRule, 0)
		if e != nil {
			br.Msg = "获取失败"
			br.ErrMsg = "获取Bloomberg原始指标列表失败, Err: " + e.Error()
			return
		}
		resp := make([]*data_manage.BaseFromBloombergIndexItem, 0)
		for _, v := range list {
			t := data_manage.FormatBaseFromBloombergIndex2Item(v)
			ed := existMap[v.IndexCode]
			if ed != nil {
				t.EdbExist = 1
				t.EdbInfoId = ed.EdbInfoId
				t.EdbUniqueCode = ed.UniqueCode
				t.EdbClassifyId = ed.ClassifyId
			}
			resp = append(resp, t)
		}

		br.Data = resp
		br.Msg = "校验成功"
		br.Ret = 200
		br.Success = true
		return
	}

	// 全选-需要频率等筛选条件
	cond := ``
	pars := make([]interface{}, 0)
	// 筛选项
	req.Keywords = strings.TrimSpace(req.Keywords)
	if req.Keywords != "" {
		cond += fmt.Sprintf(` AND (%s LIKE ? OR %s LIKE ?)`, data_manage.BaseFromBloombergIndexCols.IndexCode, data_manage.BaseFromBloombergIndexCols.IndexName)
		kw := fmt.Sprint("%", req.Keywords, "%")
		pars = append(pars, kw, kw)
	}
	if req.Frequency != "" {
		cond += fmt.Sprintf(` AND %s = ?`, data_manage.BaseFromBloombergIndexCols.Frequency)
		pars = append(pars, req.Frequency)
	}
	// 排除对应指标
	if codeLen > 0 {
		cond += fmt.Sprintf(` AND %s NOT IN (%s)`, data_manage.BaseFromBloombergIndexCols.IndexCode, utils.GetOrmInReplace(codeLen))
		pars = append(pars, req.IndexCodes)
	}
	// 查询max+1个指标
	list, e := bloombergOb.GetItemsByCondition(cond, pars, []string{}, orderRule, codeMax+1)
	if e != nil {
		br.Msg = "获取失败"
		br.ErrMsg = "获取Bloomberg原始指标列表失败, Err: " + e.Error()
		return
	}
	if len(list) > codeMax {
		br.Msg = fmt.Sprintf("最多只能选择%d个指标", codeMax)
		return
	}

	resp := make([]*data_manage.BaseFromBloombergIndexItem, 0)
	for _, v := range list {
		t := data_manage.FormatBaseFromBloombergIndex2Item(v)
		ed := existMap[v.IndexCode]
		if ed != nil {
			t.EdbExist = 1
			t.EdbInfoId = ed.EdbInfoId
			t.EdbUniqueCode = ed.UniqueCode
			t.EdbClassifyId = ed.ClassifyId
		}
		resp = append(resp, t)
	}

	br.Data = resp
	br.Msg = "校验成功"
	br.Ret = 200
	br.Success = true
}