package inspection

import (
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"strings"
	"time"

	"dc-inspection/internal/config"
)

// CloudDesktopInspector 云桌面资源巡检器
type CloudDesktopInspector struct {
	cfg *config.CloudDesktopConfig
	client *http.Client
}

// NewCloudDesktopInspector 创建云桌面巡检器
func NewCloudDesktopInspector(cfg *config.CloudDesktopConfig) *CloudDesktopInspector {
	return &CloudDesktopInspector{
		cfg: cfg,
		client: &http.Client{
			Timeout: 30 * time.Second,
		},
	}
}

// DesktopMetrics 云桌面资源指标
type DesktopMetrics struct {
	PoolName    string         `json:"pool_name"`
	DesktopName string         `json:"desktop_name"`
	Host        string         `json:"host"`
	CPUUsage    float64        `json:"cpu_usage"`
	MemoryUsage float64        `json:"memory_usage"`
	DiskUsage   float64        `json:"disk_usage"`
	IOPS        int            `json:"iops"`
	Status      string         `json:"status"`
	SessionCount int           `json:"session_count"`
	Errors      []string       `json:"errors,omitempty"`
}

// PoolMetrics 云桌面池指标
type PoolMetrics struct {
	PoolName        string           `json:"pool_name"`
	TotalDesktops   int              `json:"total_desktops"`
	ActiveDesktops  int              `json:"active_desktops"`
	HealthyDesktops int              `json:"healthy_desktops"`
	AvgCPUUsage     float64          `json:"avg_cpu_usage"`
	AvgMemoryUsage  float64          `json:"avg_memory_usage"`
	AvgDiskUsage    float64          `json:"avg_disk_usage"`
	MaxIOPS         int              `json:"max_iops"`
	Desktops        []DesktopMetrics `json:"desktops"`
	Errors          []string         `json:"errors,omitempty"`
}

// Inspect 执行云桌面资源巡检
func (c *CloudDesktopInspector) Inspect() []*PoolMetrics {
	// 获取云桌面池列表
	pools, err := c.getDesktopPools()
	if err != nil {
		// 如果 API 不可用，返回模拟结构以便后续逻辑继续
		return []*PoolMetrics{
			{
				PoolName: "unknown",
				Errors:   []string{fmt.Sprintf("获取云桌面池列表失败: %v", err)},
			},
		}
	}

	results := make([]*PoolMetrics, 0, len(pools))
	for _, pool := range pools {
		metrics := c.inspectPool(pool)
		results = append(results, metrics)
	}

	return results
}

// getDesktopPools 获取云桌面池列表
func (c *CloudDesktopInspector) getDesktopPools() ([]string, error) {
	url := fmt.Sprintf("%s/api/v1/pools", c.cfg.APIHost)
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return nil, err
	}
	req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", c.cfg.APIKey))
	req.Header.Set("Content-Type", "application/json")

	resp, err := c.client.Do(req)
	if err != nil {
		return nil, fmt.Errorf("请求云桌面 API 失败: %w", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		body, _ := io.ReadAll(resp.Body)
		return nil, fmt.Errorf("API 返回 %d: %s", resp.StatusCode, string(body))
	}

	var apiResp struct {
		Pools []struct {
			Name string `json:"name"`
		} `json:"pools"`
	}
	if err := json.NewDecoder(resp.Body).Decode(&apiResp); err != nil {
		return nil, fmt.Errorf("解析响应失败: %w", err)
	}

	pools := make([]string, 0, len(apiResp.Pools))
	for _, p := range apiResp.Pools {
		pools = append(pools, p.Name)
	}

	// 如果没有池，返回默认池名
	if len(pools) == 0 {
		pools = []string{"default"}
	}

	return pools, nil
}

// inspectPool 巡检单个云桌面池
func (c *CloudDesktopInspector) inspectPool(poolName string) *PoolMetrics {
	metrics := &PoolMetrics{
		PoolName: poolName,
	}

	// 获取池内桌面资源指标
	desktops, err := c.getPoolDesktops(poolName)
	if err != nil {
		metrics.Desktops = []DesktopMetrics{
			{Errors: []string{fmt.Sprintf("获取桌面列表失败: %v", err)}},
		}
		return metrics
	}

	metrics.TotalDesktops = len(desktops)
	var totalCPU, totalMem, totalDisk float64
	maxIOPS := 0

	for _, d := range desktops {
		if d.Status == "running" || d.Status == "active" {
			metrics.ActiveDesktops++
		}
		if d.CPUUsage <= c.cfg.CPUThreshold &&
			d.MemoryUsage <= c.cfg.MemThreshold &&
			d.DiskUsage <= c.cfg.DiskThreshold {
			metrics.HealthyDesktops++
		}
		totalCPU += d.CPUUsage
		totalMem += d.MemoryUsage
		totalDisk += d.DiskUsage
		if d.IOPS > maxIOPS {
			maxIOPS = d.IOPS
		}
	}

	if metrics.TotalDesktops > 0 {
		metrics.AvgCPUUsage = totalCPU / float64(metrics.TotalDesktops)
		metrics.AvgMemoryUsage = totalMem / float64(metrics.TotalDesktops)
		metrics.AvgDiskUsage = totalDisk / float64(metrics.TotalDesktops)
	}
	metrics.MaxIOPS = maxIOPS
	metrics.Desktops = desktops

	return metrics
}

