package util

import (
	"cicv-data-closedloop/kinglong/common/log"
	"cicv-data-closedloop/pji/common/cfg"
	"cicv-data-closedloop/pji/common/ent"
	"cicv-data-closedloop/pji/common/global"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"sort"
	"strconv"
	"strings"
	"time"
)

// AppendIfNotExists 向切片中追加元素,如果元素已存在则不添加
func AppendIfNotExists(slice []string, element string) []string {
	for _, item := range slice {
		if item == element {
			return slice // 元素已存在,直接返回原切片
		}
	}
	return append(slice, element) // 元素不存在,追加到切片末尾
}

func AddTimeWindowToTimeWindowProducerQueue(window ent.TimeWindow) {
	global.TimeWindowProducerQueueMutex.RLock()
	{
		global.TimeWindowProducerQueue = append(global.TimeWindowProducerQueue, window)
	}
	global.TimeWindowProducerQueueMutex.RUnlock()
}

func AddTimeWindowToTimeWindowConsumerQueue(window ent.TimeWindow) {
	global.TimeWindowConsumerQueueMutex.RLock()
	{
		global.TimeWindowConsumerQueue = append(global.TimeWindowConsumerQueue, window)
	}
	global.TimeWindowConsumerQueueMutex.RUnlock()
}

func RemoveHeaOfdTimeWindowProducerQueue() {
	global.TimeWindowProducerQueueMutex.RLock()
	{
		global.TimeWindowProducerQueue = global.TimeWindowProducerQueue[1:]
	}
	global.TimeWindowProducerQueueMutex.RUnlock()
}

func RemoveHeaOfdTimeWindowConsumerQueue() {
	global.TimeWindowConsumerQueueMutex.RLock()
	{
		global.TimeWindowConsumerQueue = global.TimeWindowConsumerQueue[1:]
	}
	global.TimeWindowConsumerQueueMutex.RUnlock()
}

func GetBagTime(bagName string) string {
	s1 := strings.Split(bagName, "_")[0]
	s1Split := strings.Split(s1, "/")
	s2 := s1Split[len(s1Split)-1]
	return s2
}

func TimeCustomChange(originalTimeStr string, number int) string {
	var newTimeStr string
	// 解析时间字符串
	layout := "2006-01-02-15-04-05"
	originalTime, err := time.Parse(layout, originalTimeStr)
	if err != nil {
		log.GlobalLogger.Info("无法解析时间字符串:", err)
		return newTimeStr
	}

	// 减少1秒
	newTime := originalTime.Add(time.Duration(number) * time.Second)

	// 格式化新的时间为指定字符串格式
	return newTime.Format(layout)
}

func CalculateDifferenceOfTimeCustom(timeCustom1 string, timeCustom2 string) int {
	timeInt1, _ := strconv.Atoi(strings.Replace(timeCustom1, "-", "", -1))
	timeInt2, _ := strconv.Atoi(strings.Replace(timeCustom2, "-", "", -1))
	return timeInt2 - timeInt1 + 1

}
func TimeCustom1GreaterTimeCustom2(timeCustom1 string, timeCustom2 string) bool {
	timeInt1, _ := strconv.Atoi(strings.Replace(timeCustom1, "-", "", -1))
	timeInt2, _ := strconv.Atoi(strings.Replace(timeCustom2, "-", "", -1))
	return timeInt1 > timeInt2
}

func TimeCustom1GreaterEqualThanTimeCustom2(timeCustom1 string, timeCustom2 string) bool {
	timeInt1, _ := strconv.Atoi(strings.Replace(timeCustom1, "-", "", -1))
	timeInt2, _ := strconv.Atoi(strings.Replace(timeCustom2, "-", "", -1))
	return timeInt1 >= timeInt2
}

func TimeCustom1LessEqualThanTimeCustom2(timeCustom1 string, timeCustom2 string) bool {
	timeInt1, _ := strconv.Atoi(strings.Replace(timeCustom1, "-", "", -1))
	timeInt2, _ := strconv.Atoi(strings.Replace(timeCustom2, "-", "", -1))
	return timeInt1 <= timeInt2
}

