package services

import (
	"encoding/json"
	"eta/eta_index_lib/models"
	"eta/eta_index_lib/services/alarm_msg"
	"eta/eta_index_lib/utils"
	"fmt"
	"io/ioutil"
	netHttp "net/http"
	"strings"
	"time"
)

var (
	BridgeApiZhongJiIndexDataUrl   = "/api/index_data/zhongji/smm/data"   // 获取指标数据API
	BridgeApiZhongJiIndexListUrl   = "/api/index_data/zhongji/smm/list"   // 获取指标列表API
	BridgeApiZhongJiIndexLatestUrl = "/api/index_data/zhongji/smm/latest" // 获取指标最新数据API
)

// Data is a struct that represents the data field in the JSON string
type Data struct {
	Date   string `json:"date"`
	Value  string `json:"value"`
	Create string `json:"create"`
}

// Quota is a struct that represents the quota information in the JSON string
type Quota struct {
	QuotaID   string `json:"quota_id"`
	QuotaName string `json:"quota_name"`
	Unit      string `json:"unit"`
	Frequency string `json:"frequency"`
	ValueType string `json:"value_type"`
	Precision int    `json:"precision"`
	PermState int    `json:"perm_state"`
	Data      []Data `json:"data"`
}

// Response is a struct that represents the whole JSON string
type SmmResponse struct {
	Code  int     `json:"code"`
	Msg   string  `json:"msg"`
	Quota []Quota `json:"data"`
}

type SmmResp struct {
	Code int         `json:"code"`
	Msg  string      `json:"msg"`
	Data SmmResponse `json:"data"`
}

type GetSmmTokenResp struct {
	Code int          `json:"code"`
	Msg  string       `json:"msg"`
	Data SmmTokenData `json:"data"`
}

type SmmTokenData struct {
	Token string `json:"token"`
}

// GetSmmNewIndexFromBridge 从桥接服务获取指标
func GetSmmNewIndexFromBridge(edbCode string) (indexDataList []models.BaseFromSmmDataList, err error) {
	defer func() {
		if err != nil {
			tips := fmt.Sprintf("桥接服务-获取SMM指标失败, err: %s", err.Error())
			utils.FileLog.Info(tips)
			go alarm_msg.SendAlarmMsg(tips, 3)
		}
	}()

	url := fmt.Sprint(utils.EtaBridgeUrl, BridgeApiZhongJiIndexDataUrl)
	param := models.BridgeZhongJiIndexDataParams{EdbCode: edbCode}
	data, e := json.Marshal(param)
	if e != nil {
		err = fmt.Errorf("data json marshal err: %s", e.Error())
		return
	}
	body := ioutil.NopCloser(strings.NewReader(string(data)))
	client := &netHttp.Client{}
	req, e := netHttp.NewRequest("POST", url, body)
	if e != nil {
		err = fmt.Errorf("http create request err: %s", e.Error())
		return
	}

	checkToken := utils.MD5(utils.EtaBridgeAppNameEn + utils.EtaBridgeMd5Key)
	contentType := "application/json;charset=utf-8"
	req.Header.Set("Content-Type", contentType)
	req.Header.Set("Authorization", checkToken)
	resp, e := client.Do(req)
	if e != nil {
		err = fmt.Errorf("http client do err: %s", e.Error())
		return
	}
	defer func() {
		_ = resp.Body.Close()
	}()
	b, e := ioutil.ReadAll(resp.Body)
	if e != nil {
		err = fmt.Errorf("resp body read err: %s", e.Error())
		return
	}
	if len(b) == 0 {
		err = fmt.Errorf("resp body is empty")
		return
	}
	// 生产环境解密
	if utils.RunMode == "release" {
		str := string(b)
		str = strings.Trim(str, `"`)
		b = utils.DesBase64Decrypt([]byte(str), utils.EtaBridgeDesKey)
	}

	result := new(SmmResp)
	if e = json.Unmarshal(b, &result); e != nil {
		err = fmt.Errorf("result unmarshal err: %s\nresult: %s", e.Error(), string(b))
		return
	}
	if result.Code != 200 {
		err = fmt.Errorf("result: %s", string(b))
		return
	}

	dataList := make([]models.BaseFromSmmDataList, 0)
	for _, quota := range result.Data.Quota {
		var dataListItem models.BaseFromSmmDataList

		dataListItem.IndexCode = quota.QuotaID
		for _, v := range quota.Data {
			dataItem := new(models.BaseFromSmmData)
			dataItem.IndexCode = quota.QuotaID
			dataItem.DataTime = v.Date
			dataItem.Value = v.Value
			createTime, e := time.Parse(utils.FormatDateTime, v.Create)
			if e != nil {
				err = fmt.Errorf("time parse err: %s", e.Error())
				return
			}
			dataItem.CreateTime = createTime
			dataItem.ModifyTime = createTime
			currentDate, _ := time.ParseInLocation(utils.FormatDate, v.Date, time.Local)
			timestamp := currentDate.UnixNano() / 1e6
			dataItem.DataTimestamp = timestamp

			dataListItem.Data = append(dataListItem.Data, dataItem)
		}
		dataList = append(dataList, dataListItem)
	}
	indexDataList = dataList
	return
}