// getPoolDesktops 获取池内桌面资源指标
func (c *CloudDesktopInspector) getPoolDesktops(poolName string) ([]DesktopMetrics, error) {
	url := fmt.Sprintf("%s/api/v1/pools/%s/desktops/metrics", c.cfg.APIHost, poolName)
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return nil, err
	}
	req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", c.cfg.APIKey))
	req.Header.Set("Content-Type", "application/json")

	resp, err := c.client.Do(req)
	if err != nil {
		return nil, fmt.Errorf("请求桌面指标失败: %w", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		body, _ := io.ReadAll(resp.Body)
		return nil, fmt.Errorf("API 返回 %d: %s", resp.StatusCode, string(body))
	}

	var apiResp struct {
		Desktops []struct {
			Name     string  `json:"name"`
			Host     string  `json:"host"`
			CPU      float64 `json:"cpu_usage"`
			Memory   float64 `json:"memory_usage"`
			Disk     float64 `json:"disk_usage"`
			IOPS     int     `json:"iops"`
			Status   string  `json:"status"`
			Sessions int     `json:"session_count"`
		} `json:"desktops"`
	}
	if err := json.NewDecoder(resp.Body).Decode(&apiResp); err != nil {
		return nil, fmt.Errorf("解析响应失败: %w", err)
	}

	desktops := make([]DesktopMetrics, 0, len(apiResp.Desktops))
	for _, d := range apiResp.Desktops {
		desktops = append(desktops, DesktopMetrics{
			DesktopName:  d.Name,
			Host:         d.Host,
			CPUUsage:     d.CPU,
			MemoryUsage:  d.Memory,
			DiskUsage:    d.Disk,
			IOPS:         d.IOPS,
			Status:       d.Status,
			SessionCount: d.Sessions,
		})
	}

	return desktops, nil
}

// CheckThresholds 检查云桌面资源阈值
func (c *CloudDesktopInspector) CheckThresholds(metrics *PoolMetrics) []string {
	var alerts []string

	for _, d := range metrics.Desktops {
		if len(d.Errors) > 0 {
			alerts = append(alerts, fmt.Sprintf("桌面 %s 异常: %s", d.DesktopName, strings.Join(d.Errors, "; ")))
			continue
		}

		if d.CPUUsage > c.cfg.CPUThreshold {
			alerts = append(alerts, fmt.Sprintf("桌面 %s CPU 使用率 %.1f%% 超过阈值 %.1f%%",
				d.DesktopName, d.CPUUsage, c.cfg.CPUThreshold))
		}
		if d.MemoryUsage > c.cfg.MemThreshold {
			alerts = append(alerts, fmt.Sprintf("桌面 %s 内存使用率 %.1f%% 超过阈值 %.1f%%",
				d.DesktopName, d.MemoryUsage, c.cfg.MemThreshold))
		}
		if d.DiskUsage > c.cfg.DiskThreshold {
			alerts = append(alerts, fmt.Sprintf("桌面 %s 磁盘使用率 %.1f%% 超过阈值 %.1f%%",
				d.DesktopName, d.DiskUsage, c.cfg.DiskThreshold))
		}
		if d.IOPS > c.cfg.IOPSThreshold {
			alerts = append(alerts, fmt.Sprintf("桌面 %s IOPS %d 超过阈值 %d",
				d.DesktopName, d.IOPS, c.cfg.IOPSThreshold))
		}
		if d.Status == "error" || d.Status == "stopped" {
			alerts = append(alerts, fmt.Sprintf("桌面 %s 状态异常: %s", d.DesktopName, d.Status))
		}
	}

	// 池整体检查
	if metrics.TotalDesktops > 0 && metrics.HealthyDesktops < metrics.TotalDesktops/2 {
		alerts = append(alerts, fmt.Sprintf("桌面池 %s 健康桌面数 %d/%d，健康率低于 50%%",
			metrics.PoolName, metrics.HealthyDesktops, metrics.TotalDesktops))
	}

	return alerts
}

// ToRecord 将巡检指标转换为数据库记录
func (c *CloudDesktopInspector) ToRecord(metrics *PoolMetrics) *Record {
	status := "ok"
	alerts := c.CheckThresholds(metrics)

	for _, d := range metrics.Desktops {
		if len(d.Errors) > 0 {
			status = "error"
			break
		}
	}
	if status != "error" && len(alerts) > 0 {
		status = "warning"
	}

	metricsJSON, _ := json.Marshal(metrics)

	return &Record{
		InspectionType: "cloud_desktop",
		Target:         metrics.PoolName,
		Status:         status,
		Metrics:        string(metricsJSON),
		Message:        strings.Join(alerts, "\n"),
		InspectedAt:    time.Now(),
	}
}
