package a_status

import (
	"encoding/json"
	"fmt"
	"strings"
	"time"
	"wdd.io/agent-common/logger"
	"wdd.io/agent-common/utils"
	"wdd.io/agent-go/g"
	"wdd.io/agent-go/rabbitmq"
)

var log = logger.Log
var pool = g.G.P

type StatusMessage struct {
	/**
	    * which kind of status should be return
	  	 "PING";
	     * METRIC => short time message
	     * ALL => all agent status message
	    * */
	StatusType        string `json:"statusType,omitempty"`
	MetricRepeatCount int    `json:"metricRepeatCount,omitempty"`
	metricRepeatPinch int    `json:"metricRepeatPinch,omitempty"`
}

type AgentMetric struct {
	CPUMetric     *CPUMetric
	MemoryMetric  *MemoryMetric
	NetworkMetric []NetworkMetric
	DiskMetric    []DiskInfo
	DockerMetric  *DockerMetric
}

type AgentInfo struct {
	CPUInfo     *CPUInfo
	MemoryInfo  *MemoryInfo
	NetworkInfo []NetworkInfo
	DiskInfo    []DiskInfo
	HostInfo    *HostInfo
	DockerInfo  *DockerMetric
}

func Activate() {
	log.Info("Module [ STATUS ] activated !")

	// 死循环获取channel中的数据
	for {
		if octopusMessage, ok := <-rabbitmq.BusinessRuntimeQueue.ReceiveChan.StatusRChan; ok {
			// 处理数据

			statusMsgString := octopusMessage.Content.(string)

			var statusMessage *StatusMessage
			err := json.Unmarshal([]byte(statusMsgString), &statusMessage)
			if err != nil {
				fmt.Println(err.Error())
				log.Error(fmt.Sprintf("status message convert to json is wrong! msg is => %s", octopusMessage))
				return
			}

			// OMessageStatusTypeEnum
			var statusRes string
			if strings.HasPrefix(statusMessage.StatusType, "PING") {
				// ping info
				statusRes = Ping()
			} else if strings.HasPrefix(statusMessage.StatusType, "METRIC") {
				// metric info
				agentStatusString, _ := json.Marshal(ReportAgentMetric())
				statusRes = string(agentStatusString)
			} else if strings.HasPrefix(statusMessage.StatusType, "INFO") {
				log.InfoF("[statusOMHandler] - call for agent info !")
			} else {
				log.WarnF("[statusOMHandler] - error octopus status message type of %s", statusMessage.StatusType)
			}

			// 返回消息
			// 组装消息
			octopusMessage.ACTime = utils.ParseDateTimeTime()
			octopusMessage.Result = statusRes
			// 发送回去
			octopusMessage.SendToOctopusServer()

			// 输出日志
			log.InfoF("接收到查询Agent状态的请求，结果为 => %s", statusRes)
		} else {
			// channel已关闭，跳出循环
			log.ErrorF("business queue [ STATUS ] receive chan has closed !")
			break
		}

		time.Sleep(time.Second * 20)
	}

}

func Ping() string {
	return "PONG"
}

func ReportAgentMetric() *AgentMetric {

	lenOfAgentMetric := 5
	waitResultChan := make(chan string, lenOfAgentMetric)
	timeout := time.After(5 * time.Second)
	var err error

	var cpuMetric *CPUMetric
	err = pool.Submit(func() {
		cpuMetric, err = GetCPUMetric()
		if err != nil {
			log.ErrorF("获取Agent的状态出现错误！ 请检查 => %v", err)
			waitResultChan <- "GetCPUMetric error !"
			return
		}
		waitResultChan <- "GetCPUMetric success !"
	})
	if err != nil {
		log.ErrorF("[ReportAgentMetric] - GetCPUMetric exec error  => %v", err)
	}

	var memoryMetric *MemoryMetric
	err = pool.Submit(func() {
		memoryMetric, err = GetMemoryMetric()
		if err != nil {
			log.ErrorF("获取Agent的状态出现错误！ 请检查 => %v", err)
			waitResultChan <- "GetMemoryMetric error !"
			return
		}
		waitResultChan <- "GetMemoryMetric success !"
	})
	if err != nil {
		log.ErrorF("[ReportAgentMetric] - GetMemoryMetric exec error  => %v", err)
	}

	var diskInfoList []DiskInfo
	err = pool.Submit(func() {
		diskInfoList, err = GetDiskInfo()
		if err != nil {
			log.ErrorF("获取Agent的状态出现错误！ 请检查 => %v", err)
			waitResultChan <- "GetDiskInfo error !"
			return
		}
		waitResultChan <- "GetDiskInfo success !"
	})
	if err != nil {
		log.ErrorF("[ReportAgentMetric] - GetDiskInfo exec error  => %v", err)
	}

	var networkMetric []NetworkMetric
	err = pool.Submit(func() {
		networkMetric, err = GetNetworkMetric()
		if err != nil {
			log.ErrorF("获取Agent的状态出现错误！ 请检查 => %v", err)
			waitResultChan <- "GetNetworkMetric error !"
			return
		}
		waitResultChan <- "GetNetworkMetric success !"
	})
	if err != nil {
		log.ErrorF("[ReportAgentMetric] - GetNetworkMetric exec error  => %v", err)
	}
	var dockerMetric *DockerMetric
	err = pool.Submit(func() {
		dockerMetric, err = GetDockerMetric()
		if err != nil {
			log.ErrorF("获取Agent的状态出现错误！ 请检查 => %v", err)
			waitResultChan <- "GetDockerMetric error !"
			return
		}
		waitResultChan <- "GetDockerMetric success !"
	})
	if err != nil {
		log.ErrorF("[ReportAgentMetric] - GetDockerMetric exec error  => %v", err)
	}

	for i := 0; i < lenOfAgentMetric; i++ {
		select {
		case result := <-waitResultChan:
			log.DebugF("[ReportAgentMetric] - metric received => %s", result)
		case <-timeout:
			fmt.Println("[ReportAgentMetric] - Timeout! Not all results received.")
			break
		}
	}

	return &AgentMetric{
		CPUMetric:     cpuMetric,
		MemoryMetric:  memoryMetric,
		NetworkMetric: networkMetric,
		DiskMetric:    diskInfoList,
		DockerMetric:  dockerMetric,
	}

}