func Hex(num int) string {
	return fmt.Sprintf("0x%x", num)
}

// GetDiskUsagePercent 获取磁盘使用率
func GetDiskUsagePercent() float64 {
	// 执行 df 命令获取磁盘使用情况
	cmd := exec.Command("df", "--total")
	output, err := cmd.Output()
	if err != nil {
		log.GlobalLogger.Info("执行命令失败:", err)
		return 0.0
	}

	// 解析 df 命令输出,计算磁盘占比
	lines := strings.Split(string(output), "\n")
	for _, line := range lines[1:] {
		fields := strings.Fields(line)
		if len(fields) >= 6 && fields[0] == "total" {
			//filesystem := fields[0]
			total, _ := strconv.ParseFloat(strings.TrimSuffix(fields[1], "G"), 64)
			used, _ := strconv.ParseFloat(strings.TrimSuffix(fields[2], "G"), 64)
			usedPercent := (used / total) * 100

			//fmt.Printf("文件系统 %s 已使用 %.2f%%\n", filesystem, usedPercent)
			return usedPercent
		}
	}
	return 0.0
}

func ListAbsolutePathAndSort(dir string) []string {
	var result []string
	if !strings.HasSuffix(dir, "/") {
		dir = dir + "/"
	}
	files, err := os.ReadDir(dir)
	if err != nil {
		log.GlobalLogger.Info("获取文件列表失败:", err)
		return result
	}
	for _, file := range files {
		result = append(result, dir+file.Name())
	}

	// 根据文件名进行升序排序
	sort.Slice(result, func(i, j int) bool {
		return filepath.Base(result[i]) < filepath.Base(result[j])
	})
	return result
}

func GetCopyDir(faultTime string) string {
	return cfg.CloudConfig.BagCopyDir + faultTime + "/"
}

func MergeSlice(slice1 []string, slice2 []string) []string {

	// 遍历第二个切片中的元素,并去重追加到结果切片1中
	for _, element := range slice2 {
		found := false
		for _, item := range slice1 {
			if element == item {
				found = true
				break
			}
		}
		if !found {
			slice1 = append(slice1, element)
		}
	}
	return slice1
}

func DeleteFile(path string) {
	// 检查文件是否存在
	if _, err := os.Stat(path); err == nil {
		// 文件存在,执行删除操作
		err := os.Remove(path)
		if err != nil {
			fmt.Printf("删除文件时发生错误:%s\n", err)
			return
		}
	}
}

// GetLastTimeWindow 获取最后一个时间窗口
func GetLastTimeWindow() *ent.TimeWindow {
	var lastTimeWindow *ent.TimeWindow // 获取最后一个时间窗口
	if len(global.TimeWindowProducerQueue) > 0 {
		lastTimeWindow = &global.TimeWindowProducerQueue[len(global.TimeWindowProducerQueue)-1]
	}
	return lastTimeWindow
}

// SupplyCopyBags 如果 Copy目录下的包不够,则补充一些
func SupplyCopyBags(currentTimeWindow ent.TimeWindow) {
	// 如果bag包没有达到length,补充几个
	copyBags, _ := ListAbsolutePathWithSuffixAndSort(GetCopyDir(currentTimeWindow.FaultTime), ".bag")
	copyBagsLength := len(copyBags)
	if copyBagsLength < currentTimeWindow.Length {
		time.Sleep(time.Duration(copyBagsLength) * time.Second)
		dataBags, _ := ListAbsolutePathWithSuffixAndSort(cfg.CloudConfig.BagDataDir, ".bag")
		gap := currentTimeWindow.Length - copyBagsLength
		log.GlobalLogger.Info("故障 ", currentTimeWindow.FaultTime, "需要补充 ", gap, " 个 bag 包")
		for _, bag := range dataBags {
			bagTime := GetBagTime(bag)
			if TimeCustom1GreaterEqualThanTimeCustom2(bagTime, currentTimeWindow.FaultTime) {
				MoveFromDataToCopy(currentTimeWindow.FaultTime, bag)
				gap = gap - 1
				if gap == 0 {
					break
				}
			}
		}
	}
}