package service

import (
	"encoding/json"
	"fmt"
	"git.quantgroup.cn/DevOps/enoch/service/data"
	"git.quantgroup.cn/DevOps/enoch/service/log"
	"github.com/gomodule/redigo/redis"
	"github.com/influxdata/influxdb/client/v2"
	"log"
	"time"
)

type BraveMessageHandler struct {
}

var httpMethod = map[string]string{
	"get": "", "GET": "", "post": "", "options": "", "put": "", "delete": "", "head": "",
}

func (BraveMessageHandler) MsgProcess(msg string) {

	traceMsg := make([]TraceMsg, 3) //[]TraceMsg{}
	err := json.Unmarshal([]byte(msg), &traceMsg)
	if err != nil {
		fmt.Println(err)
	}

	//msgRedisProcess(traceMsg)
	msgInfluxProcess(traceMsg)
}

var batchSize = 5000
var pointSlice = make([]*client.Point, 0, batchSize)

func msgInfluxProcess(traceMsgs []TraceMsg) {

	for _, traceMsg := range traceMsgs {

		if traceMsg.Kind != "SERVER" {
			continue
		}
		path := traceMsg.Name

		if _, ok := httpMethod[path]; ok {
			path = traceMsg.Tags.HttpMethod + " " + traceMsg.Tags.HttpPath
		}

		sysName := traceMsg.LocalEndpoint.ServiceName

		fields := make(map[string]interface{})
		fields["duration"] = traceMsg.Duration / 1000
		fields["traceId"] = traceMsg.TraceId
		bytes, err := json.Marshal(traceMsg)

		msg := string(bytes)

		fields["msg"] = msg

		tags := make(map[string]string)
		tags["sys_name"] = sysName
		tags["path"] = path
		tags["host"] = traceMsg.LocalEndpoint.Ipv4

		if err != nil {
			log.Fatal(err)
		}

		unix := time.Unix(0, traceMsg.Timestamp*1000)
		if len(pointSlice) == batchSize {
			go batchWrite(pointSlice)
			pointSlice = make([]*client.Point, 0, batchSize)
		}

		point, _ := client.NewPoint("trace_info", tags, fields, unix)
		pointSlice = append(pointSlice, point)

		if err != nil {
			log.Fatal(err, msg)
		}
	}

}

func batchWrite(pointArray []*client.Point) {
	c := data.NewClient()
	defer func() { _ = c.Close() }()

	points, err := client.NewBatchPoints(client.BatchPointsConfig{
		Database: "monitor",
		//Precision : "ms",
	})
	if err != nil {
		log.Fatal(err)
	}

	points.AddPoints(pointArray)
	err = c.Write(points)
	logger.Info.Println("写入数据", len(pointArray))
	if err != nil {
		logger.Error.Fatal(err)
	}
}

func Duration(day string, fun func(sysName string, durations map[string]string)) {

	conn := data.Pool.Get()
	defer func() { _ = conn.Close() }()
	matchPattern := "duration*" + day
	reply, err := redis.Values(conn.Do("scan", 0, "match", matchPattern, "count", 10000))
	if err != nil {
		fmt.Print("Scan 扫描key出错", err)
	}

	redisKeys := reply[1].([]interface{})
	for _, redisKey := range redisKeys {

		reply2, err := redis.StringMap(conn.Do("zrevrangebyscore", redisKey, "+inf", 200000, "withscores"))
		if err != nil {
			fmt.Print("获取出错了", err)
		}
		fun(string(redisKey.([]uint8)), reply2)
	}

}

func Counter(day string, fun func(sysName string, durations map[string]string)) {
	conn := data.Pool.Get()
	defer func() { _ = conn.Close() }()
	matchPattern := "counter*" + day
	reply, err := redis.Values(conn.Do("scan", 0, "match", matchPattern, "count", 10000))
	if err != nil {
		fmt.Print("Scan 扫描key出错", err)
	}
	redisKeys := reply[1].([]interface{})
	for _, redisKey := range redisKeys {

		reply2, err := redis.StringMap(conn.Do("zrevrange", redisKey, 0, 300, "withscores"))
		if err != nil {
			fmt.Print("获取出错了", err)
		}
		fun(string(redisKey.([]uint8)), reply2)
	}

}