// GetSmmNewIndexListFromBridge 从桥接服务获取指标列表
func GetSmmNewIndexListFromBridge(params models.BridgeZhongJiIndexListParams) (indexList []*models.BaseFromSmmIndex, err error) {
	defer func() {
		if err != nil {
			tips := fmt.Sprintf("桥接服务-获取SMM指标失败, err: %s", err.Error())
			utils.FileLog.Info(tips)
			go alarm_msg.SendAlarmMsg(tips, 3)
		}
	}()

	url := fmt.Sprint(utils.EtaBridgeUrl, BridgeApiZhongJiIndexListUrl)

	data, e := json.Marshal(params)
	if e != nil {
		err = fmt.Errorf("data json marshal err: %s", e.Error())
		return
	}
	body := ioutil.NopCloser(strings.NewReader(string(data)))
	client := &netHttp.Client{}
	req, e := netHttp.NewRequest("POST", url, body)
	if e != nil {
		err = fmt.Errorf("http create request err: %s", e.Error())
		return
	}

	checkToken := utils.MD5(utils.EtaBridgeAppNameEn + utils.EtaBridgeMd5Key)
	contentType := "application/json;charset=utf-8"
	req.Header.Set("Content-Type", contentType)
	req.Header.Set("Authorization", checkToken)
	resp, e := client.Do(req)
	if e != nil {
		err = fmt.Errorf("http client do err: %s", e.Error())
		return
	}
	defer func() {
		_ = resp.Body.Close()
	}()
	b, e := ioutil.ReadAll(resp.Body)
	if e != nil {
		err = fmt.Errorf("resp body read err: %s", e.Error())
		return
	}
	if len(b) == 0 {
		err = fmt.Errorf("resp body is empty")
		return
	}
	// 生产环境解密
	if utils.RunMode == "release" {
		str := string(b)
		str = strings.Trim(str, `"`)
		b = utils.DesBase64Decrypt([]byte(str), utils.EtaBridgeDesKey)
	}

	result := new(models.SmmListResp)
	if e = json.Unmarshal(b, &result); e != nil {
		err = fmt.Errorf("result unmarshal err: %s\nresult: %s", e.Error(), string(b))
		return
	}
	if result.Code != 200 {
		err = fmt.Errorf("result: %s", string(b))
		return
	}

	for _, v := range result.Data.Data.Data {
		typeList := strings.Split(v.TypeAll, ";")
		item := new(models.BaseFromSmmIndex)
		item.IndexCode = v.QuotaID
		item.IndexName = v.QuotaName
		item.Frequency = v.Frequency
		item.StartDate = v.DataStart
		item.EndDate = v.DataEnd
		item.Name = v.TypeName
		item.CreateTime = time.Now()
		item.Unit = v.Unit
		item.Frequency = v.Frequency
		if v.Frequency != "半年" {
			item.Frequency += "度"
		}
		item.Interface = "SMM"
		item.ModifyTime = time.Now()
		item.DataState = v.DataState
		item.ReleaseTime = v.UpdateRule.ReleaseTime
		for i, typeItem := range typeList {
			if i == 0 {
				item.Type1 = typeItem
			} else if i == 1 {
				item.Type2 = typeItem
			} else if i == 2 {
				item.Type3 = typeItem
			}
		}
		indexList = append(indexList, item)
	}

	return
}

