package docker

import (
	"context"
	"encoding/json"
	"fmt"
	"github.com/docker/docker/api/types/container"
	"time"
)

// ContainerStats 容器统计数据结构
type ContainerStats struct {
	CPUPercentage    float64 `json:"cpu_percent"`    // CPU 使用百分比
	MemoryUsage      int64   `json:"memory_usage"`   // 内存使用量（字节）
	MemoryLimit      int64   `json:"memory_limit"`   // 内存限制（字节）
	MemoryPercentage float64 `json:"memory_percent"` // 内存使用百分比
	NetworkRx        int64   `json:"network_rx"`     // 网络接收（字节）
	NetworkTx        int64   `json:"network_tx"`     // 网络发送（字节）
	BlockRead        int64   `json:"block_read"`     // 块设备读取（字节）
	BlockWrite       int64   `json:"block_write"`    // 块设备写入（字节）
	PID              int     `json:"pid"`            // 进程ID
	Status           string  `json:"status"`         // 容器状态
	Uptime           string  `json:"uptime"`         // 运行时间
}

// GetStats 获取容器的实时统计数据
func GetStats(ctx context.Context, containerID string) (*ContainerStats, error) {
	if containerID == "" {
		return nil, fmt.Errorf("容器ID不能为空")
	}

	cli := GetClient()
	if cli == nil {
		return nil, fmt.Errorf("Docker客户端未初始化")
	}

	// 获取容器详细信息
	inspect, err := cli.ContainerInspect(ctx, containerID)
	if err != nil {
		return nil, fmt.Errorf("无法获取容器信息: %w", err)
	}

	// 获取容器状态
	status := "stopped"
	if inspect.State.Running {
		status = "running"
	} else if inspect.State.Paused {
		status = "paused"
	} else if inspect.State.Restarting {
		status = "restarting"
	}

	// 计算运行时间
	uptime := "0s"
	if inspect.State.Running && inspect.State.StartedAt != "" {
		startTime, err := time.Parse(time.RFC3339, inspect.State.StartedAt)
		if err == nil {
			duration := time.Since(startTime)
			uptime = formatDuration(duration)
		}
	}

	// 如果容器未运行，返回基本信息
	if !inspect.State.Running {
		return &ContainerStats{
			Status: status,
			Uptime: uptime,
			PID:    inspect.State.Pid,
		}, nil
	}

	// 获取容器实时统计数据
	stats, err := cli.ContainerStats(ctx, containerID, false) // 不需要持续流式数据
	if err != nil {
		return nil, fmt.Errorf("获取容器统计数据失败: %w", err)
	}
	defer stats.Body.Close()

	// 解析统计数据JSON
	var statsJSON container.StatsResponse
	if err := json.NewDecoder(stats.Body).Decode(&statsJSON); err != nil {
		return nil, fmt.Errorf("解析容器统计数据失败: %w", err)
	}

	result := &ContainerStats{
		Status: status,
		Uptime: uptime,
		PID:    inspect.State.Pid,
	}

	// 计算CPU使用百分比
	result.CPUPercentage = calculateCPUPercentage(&statsJSON)

	// 设置内存使用情况
	result.MemoryUsage = getMemoryUsage(&statsJSON)
	result.MemoryLimit = getMemoryLimit(&statsJSON)
	result.MemoryPercentage = calculateMemoryPercentage(&statsJSON)

	// 获取网络数据
	networkStats := getNetworkStats(&statsJSON)
	result.NetworkRx = networkStats.rx
	result.NetworkTx = networkStats.tx

	// 获取I/O数据
	ioStats := getIOStats(&statsJSON)
	result.BlockRead = ioStats.read
	result.BlockWrite = ioStats.write

	return result, nil
}