func ReportAgentInfo() *AgentInfo {

	lenOfAgentMetric := 6
	waitResultChan := make(chan string, lenOfAgentMetric)
	timeout := time.After(5 * time.Second)
	var err error

	var cpuInfo *CPUInfo
	err = pool.Submit(func() {
		cpuInfo, err = GetCPUInfo()
		if err != nil {
			log.ErrorF("获取Agent的状态出现错误！ 请检查 => %v", err)
			waitResultChan <- "GetCPUInfo error !"
			return
		}
		waitResultChan <- "GetCPUInfo success !"
	})
	if err != nil {
		log.ErrorF("[ReportAgentInfo] - GetCPUInfo exec error  => %v", err)
	}

	var memoryInfo *MemoryInfo
	err = pool.Submit(func() {
		memoryInfo, err = GetMemoryInfo()
		if err != nil {
			log.ErrorF("获取Agent的状态出现错误！ 请检查 => %v", err)
			waitResultChan <- "GetMemoryInfo error !"
			return
		}
		waitResultChan <- "GetMemoryInfo success !"
	})
	if err != nil {
		log.ErrorF("[ReportAgentInfo] - GetMemoryInfo exec error  => %v", err)
	}

	var diskInfoList []DiskInfo
	err = pool.Submit(func() {
		diskInfoList, err = GetDiskInfo()
		if err != nil {
			log.ErrorF("获取Agent的状态出现错误！ 请检查 => %v", err)
			waitResultChan <- "GetDiskInfo error !"
			return
		}
		waitResultChan <- "GetDiskInfo success !"
	})
	if err != nil {
		log.ErrorF("[ReportAgentInfo] - GetDiskInfo exec error  => %v", err)
	}

	var hostInfo *HostInfo
	err = pool.Submit(func() {
		hostInfo, err = GetHostInfo()
		if err != nil {
			log.ErrorF("获取Agent的状态出现错误！ 请检查 => %v", err)
			waitResultChan <- "GetHostInfo error !"
			return
		}
		waitResultChan <- "hostInfo success !"
	})
	if err != nil {
		log.ErrorF("[ReportAgentInfo] - hostInfo exec error  => %v", err)
	}

	var networkInfo []NetworkInfo
	err = pool.Submit(func() {
		networkInfo, err = GetNetworkInfo()
		if err != nil {
			log.ErrorF("获取Agent的状态出现错误！ 请检查 => %v", err)
			waitResultChan <- "GetNetworkInfo error !"
			return
		}
		waitResultChan <- "GetNetworkInfo success !"
	})
	if err != nil {
		log.ErrorF("[ReportAgentInfo] - GetNetworkInfo exec error  => %v", err)
	}

	var dockerMetric *DockerMetric
	err = pool.Submit(func() {
		dockerMetric, err = GetDockerMetric()
		if err != nil {
			log.ErrorF("获取Agent的状态出现错误！ 请检查 => %v", err)
			waitResultChan <- "GetDockerMetric error !"
			return
		}
		waitResultChan <- "GetDockerMetric success !"
	})
	if err != nil {
		log.ErrorF("[ReportAgentInfo] - GetDockerMetric exec error  => %v", err)
	}

	for i := 0; i < lenOfAgentMetric; i++ {
		select {
		case result := <-waitResultChan:
			log.DebugF("[ReportAgentInfo] - metric received => %s", result)
		case <-timeout:
			fmt.Println("[ReportAgentInfo] - Timeout! Not all results received.")
			break
		}
	}

	return &AgentInfo{
		CPUInfo:     cpuInfo,
		MemoryInfo:  memoryInfo,
		NetworkInfo: networkInfo,
		DiskInfo:    diskInfoList,
		HostInfo:    hostInfo,
		DockerInfo:  dockerMetric,
	}

}

func ConvertToFormat(eventData float64) string {
	duration := time.Duration(eventData) * time.Second

	fmt.Println(duration)

	hours := int(duration.Hours())
	minutes := int(duration.Minutes()) % 60
	seconds := int(duration.Seconds()) % 60
	milliseconds := duration.Milliseconds() % 1000
	return fmt.Sprintf("%02d:%02d:%02d,%03d", hours, minutes, seconds, milliseconds)
}