// GetSmmNewIndexListTotalFromBridge 从桥接服务获取指标列表总数
func GetSmmNewIndexListTotalFromBridge(params models.BridgeZhongJiIndexListParams) (total int, err error) {
	defer func() {
		if err != nil {
			tips := fmt.Sprintf("桥接服务-获取SMM指标失败, err: %s", err.Error())
			utils.FileLog.Info(tips)
			go alarm_msg.SendAlarmMsg(tips, 3)
		}
	}()

	url := fmt.Sprint(utils.EtaBridgeUrl, BridgeApiZhongJiIndexListUrl)

	data, e := json.Marshal(params)
	if e != nil {
		err = fmt.Errorf("data json marshal err: %s", e.Error())
		return
	}
	body := ioutil.NopCloser(strings.NewReader(string(data)))
	client := &netHttp.Client{}
	req, e := netHttp.NewRequest("POST", url, body)
	if e != nil {
		err = fmt.Errorf("http create request err: %s", e.Error())
		return
	}

	checkToken := utils.MD5(utils.EtaBridgeAppNameEn + utils.EtaBridgeMd5Key)
	contentType := "application/json;charset=utf-8"
	req.Header.Set("Content-Type", contentType)
	req.Header.Set("Authorization", checkToken)
	resp, e := client.Do(req)
	if e != nil {
		err = fmt.Errorf("http client do err: %s", e.Error())
		return
	}
	defer func() {
		_ = resp.Body.Close()
	}()
	b, e := ioutil.ReadAll(resp.Body)
	if e != nil {
		err = fmt.Errorf("resp body read err: %s", e.Error())
		return
	}
	if len(b) == 0 {
		err = fmt.Errorf("resp body is empty")
		return
	}
	// 生产环境解密
	if utils.RunMode == "release" {
		str := string(b)
		str = strings.Trim(str, `"`)
		b = utils.DesBase64Decrypt([]byte(str), utils.EtaBridgeDesKey)
	}

	result := new(models.SmmListResp)
	if e = json.Unmarshal(b, &result); e != nil {
		err = fmt.Errorf("result unmarshal err: %s\nresult: %s", e.Error(), string(b))
		return
	}
	if result.Code != 200 {
		err = fmt.Errorf("result: %s", string(b))
		return
	}

	total = result.Data.Data.Total
	return
}

// GetSmmIndexLatestFromBridge 从桥接服务获取指标更新
func GetSmmIndexLatestFromBridge(edbInfoId int, edbCode, startDate string) (err error) {
	defer func() {
		if err != nil {
			tips := fmt.Sprintf("桥接服务-获取SMM指标失败, err: %s", err.Error())
			utils.FileLog.Info(tips)
			go alarm_msg.SendAlarmMsg(tips, 3)
		}
	}()

	url := fmt.Sprint(utils.EtaBridgeUrl, BridgeApiZhongJiIndexLatestUrl)

	startDateTime, err := time.Parse(utils.FormatDate, startDate)
	if err != nil {
		err = fmt.Errorf("startDateTime parse err: %s", err.Error())
		return
	}
	timeStamp := startDateTime.Unix()

	param := models.BridgeZhongJiIndexLatestDataParams{
		EdbCode:  edbCode,
		LastTime: timeStamp,
	}
	data, e := json.Marshal(param)
	if e != nil {
		err = fmt.Errorf("data json marshal err: %s", e.Error())
		return
	}
	body := ioutil.NopCloser(strings.NewReader(string(data)))
	client := &netHttp.Client{}
	req, e := netHttp.NewRequest("POST", url, body)
	if e != nil {
		err = fmt.Errorf("http create request err: %s", e.Error())
		return
	}

	checkToken := utils.MD5(utils.EtaBridgeAppNameEn + utils.EtaBridgeMd5Key)
	contentType := "application/json;charset=utf-8"
	req.Header.Set("Content-Type", contentType)
	req.Header.Set("Authorization", checkToken)
	resp, e := client.Do(req)
	if e != nil {
		err = fmt.Errorf("http client do err: %s", e.Error())
		return
	}
	defer func() {
		_ = resp.Body.Close()
	}()
	b, e := ioutil.ReadAll(resp.Body)
	if e != nil {
		err = fmt.Errorf("resp body read err: %s", e.Error())
		return
	}
	if len(b) == 0 {
		err = fmt.Errorf("resp body is empty")
		return
	}
	// 生产环境解密
	if utils.RunMode == "release" {
		str := string(b)
		str = strings.Trim(str, `"`)
		b = utils.DesBase64Decrypt([]byte(str), utils.EtaBridgeDesKey)
	}

	result := new(models.SmmLatestDataResponse)
	if e = json.Unmarshal(b, &result); e != nil {
		err = fmt.Errorf("result unmarshal err: %s\nresult: %s", e.Error(), string(b))
		return
	}
	if result.Code != 200 {
		err = fmt.Errorf("result: %s", string(b))
		return
	}
	smmDataList := make([]*models.BaseFromSmmData, 0)

	for _, v := range result.Data.Data.DataList {
		item := new(models.BaseFromSmmData)
		item.BaseFromSmmIndexId = edbInfoId
		item.IndexCode = v.QuotaID
		item.DataTime = v.Date
		item.Value = v.Value
		item.CreateTime = time.Now()
		item.ModifyTime = time.Now()

		timeDate, _ := time.Parse(utils.FormatDateTime, v.Date)
		timestamp := timeDate.UnixNano() / 1e6
		item.DataTimestamp = timestamp

		smmDataList = append(smmDataList, item)
	}

	err = models.RefreshEdbDataFromSmmToEdb(edbInfoId, edbCode, startDate, smmDataList)
	return
}