// 计算CPU使用百分比
func calculateCPUPercentage(stats *container.StatsResponse) float64 {
	if stats == nil {
		return 0.0
	}

	// CPU使用率计算公式 = (CPU使用时间 / CPU总时间) * 核心数 * 100%
	cpuDelta := float64(stats.CPUStats.CPUUsage.TotalUsage) - float64(stats.PreCPUStats.CPUUsage.TotalUsage)
	systemDelta := float64(stats.CPUStats.SystemUsage) - float64(stats.PreCPUStats.SystemUsage)

	numCPUs := uint32(1) // 默认为1个CPU
	if len(stats.CPUStats.CPUUsage.PercpuUsage) > 0 {
		numCPUs = uint32(len(stats.CPUStats.CPUUsage.PercpuUsage))
	}

	if systemDelta > 0 && cpuDelta > 0 {
		cpuPercent := (cpuDelta / systemDelta) * float64(numCPUs) * 100.0
		return roundToTwo(cpuPercent)
	}
	return 0.0
}

// 获取内存使用量
func getMemoryUsage(stats *container.StatsResponse) int64 {
	if stats == nil || stats.MemoryStats.Usage == 0 {
		return 0
	}
	// 某些环境下，需要减去缓存
	if stats.MemoryStats.Stats != nil {
		if cache, ok := stats.MemoryStats.Stats["cache"]; ok {
			return int64(stats.MemoryStats.Usage - cache) // 转换为int64
		}
	}
	return int64(stats.MemoryStats.Usage) // 转换为int64
}

// 获取内存限制
func getMemoryLimit(stats *container.StatsResponse) int64 {
	if stats == nil || stats.MemoryStats.Limit == 0 {
		return 0
	}
	return int64(stats.MemoryStats.Limit) // 转换为int64
}

// 计算内存使用百分比
func calculateMemoryPercentage(stats *container.StatsResponse) float64 {
	if stats == nil {
		return 0.0
	}

	usage := getMemoryUsage(stats)
	limit := getMemoryLimit(stats)

	if limit > 0 && usage > 0 {
		memPercent := float64(usage) / float64(limit) * 100.0
		return roundToTwo(memPercent)
	}
	return 0.0
}

// 网络统计结构
type networkStats struct {
	rx int64
	tx int64
}

// 获取网络统计数据
func getNetworkStats(stats *container.StatsResponse) networkStats {
	if stats == nil || len(stats.Networks) == 0 {
		return networkStats{}
	}

	var rx, tx int64
	for _, network := range stats.Networks {
		rx += int64(network.RxBytes) // 转换为int64
		tx += int64(network.TxBytes) // 转换为int64
	}

	return networkStats{rx: rx, tx: tx}
}

// IO统计结构
type ioStats struct {
	read  int64
	write int64
}

// 获取IO统计数据
func getIOStats(stats *container.StatsResponse) ioStats {
	if stats == nil {
		return ioStats{}
	}

	var read, write int64
	if len(stats.BlkioStats.IoServiceBytesRecursive) > 0 {
		for _, blkio := range stats.BlkioStats.IoServiceBytesRecursive {
			switch blkio.Op {
			case "Read":
				read += int64(blkio.Value) // 转换为int64
			case "Write":
				write += int64(blkio.Value) // 转换为int64
			}
		}
	}

	return ioStats{read: read, write: write}
}

// 四舍五入到两位小数
func roundToTwo(num float64) float64 {
	if num < 0 {
		return 0.0 // 避免负值
	}
	return float64(int(num*100)) / 100
}

// 格式化时间持续
func formatDuration(d time.Duration) string {
	if d < 0 {
		d = 0 // 避免负值
	}

	days := int(d.Hours() / 24)
	hours := int(d.Hours()) % 24
	minutes := int(d.Minutes()) % 60
	seconds := int(d.Seconds()) % 60

	if days > 0 {
		return fmt.Sprintf("%dd %dh %dm", days, hours, minutes)
	}
	if hours > 0 {
		return fmt.Sprintf("%dh %dm", hours, minutes)
	}
	if minutes > 0 {
		return fmt.Sprintf("%dm %ds", minutes, seconds)
	}
	return fmt.Sprintf("%ds", seconds)
}
